/* Set an IDT entry. If the entry is part of the current IDT, then also update Xen. */ static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g) { unsigned long p = (unsigned long)&dt[entrynum]; unsigned long start, end; preempt_disable(); start = (unsigned long)__get_cpu_var(idt_desc).address; end = start + __get_cpu_var(idt_desc).size + 1; xen_mc_flush(); native_write_idt_entry(dt, entrynum, g); if (p >= start && (p + 8) <= end) { struct trap_info info[2]; info[1].address = 0; if (cvt_gate_to_trap(entrynum, g, &info[0])) if (HYPERVISOR_set_trap_table(info)) BUG(); } preempt_enable(); }
/*G:034 * The Interrupt Descriptor Table (IDT). * * The IDT tells the processor what to do when an interrupt comes in. Each * entry in the table is a 64-bit descriptor: this holds the privilege level, * address of the handler, and... well, who cares? The Guest just asks the * Host to make the change anyway, because the Host controls the real IDT. */ static void lguest_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g) { /* The gate_desc structure is 8 bytes long: we hand it to the Host in * two 32-bit chunks. The whole 32-bit kernel used to hand descriptors * around like this; typesafety wasn't a big concern in Linux's early * years. */ u32 *desc = (u32 *)g; /* Keep the local copy up to date. */ native_write_idt_entry(dt, entrynum, g); /* Tell Host about this new entry. */ hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]); }