Something very odd is happening when I try to add new entries to
idt_table in 2.4 on x86 (well, 2.3.99-pre6): immediately after I
add them, they are present but by the time the system has finished
booting, they've vanished.
In arch/i386/kernel/traps.c, after the line
set_system_gate(SYSCALL_VECTOR,&system_call);
I add
set_system_gate(HYPERCALL_VECTOR,&hyper_call);
set_system_gate(RET_TO_USER_VECTOR,&return_to_usermode);
(with surrounding printk statements both sides of each line for
debugging). When I boot I see
Old idt_table[SYSCALL_VECTOR] = (0x100210, 0xf0108e00)
New idt_table[SYSCALL_VECTOR] = (0x1096d0, 0xf010ef00)
Initialising SILK system gates
Old idt_table[HYPERCALL_VECTOR] = (0x100210, 0xf0108e00)
New idt_table[HYPERCALL_VECTOR] = (0x109870, 0xf010ef00)
Old idt_table[RET_TO_USER_VECTOR] = (0x100210, 0xf0108e00)
New idt_table[RET_TO_USER_VECTOR] = (0x109910, 0xf010ef00)
and the symbol addresses match up correctly. But when the system
has finished booting, my two additions have been silently replaced
with 0x100000 like the other uninitialised vectors:
# gdb vmlinux.hyper8 /proc/kcore
(gdb) p idt_table
b = 0xf01e8e00}, {a = 0x101900, b = 0xf01e8e00}, {a = 0x100000,
b = 0x8e00} <repeats 80 times>, {a = 0x1096d0, b = 0xf010ef00}, {
a = 0x100000, b = 0x8e00} <repeats 127 times>}
where 0x1096d0 is the (physical) address of system_call and my
vectors have "vanished". The same happens whether I use 0x85 and
0x86 or 0x70 and 0x71 for my vectors so my first thought that
something messing with the page tables mapping between real mode
and protected mode (such as in trap_init_f00f_bug) doesn't seem to
hold water.
Once the system is booted, I can rewrite the new entries into
idt_table, and everything works fine. Behold:
# cat fixtraps.c
...
MODULE_PARM(idt_table_addr,"i");
MODULE_PARM(hyper_call_addr,"i");
MODULE_PARM(return_to_usermode_addr,"i");
...
int init_module(void)
{
idt_t *idt = (idt_t *)idt_table_addr;
...
idt[HYPERCALL_VECTOR].a = (unsigned long)hyper_call_addr;
idt[HYPERCALL_VECTOR].b = idt[0x80].b;
idt[RET_TO_USER_VECTOR].a = (unsigned long)return_to_usermode_addr;
idt[RET_TO_USER_VECTOR].b = idt[0x80].b;
...
# insmod fixtraps.o idt_table_addr=0xf0268000 hyper_call_addr=0x109870 return_to_usermode_addr=0x109910
# gdb vmlinux.hyper8 /proc/kcore
(gdb) p/x idt_table[0x70]
$2 = {a = 0x109870, b = 0xf010ef00}
(gdb) p/x idt_table[0x71]
$3 = {a = 0x109910, b = 0xf010ef00}
And, indeed, int $0x70 and int 0x71 work fine to trap to the new
vectors.
What the heck is going on to stop the original initialisation from
sticking? I can't find anything which special-cases or reinitialises
the idt_table other than the first initialisation in head.S, the
setting with set_system_gate in trap_init in traps.c and the f00f
fudge in trap_init_f00f_bug in traps.c.
Can anyone please explain?
Thanks,
--Malcolm
-- Malcolm Beattie <mbeattie@sable.ox.ac.uk> Unix Systems Programmer Oxford University Computing Services- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Jul 23 2000 - 21:00:11 EST