mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
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. Cheers, Rusty. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVN1SjAAoJENkgDmzRrbjxeDoP+wZnZdG4cHNc6ifiNPkSed9m cKWV7L6uTxczdFKcTNpDShn2MW0XqbcHc+VdBH9Exl3+cyick6fuhpi6SjLby0g6 a40RldysRMAc/K/dK40dG4qtSUT1uwDrOYNonMDjx1RAikO3DoTGUm4YgYZKSlM/ pKuCbAebM3dZ6EUVnaJICHWkJvY7Bk9JwGL6Z8RhF7lunVAGqIMHH9GklqSCyNiY LK+05hNXHv/OOIAkEO+ZmDrWSagogggGXEdRFom9s87xmu9GVse7Fzfq9pZ5nQre gickgBeC+gN8das1wvhlTp22F8XJslC0IRJhvbwLMQUd16hrH1YUIdvsqry/Qxds 04GgzLTVA/Z5VVEVm9MXcKWGwcsnUBu9EChsdEKZwNgBz9UF2gs39My8Co6AZ7U/ Ajcpksl22RXaR7OB65vRPIk23mh/NchGSzVGFbppzCwj2SkO9ONSFrDj3mAzfbhR 9NHi32Xm0+LdN444WCo1NzahKLAX5bYCv2ZSDs5JEBDQzmW2FWKO2ZaVJ84jpG6O O4XppI/X8cP+dxTs8xH91qh9GGmq9Aa41iuekZh/jG/8fLFT45rhlzLJfwh2B9rI djcaFFLFt+in5R6kgugM9dbCNALneXgGDnzlmqy5RwOrrCTwhyGn6DMwDqRz7EHn gsbiiv6eSsrgX4mLHP2n =Wj06 -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
b9bb6fb73b
24 changed files with 721 additions and 167 deletions
|
|
@ -211,10 +211,9 @@ static void initialize(struct lg_cpu *cpu)
|
|||
|
||||
/*
|
||||
* The Guest tells us where we're not to deliver interrupts by putting
|
||||
* the range of addresses into "struct lguest_data".
|
||||
* the instruction address into "struct lguest_data".
|
||||
*/
|
||||
if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
|
||||
|| get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
|
||||
if (get_user(cpu->lg->noirq_iret, &cpu->lg->lguest_data->noirq_iret))
|
||||
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -56,21 +56,16 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
|
|||
}
|
||||
|
||||
/*H:210
|
||||
* The set_guest_interrupt() routine actually delivers the interrupt or
|
||||
* trap. The mechanics of delivering traps and interrupts to the Guest are the
|
||||
* same, except some traps have an "error code" which gets pushed onto the
|
||||
* stack as well: the caller tells us if this is one.
|
||||
*
|
||||
* "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this
|
||||
* interrupt or trap. It's split into two parts for traditional reasons: gcc
|
||||
* on i386 used to be frightened by 64 bit numbers.
|
||||
* The push_guest_interrupt_stack() routine saves Guest state on the stack for
|
||||
* an interrupt or trap. The mechanics of delivering traps and interrupts to
|
||||
* the Guest are the same, except some traps have an "error code" which gets
|
||||
* pushed onto the stack as well: the caller tells us if this is one.
|
||||
*
|
||||
* We set up the stack just like the CPU does for a real interrupt, so it's
|
||||
* identical for the Guest (and the standard "iret" instruction will undo
|
||||
* it).
|
||||
*/
|
||||
static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
|
||||
bool has_err)
|
||||
static void push_guest_interrupt_stack(struct lg_cpu *cpu, bool has_err)
|
||||
{
|
||||
unsigned long gstack, origstack;
|
||||
u32 eflags, ss, irq_enable;
|
||||
|
|
@ -130,12 +125,28 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
|
|||
if (has_err)
|
||||
push_guest_stack(cpu, &gstack, cpu->regs->errcode);
|
||||
|
||||
/*
|
||||
* Now we've pushed all the old state, we change the stack, the code
|
||||
* segment and the address to execute.
|
||||
*/
|
||||
/* Adjust the stack pointer and stack segment. */
|
||||
cpu->regs->ss = ss;
|
||||
cpu->regs->esp = virtstack + (gstack - origstack);
|
||||
}
|
||||
|
||||
/*
|
||||
* This actually makes the Guest start executing the given interrupt/trap
|
||||
* handler.
|
||||
*
|
||||
* "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this
|
||||
* interrupt or trap. It's split into two parts for traditional reasons: gcc
|
||||
* on i386 used to be frightened by 64 bit numbers.
|
||||
*/
|
||||
static void guest_run_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi)
|
||||
{
|
||||
/* If we're already in the kernel, we don't change stacks. */
|
||||
if ((cpu->regs->ss&0x3) != GUEST_PL)
|
||||
cpu->regs->ss = cpu->esp1;
|
||||
|
||||
/*
|
||||
* Set the code segment and the address to execute.
|
||||
*/
|
||||
cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
|
||||
cpu->regs->eip = idt_address(lo, hi);
|
||||
|
||||
|
|
@ -158,6 +169,24 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
|
|||
kill_guest(cpu, "Disabling interrupts");
|
||||
}
|
||||
|
||||
/* This restores the eflags word which was pushed on the stack by a trap */
|
||||
static void restore_eflags(struct lg_cpu *cpu)
|
||||
{
|
||||
/* This is the physical address of the stack. */
|
||||
unsigned long stack_pa = guest_pa(cpu, cpu->regs->esp);
|
||||
|
||||
/*
|
||||
* Stack looks like this:
|
||||
* Address Contents
|
||||
* esp EIP
|
||||
* esp + 4 CS
|
||||
* esp + 8 EFLAGS
|
||||
*/
|
||||
cpu->regs->eflags = lgread(cpu, stack_pa + 8, u32);
|
||||
cpu->regs->eflags &=
|
||||
~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT);
|
||||
}
|
||||
|
||||
/*H:205
|
||||
* Virtual Interrupts.
|
||||
*
|
||||
|
|
@ -200,14 +229,6 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
|
|||
|
||||
BUG_ON(irq >= LGUEST_IRQS);
|
||||
|
||||
/*
|
||||
* They may be in the middle of an iret, where they asked us never to
|
||||
* deliver interrupts.
|
||||
*/
|
||||
if (cpu->regs->eip >= cpu->lg->noirq_start &&
|
||||
(cpu->regs->eip < cpu->lg->noirq_end))
|
||||
return;
|
||||
|
||||
/* If they're halted, interrupts restart them. */
|
||||
if (cpu->halted) {
|
||||
/* Re-enable interrupts. */
|
||||
|
|
@ -237,12 +258,34 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
|
|||
if (idt_present(idt->a, idt->b)) {
|
||||
/* OK, mark it no longer pending and deliver it. */
|
||||
clear_bit(irq, cpu->irqs_pending);
|
||||
|
||||
/*
|
||||
* set_guest_interrupt() takes the interrupt descriptor and a
|
||||
* flag to say whether this interrupt pushes an error code onto
|
||||
* the stack as well: virtual interrupts never do.
|
||||
* They may be about to iret, where they asked us never to
|
||||
* deliver interrupts. In this case, we can emulate that iret
|
||||
* then immediately deliver the interrupt. This is basically
|
||||
* a noop: the iret would pop the interrupt frame and restore
|
||||
* eflags, and then we'd set it up again. So just restore the
|
||||
* eflags word and jump straight to the handler in this case.
|
||||
*
|
||||
* Denys Vlasenko points out that this isn't quite right: if
|
||||
* the iret was returning to userspace, then that interrupt
|
||||
* would reset the stack pointer (which the Guest told us
|
||||
* about via LHCALL_SET_STACK). But unless the Guest is being
|
||||
* *really* weird, that will be the same as the current stack
|
||||
* anyway.
|
||||
*/
|
||||
set_guest_interrupt(cpu, idt->a, idt->b, false);
|
||||
if (cpu->regs->eip == cpu->lg->noirq_iret) {
|
||||
restore_eflags(cpu);
|
||||
} else {
|
||||
/*
|
||||
* set_guest_interrupt() takes a flag to say whether
|
||||
* this interrupt pushes an error code onto the stack
|
||||
* as well: virtual interrupts never do.
|
||||
*/
|
||||
push_guest_interrupt_stack(cpu, false);
|
||||
}
|
||||
/* Actually make Guest cpu jump to handler. */
|
||||
guest_run_interrupt(cpu, idt->a, idt->b);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -353,8 +396,9 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
|
|||
*/
|
||||
if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
|
||||
return false;
|
||||
set_guest_interrupt(cpu, cpu->arch.idt[num].a,
|
||||
cpu->arch.idt[num].b, has_err(num));
|
||||
push_guest_interrupt_stack(cpu, has_err(num));
|
||||
guest_run_interrupt(cpu, cpu->arch.idt[num].a,
|
||||
cpu->arch.idt[num].b);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -395,8 +439,9 @@ static bool direct_trap(unsigned int num)
|
|||
* The Guest has the ability to turn its interrupt gates into trap gates,
|
||||
* if it is careful. The Host will let trap gates can go directly to the
|
||||
* Guest, but the Guest needs the interrupts atomically disabled for an
|
||||
* interrupt gate. It can do this by pointing the trap gate at instructions
|
||||
* within noirq_start and noirq_end, where it can safely disable interrupts.
|
||||
* interrupt gate. The Host could provide a mechanism to register more
|
||||
* "no-interrupt" regions, and the Guest could point the trap gate at
|
||||
* instructions within that region, where it can safely disable interrupts.
|
||||
*/
|
||||
|
||||
/*M:006
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ struct lguest {
|
|||
|
||||
struct pgdir pgdirs[4];
|
||||
|
||||
unsigned long noirq_start, noirq_end;
|
||||
unsigned long noirq_iret;
|
||||
|
||||
unsigned int stack_pages;
|
||||
u32 tsc_khz;
|
||||
|
|
|
|||
|
|
@ -339,6 +339,13 @@ static ssize_t write(struct file *file, const char __user *in,
|
|||
}
|
||||
}
|
||||
|
||||
static int open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*L:060
|
||||
* The final piece of interface code is the close() routine. It reverses
|
||||
* everything done in initialize(). This is usually called because the
|
||||
|
|
@ -409,6 +416,7 @@ static int close(struct inode *inode, struct file *file)
|
|||
*/
|
||||
static const struct file_operations lguest_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = open,
|
||||
.release = close,
|
||||
.write = write,
|
||||
.read = read,
|
||||
|
|
|
|||
Loading…
Reference in a new issue