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