summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/lguest.h7
-rw-r--r--arch/x86/lguest/boot.c3
-rw-r--r--arch/x86/lguest/head_32.S15
-rw-r--r--drivers/lguest/hypercalls.c5
-rw-r--r--drivers/lguest/interrupts_and_traps.c8
-rw-r--r--drivers/lguest/lg.h2
-rw-r--r--include/linux/lguest.h4
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 */
21extern unsigned long default_idt_entries[]; 21extern 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 */
24extern char lguest_noirq_start[], lguest_noirq_end[]; 24extern char lguest_noirq_iret[];
25extern const char lgstart_cli[], lgend_cli[]; 25extern const char lgstart_cli[], lgend_cli[];
26extern const char lgstart_sti[], lgend_sti[];
27extern const char lgstart_popf[], lgend_popf[];
28extern const char lgstart_pushf[], lgend_pushf[]; 26extern const char lgstart_pushf[], lgend_pushf[];
29extern const char lgstart_iret[], lgend_iret[];
30 27
31extern void lguest_iret(void); 28extern void lguest_iret(void);
32extern void lguest_init(void); 29extern 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
88struct lguest_data lguest_data = { 88struct 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 */
184ENTRY(lguest_iret) 182ENTRY(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
193lguest_noirq_start: 191lguest_noirq_iret:
194 iret 192 iret
195lguest_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). */