diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 13:55:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 13:55:06 -0400 |
commit | b9bb6fb73b3e112d241a5edd146740be9a0c3cc0 (patch) | |
tree | d65072d0371468d685b7464dc6b38f920c0c9666 /drivers/lguest | |
parent | 15ce2658ddbd3db20dfba3622f3d224f01837fdc (diff) | |
parent | 9abbfb486f5c254805bb6a3f263bc14d989eb90b (diff) |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio updates from Rusty Russell:
"Some virtio internal cleanups, a new virtio device "virtio input", and
a change to allow the legacy virtio balloon.
Most excitingly, some lguest work! No seriously, I got some cleanup
patches"
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio: drop virtio_device_is_legacy_only
virtio_pci: support non-legacy balloon devices
virtio_mmio: support non-legacy balloon devices
virtio_ccw: support non-legacy balloon devices
virtio: balloon might not be a legacy device
virtio_balloon: transitional interface
virtio_ring: Update weak barriers to use dma_wmb/rmb
virtio_pci_modern: switch to type-safe io accessors
virtio_pci_modern: type-safe io accessors
lguest: handle traps on the "interrupt suppressed" iret instruction.
virtio: drop a useless config read
virtio_config: reorder functions
Add virtio-input driver.
lguest: suppress interrupts for single insn, not range.
lguest: simplify lguest_iret
lguest: rename i386_head.S in the comments
lguest: explicitly set miscdevice's private_data NULL
lguest: fix pending interrupt test.
Diffstat (limited to 'drivers/lguest')
-rw-r--r-- | drivers/lguest/hypercalls.c | 5 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 105 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 2 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 8 |
4 files changed, 86 insertions, 34 deletions
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..5e7559be222a 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c | |||
@@ -56,21 +56,16 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | /*H:210 | 58 | /*H:210 |
59 | * The set_guest_interrupt() routine actually delivers the interrupt or | 59 | * The push_guest_interrupt_stack() routine saves Guest state on the stack for |
60 | * trap. The mechanics of delivering traps and interrupts to the Guest are the | 60 | * an interrupt or trap. The mechanics of delivering traps and interrupts to |
61 | * same, except some traps have an "error code" which gets pushed onto the | 61 | * the Guest are the same, except some traps have an "error code" which gets |
62 | * stack as well: the caller tells us if this is one. | 62 | * pushed onto the stack as well: the caller tells us if this is one. |
63 | * | ||
64 | * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this | ||
65 | * interrupt or trap. It's split into two parts for traditional reasons: gcc | ||
66 | * on i386 used to be frightened by 64 bit numbers. | ||
67 | * | 63 | * |
68 | * We set up the stack just like the CPU does for a real interrupt, so it's | 64 | * We set up the stack just like the CPU does for a real interrupt, so it's |
69 | * identical for the Guest (and the standard "iret" instruction will undo | 65 | * identical for the Guest (and the standard "iret" instruction will undo |
70 | * it). | 66 | * it). |
71 | */ | 67 | */ |
72 | static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, | 68 | static void push_guest_interrupt_stack(struct lg_cpu *cpu, bool has_err) |
73 | bool has_err) | ||
74 | { | 69 | { |
75 | unsigned long gstack, origstack; | 70 | unsigned long gstack, origstack; |
76 | u32 eflags, ss, irq_enable; | 71 | u32 eflags, ss, irq_enable; |
@@ -130,12 +125,28 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, | |||
130 | if (has_err) | 125 | if (has_err) |
131 | push_guest_stack(cpu, &gstack, cpu->regs->errcode); | 126 | push_guest_stack(cpu, &gstack, cpu->regs->errcode); |
132 | 127 | ||
133 | /* | 128 | /* Adjust the stack pointer and stack segment. */ |
134 | * Now we've pushed all the old state, we change the stack, the code | ||
135 | * segment and the address to execute. | ||
136 | */ | ||
137 | cpu->regs->ss = ss; | 129 | cpu->regs->ss = ss; |
138 | cpu->regs->esp = virtstack + (gstack - origstack); | 130 | cpu->regs->esp = virtstack + (gstack - origstack); |
131 | } | ||
132 | |||
133 | /* | ||
134 | * This actually makes the Guest start executing the given interrupt/trap | ||
135 | * handler. | ||
136 | * | ||
137 | * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this | ||
138 | * interrupt or trap. It's split into two parts for traditional reasons: gcc | ||
139 | * on i386 used to be frightened by 64 bit numbers. | ||
140 | */ | ||
141 | static void guest_run_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi) | ||
142 | { | ||
143 | /* If we're already in the kernel, we don't change stacks. */ | ||
144 | if ((cpu->regs->ss&0x3) != GUEST_PL) | ||
145 | cpu->regs->ss = cpu->esp1; | ||
146 | |||
147 | /* | ||
148 | * Set the code segment and the address to execute. | ||
149 | */ | ||
139 | cpu->regs->cs = (__KERNEL_CS|GUEST_PL); | 150 | cpu->regs->cs = (__KERNEL_CS|GUEST_PL); |
140 | cpu->regs->eip = idt_address(lo, hi); | 151 | cpu->regs->eip = idt_address(lo, hi); |
141 | 152 | ||
@@ -158,6 +169,24 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, | |||
158 | kill_guest(cpu, "Disabling interrupts"); | 169 | kill_guest(cpu, "Disabling interrupts"); |
159 | } | 170 | } |
160 | 171 | ||
172 | /* This restores the eflags word which was pushed on the stack by a trap */ | ||
173 | static void restore_eflags(struct lg_cpu *cpu) | ||
174 | { | ||
175 | /* This is the physical address of the stack. */ | ||
176 | unsigned long stack_pa = guest_pa(cpu, cpu->regs->esp); | ||
177 | |||
178 | /* | ||
179 | * Stack looks like this: | ||
180 | * Address Contents | ||
181 | * esp EIP | ||
182 | * esp + 4 CS | ||
183 | * esp + 8 EFLAGS | ||
184 | */ | ||
185 | cpu->regs->eflags = lgread(cpu, stack_pa + 8, u32); | ||
186 | cpu->regs->eflags &= | ||
187 | ~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT); | ||
188 | } | ||
189 | |||
161 | /*H:205 | 190 | /*H:205 |
162 | * Virtual Interrupts. | 191 | * Virtual Interrupts. |
163 | * | 192 | * |
@@ -200,14 +229,6 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more) | |||
200 | 229 | ||
201 | BUG_ON(irq >= LGUEST_IRQS); | 230 | BUG_ON(irq >= LGUEST_IRQS); |
202 | 231 | ||
203 | /* | ||
204 | * They may be in the middle of an iret, where they asked us never to | ||
205 | * deliver interrupts. | ||
206 | */ | ||
207 | if (cpu->regs->eip >= cpu->lg->noirq_start && | ||
208 | (cpu->regs->eip < cpu->lg->noirq_end)) | ||
209 | return; | ||
210 | |||
211 | /* If they're halted, interrupts restart them. */ | 232 | /* If they're halted, interrupts restart them. */ |
212 | if (cpu->halted) { | 233 | if (cpu->halted) { |
213 | /* Re-enable interrupts. */ | 234 | /* Re-enable interrupts. */ |
@@ -237,12 +258,34 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more) | |||
237 | if (idt_present(idt->a, idt->b)) { | 258 | if (idt_present(idt->a, idt->b)) { |
238 | /* OK, mark it no longer pending and deliver it. */ | 259 | /* OK, mark it no longer pending and deliver it. */ |
239 | clear_bit(irq, cpu->irqs_pending); | 260 | clear_bit(irq, cpu->irqs_pending); |
261 | |||
240 | /* | 262 | /* |
241 | * set_guest_interrupt() takes the interrupt descriptor and a | 263 | * They may be about to iret, where they asked us never to |
242 | * flag to say whether this interrupt pushes an error code onto | 264 | * deliver interrupts. In this case, we can emulate that iret |
243 | * the stack as well: virtual interrupts never do. | 265 | * then immediately deliver the interrupt. This is basically |
266 | * a noop: the iret would pop the interrupt frame and restore | ||
267 | * eflags, and then we'd set it up again. So just restore the | ||
268 | * eflags word and jump straight to the handler in this case. | ||
269 | * | ||
270 | * Denys Vlasenko points out that this isn't quite right: if | ||
271 | * the iret was returning to userspace, then that interrupt | ||
272 | * would reset the stack pointer (which the Guest told us | ||
273 | * about via LHCALL_SET_STACK). But unless the Guest is being | ||
274 | * *really* weird, that will be the same as the current stack | ||
275 | * anyway. | ||
244 | */ | 276 | */ |
245 | set_guest_interrupt(cpu, idt->a, idt->b, false); | 277 | if (cpu->regs->eip == cpu->lg->noirq_iret) { |
278 | restore_eflags(cpu); | ||
279 | } else { | ||
280 | /* | ||
281 | * set_guest_interrupt() takes a flag to say whether | ||
282 | * this interrupt pushes an error code onto the stack | ||
283 | * as well: virtual interrupts never do. | ||
284 | */ | ||
285 | push_guest_interrupt_stack(cpu, false); | ||
286 | } | ||
287 | /* Actually make Guest cpu jump to handler. */ | ||
288 | guest_run_interrupt(cpu, idt->a, idt->b); | ||
246 | } | 289 | } |
247 | 290 | ||
248 | /* | 291 | /* |
@@ -353,8 +396,9 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num) | |||
353 | */ | 396 | */ |
354 | if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b)) | 397 | if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b)) |
355 | return false; | 398 | return false; |
356 | set_guest_interrupt(cpu, cpu->arch.idt[num].a, | 399 | push_guest_interrupt_stack(cpu, has_err(num)); |
357 | cpu->arch.idt[num].b, has_err(num)); | 400 | guest_run_interrupt(cpu, cpu->arch.idt[num].a, |
401 | cpu->arch.idt[num].b); | ||
358 | return true; | 402 | return true; |
359 | } | 403 | } |
360 | 404 | ||
@@ -395,8 +439,9 @@ static bool direct_trap(unsigned int num) | |||
395 | * The Guest has the ability to turn its interrupt gates into trap gates, | 439 | * 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 | 440 | * 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 | 441 | * 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 | 442 | * interrupt gate. The Host could provide a mechanism to register more |
399 | * within noirq_start and noirq_end, where it can safely disable interrupts. | 443 | * "no-interrupt" regions, and the Guest could point the trap gate at |
444 | * instructions within that region, where it can safely disable interrupts. | ||
400 | */ | 445 | */ |
401 | 446 | ||
402 | /*M:006 | 447 | /*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/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index c4c6113eb9a6..30c60687d277 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
@@ -339,6 +339,13 @@ static ssize_t write(struct file *file, const char __user *in, | |||
339 | } | 339 | } |
340 | } | 340 | } |
341 | 341 | ||
342 | static int open(struct inode *inode, struct file *file) | ||
343 | { | ||
344 | file->private_data = NULL; | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
342 | /*L:060 | 349 | /*L:060 |
343 | * The final piece of interface code is the close() routine. It reverses | 350 | * The final piece of interface code is the close() routine. It reverses |
344 | * everything done in initialize(). This is usually called because the | 351 | * everything done in initialize(). This is usually called because the |
@@ -409,6 +416,7 @@ static int close(struct inode *inode, struct file *file) | |||
409 | */ | 416 | */ |
410 | static const struct file_operations lguest_fops = { | 417 | static const struct file_operations lguest_fops = { |
411 | .owner = THIS_MODULE, | 418 | .owner = THIS_MODULE, |
419 | .open = open, | ||
412 | .release = close, | 420 | .release = close, |
413 | .write = write, | 421 | .write = write, |
414 | .read = read, | 422 | .read = read, |