Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lguest: suppress interrupts for single insn, not range.

The last patch reduced our interrupt-suppression region to one address,
so simplify the code somewhat.

Also, remove the obsolete undefined instruction ranges and the comment
which refers to lguest_guest.S instead of head_32.S.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

+18 -26
+2 -5
arch/x86/include/asm/lguest.h
··· 20 20 /* Found in switcher.S */ 21 21 extern unsigned long default_idt_entries[]; 22 22 23 - /* Declarations for definitions in lguest_guest.S */ 24 - extern char lguest_noirq_start[], lguest_noirq_end[]; 23 + /* Declarations for definitions in arch/x86/lguest/head_32.S */ 24 + extern char lguest_noirq_iret[]; 25 25 extern const char lgstart_cli[], lgend_cli[]; 26 - extern const char lgstart_sti[], lgend_sti[]; 27 - extern const char lgstart_popf[], lgend_popf[]; 28 26 extern const char lgstart_pushf[], lgend_pushf[]; 29 - extern const char lgstart_iret[], lgend_iret[]; 30 27 31 28 extern void lguest_iret(void); 32 29 extern void lguest_init(void);
+1 -2
arch/x86/lguest/boot.c
··· 87 87 88 88 struct lguest_data lguest_data = { 89 89 .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF }, 90 - .noirq_start = (u32)lguest_noirq_start, 91 - .noirq_end = (u32)lguest_noirq_end, 90 + .noirq_iret = (u32)lguest_noirq_iret, 92 91 .kernel_address = PAGE_OFFSET, 93 92 .blocked_interrupts = { 1 }, /* Block timer interrupts */ 94 93 .syscall_vec = SYSCALL_VECTOR,
+6 -9
arch/x86/lguest/head_32.S
··· 133 133 ret 134 134 /*:*/ 135 135 136 - /* These demark the EIP range where host should never deliver interrupts. */ 137 - .global lguest_noirq_start 138 - .global lguest_noirq_end 136 + /* These demark the EIP where host should never deliver interrupts. */ 137 + .global lguest_noirq_iret 139 138 140 139 /*M:004 141 140 * When the Host reflects a trap or injects an interrupt into the Guest, it ··· 173 174 * 174 175 * The second is harder: copying eflags to lguest_data.irq_enabled will turn 175 176 * interrupts on before we're finished, so we could be interrupted before we 176 - * return to userspace or wherever. Our solution to this is to surround the 177 - * code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the 177 + * return to userspace or wherever. Our solution to this is to tell the 178 178 * Host that it is *never* to interrupt us there, even if interrupts seem to be 179 179 * enabled. (It's not necessary to protect pop instruction, since 180 - * data gets updated only after it completes, so we end up surrounding 181 - * just one instruction, iret). 180 + * data gets updated only after it completes, so we only need to protect 181 + * one instruction, iret). 182 182 */ 183 183 ENTRY(lguest_iret) 184 184 pushl 2*4(%esp) ··· 188 190 * prefix makes sure we use the stack segment, which is still valid. 189 191 */ 190 192 popl %ss:lguest_data+LGUEST_DATA_irq_enabled 191 - lguest_noirq_start: 193 + lguest_noirq_iret: 192 194 iret 193 - lguest_noirq_end:
+2 -3
drivers/lguest/hypercalls.c
··· 211 211 212 212 /* 213 213 * The Guest tells us where we're not to deliver interrupts by putting 214 - * the range of addresses into "struct lguest_data". 214 + * the instruction address into "struct lguest_data". 215 215 */ 216 - if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start) 217 - || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end)) 216 + if (get_user(cpu->lg->noirq_iret, &cpu->lg->lguest_data->noirq_iret)) 218 217 kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data); 219 218 220 219 /*
+4 -4
drivers/lguest/interrupts_and_traps.c
··· 204 204 * They may be in the middle of an iret, where they asked us never to 205 205 * deliver interrupts. 206 206 */ 207 - if (cpu->regs->eip >= cpu->lg->noirq_start && 208 - (cpu->regs->eip < cpu->lg->noirq_end)) 207 + if (cpu->regs->eip == cpu->lg->noirq_iret) 209 208 return; 210 209 211 210 /* If they're halted, interrupts restart them. */ ··· 394 395 * The Guest has the ability to turn its interrupt gates into trap gates, 395 396 * if it is careful. The Host will let trap gates can go directly to the 396 397 * Guest, but the Guest needs the interrupts atomically disabled for an 397 - * interrupt gate. It can do this by pointing the trap gate at instructions 398 - * within noirq_start and noirq_end, where it can safely disable interrupts. 398 + * interrupt gate. The Host could provide a mechanism to register more 399 + * "no-interrupt" regions, and the Guest could point the trap gate at 400 + * instructions within that region, where it can safely disable interrupts. 399 401 */ 400 402 401 403 /*M:006
+1 -1
drivers/lguest/lg.h
··· 102 102 103 103 struct pgdir pgdirs[4]; 104 104 105 - unsigned long noirq_start, noirq_end; 105 + unsigned long noirq_iret; 106 106 107 107 unsigned int stack_pages; 108 108 u32 tsc_khz;
+2 -2
include/linux/lguest.h
··· 61 61 u32 tsc_khz; 62 62 63 63 /* Fields initialized by the Guest at boot: */ 64 - /* Instruction range to suppress interrupts even if enabled */ 65 - unsigned long noirq_start, noirq_end; 64 + /* Instruction to suppress interrupts even if enabled */ 65 + unsigned long noirq_iret; 66 66 /* Address above which page tables are all identical. */ 67 67 unsigned long kernel_address; 68 68 /* The vector to try to use for system calls (0x40 or 0x80). */