Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a53a35a8 authored by Glauber de Oliveira Costa's avatar Glauber de Oliveira Costa Committed by Rusty Russell
Browse files

lguest: make registers per-vcpu



This is the most obvious per-vcpu field: registers.

So this patch moves it from struct lguest to struct vcpu,
and patch the places in which they are used, accordingly

Signed-off-by: default avatarGlauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent a3863f68
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
	/* There are two cases for interrupts: one where the Guest is already
	 * in the kernel, and a more complex one where the Guest is in
	 * userspace.  We check the privilege level to find out. */
	if ((lg->regs->ss&0x3) != GUEST_PL) {
	if ((cpu->regs->ss&0x3) != GUEST_PL) {
		/* The Guest told us their kernel stack with the SET_STACK
		 * hypercall: both the virtual address and the segment */
		virtstack = lg->esp1;
@@ -81,12 +81,12 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
		 * stack: when the Guest does an "iret" back from the interrupt
		 * handler the CPU will notice they're dropping privilege
		 * levels and expect these here. */
		push_guest_stack(lg, &gstack, lg->regs->ss);
		push_guest_stack(lg, &gstack, lg->regs->esp);
		push_guest_stack(lg, &gstack, cpu->regs->ss);
		push_guest_stack(lg, &gstack, cpu->regs->esp);
	} else {
		/* We're staying on the same Guest (kernel) stack. */
		virtstack = lg->regs->esp;
		ss = lg->regs->ss;
		virtstack = cpu->regs->esp;
		ss = cpu->regs->ss;

		origstack = gstack = guest_pa(lg, virtstack);
	}
@@ -95,7 +95,7 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
	 * the "Interrupt Flag" bit is always set.  We copy that bit from the
	 * Guest's "irq_enabled" field into the eflags word: we saw the Guest
	 * copy it back in "lguest_iret". */
	eflags = lg->regs->eflags;
	eflags = cpu->regs->eflags;
	if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
	    && !(irq_enable & X86_EFLAGS_IF))
		eflags &= ~X86_EFLAGS_IF;
@@ -104,19 +104,19 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
	 * "eflags" word, the old code segment, and the old instruction
	 * pointer. */
	push_guest_stack(lg, &gstack, eflags);
	push_guest_stack(lg, &gstack, lg->regs->cs);
	push_guest_stack(lg, &gstack, lg->regs->eip);
	push_guest_stack(lg, &gstack, cpu->regs->cs);
	push_guest_stack(lg, &gstack, cpu->regs->eip);

	/* For the six traps which supply an error code, we push that, too. */
	if (has_err)
		push_guest_stack(lg, &gstack, lg->regs->errcode);
		push_guest_stack(lg, &gstack, cpu->regs->errcode);

	/* Now we've pushed all the old state, we change the stack, the code
	 * segment and the address to execute. */
	lg->regs->ss = ss;
	lg->regs->esp = virtstack + (gstack - origstack);
	lg->regs->cs = (__KERNEL_CS|GUEST_PL);
	lg->regs->eip = idt_address(lo, hi);
	cpu->regs->ss = ss;
	cpu->regs->esp = virtstack + (gstack - origstack);
	cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
	cpu->regs->eip = idt_address(lo, hi);

	/* There are two kinds of interrupt handlers: 0xE is an "interrupt
	 * gate" which expects interrupts to be disabled on entry. */
@@ -157,7 +157,7 @@ void maybe_do_interrupt(struct lg_cpu *cpu)

	/* They may be in the middle of an iret, where they asked us never to
	 * deliver interrupts. */
	if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end)
	if (cpu->regs->eip >= lg->noirq_start && cpu->regs->eip < lg->noirq_end)
		return;

	/* If they're halted, interrupts restart them. */
+5 −4
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@ struct lg_cpu {
	unsigned int id;
	struct lguest *lg;

	/* At end of a page shared mapped over lguest_pages in guest.  */
	unsigned long regs_page;
	struct lguest_regs *regs;

	/* If a hypercall was asked for, this points to the arguments. */
	struct hcall_args *hcall;
	u32 next_hcall;
@@ -58,9 +62,6 @@ struct lg_cpu {
/* The private info the thread maintains about the guest. */
struct lguest
{
	/* At end of a page shared mapped over lguest_pages in guest.  */
	unsigned long regs_page;
	struct lguest_regs *regs;
	struct lguest_data __user *lguest_data;
	struct task_struct *tsk;
	struct mm_struct *mm; 	/* == tsk->mm, but that becomes NULL on exit */
@@ -181,7 +182,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu);
void lguest_arch_handle_trap(struct lg_cpu *cpu);
int lguest_arch_init_hypercalls(struct lg_cpu *cpu);
int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args);
void lguest_arch_setup_regs(struct lguest *lg, unsigned long start);
void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start);

/* <arch>/switcher.S: */
extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
+19 −18
Original line number Diff line number Diff line
@@ -106,6 +106,19 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
	cpu->lg->nr_cpus++;
	init_clockdev(cpu);

	/* We need a complete page for the Guest registers: they are accessible
	 * to the Guest and we can only grant it access to whole pages. */
	cpu->regs_page = get_zeroed_page(GFP_KERNEL);
	if (!cpu->regs_page)
		return -ENOMEM;

	/* We actually put the registers at the bottom of the page. */
	cpu->regs = (void *)cpu->regs_page + PAGE_SIZE - sizeof(*cpu->regs);

	/* Now we initialize the Guest's registers, handing it the start
	 * address. */
	lguest_arch_setup_regs(cpu, start_ip);

	return 0;
}

@@ -160,16 +173,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
	if (err)
		goto release_guest;

	/* We need a complete page for the Guest registers: they are accessible
	 * to the Guest and we can only grant it access to whole pages. */
	lg->regs_page = get_zeroed_page(GFP_KERNEL);
	if (!lg->regs_page) {
		err = -ENOMEM;
		goto release_guest;
	}
	/* We actually put the registers at the bottom of the page. */
	lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs);

	/* Initialize the Guest's shadow page tables, using the toplevel
	 * address the Launcher gave us.  This allocates memory, so can
	 * fail. */
@@ -177,10 +180,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
	if (err)
		goto free_regs;

	/* Now we initialize the Guest's registers, handing it the start
	 * address. */
	lguest_arch_setup_regs(lg, args[3]);

	/* We keep a pointer to the Launcher task (ie. current task) for when
	 * other Guests want to wake this one (inter-Guest I/O). */
	lg->tsk = current;
@@ -205,7 +204,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
	return sizeof(args);

free_regs:
	free_page(lg->regs_page);
	/* FIXME: This should be in free_vcpu */
	free_page(lg->cpus[0].regs_page);
release_guest:
	kfree(lg);
unlock:
@@ -280,9 +280,12 @@ static int close(struct inode *inode, struct file *file)
	/* We need the big lock, to protect from inter-guest I/O and other
	 * Launchers initializing guests. */
	mutex_lock(&lguest_lock);
	for (i = 0; i < lg->nr_cpus; i++)
	for (i = 0; i < lg->nr_cpus; i++) {
		/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
		hrtimer_cancel(&lg->cpus[i].hrt);
		/* We can free up the register page we allocated. */
		free_page(lg->cpus[i].regs_page);
	}
	/* Free up the shadow page tables for the Guest. */
	free_guest_pagetable(lg);
	/* Now all the memory cleanups are done, it's safe to release the
@@ -292,8 +295,6 @@ static int close(struct inode *inode, struct file *file)
	 * kmalloc()ed string, either of which is ok to hand to kfree(). */
	if (!IS_ERR(lg->dead))
		kfree(lg->dead);
	/* We can free up the register page we allocated. */
	free_page(lg->regs_page);
	/* We clear the entire structure, which also marks it as free for the
	 * next user. */
	memset(lg, 0, sizeof(*lg));
+3 −1
Original line number Diff line number Diff line
@@ -640,6 +640,7 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
	pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
	pgd_t switcher_pgd;
	pte_t regs_pte;
	unsigned long pfn;

	/* Make the last PGD entry for this Guest point to the Switcher's PTE
	 * page for this CPU (with appropriate flags). */
@@ -654,7 +655,8 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
	 * CPU's "struct lguest_pages": if we make sure the Guest's register
	 * page is already mapped there, we don't have to copy them out
	 * again. */
	regs_pte = pfn_pte (__pa(lg->regs_page) >> PAGE_SHIFT, __pgprot(_PAGE_KERNEL));
	pfn = __pa(cpu->regs_page) >> PAGE_SHIFT;
	regs_pte = pfn_pte(pfn, __pgprot(_PAGE_KERNEL));
	switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTRS_PER_PTE] = regs_pte;
}
/*:*/
+19 −19
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages)
	/* Set the trap number to 256 (impossible value).  If we fault while
	 * switching to the Guest (bad segment registers or bug), this will
	 * cause us to abort the Guest. */
	lg->regs->trapnum = 256;
	cpu->regs->trapnum = 256;

	/* Now: we push the "eflags" register on the stack, then do an "lcall".
	 * This is how we change from using the kernel code segment to using
@@ -195,11 +195,11 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
	 * bad virtual address.  We have to grab this now, because once we
	 * re-enable interrupts an interrupt could fault and thus overwrite
	 * cr2, or we could even move off to a different CPU. */
	if (lg->regs->trapnum == 14)
	if (cpu->regs->trapnum == 14)
		lg->arch.last_pagefault = read_cr2();
	/* Similarly, if we took a trap because the Guest used the FPU,
	 * we have to restore the FPU it expects to see. */
	else if (lg->regs->trapnum == 7)
	else if (cpu->regs->trapnum == 7)
		math_state_restore();

	/* Restore SYSENTER if it's supposed to be on. */
@@ -225,12 +225,12 @@ static int emulate_insn(struct lg_cpu *cpu)
	unsigned int insnlen = 0, in = 0, shift = 0;
	/* The eip contains the *virtual* address of the Guest's instruction:
	 * guest_pa just subtracts the Guest's page_offset. */
	unsigned long physaddr = guest_pa(lg, lg->regs->eip);
	unsigned long physaddr = guest_pa(lg, cpu->regs->eip);

	/* This must be the Guest kernel trying to do something, not userspace!
	 * The bottom two bits of the CS segment register are the privilege
	 * level. */
	if ((lg->regs->cs & 3) != GUEST_PL)
	if ((cpu->regs->cs & 3) != GUEST_PL)
		return 0;

	/* Decoding x86 instructions is icky. */
@@ -273,12 +273,12 @@ static int emulate_insn(struct lg_cpu *cpu)
	if (in) {
		/* Lower bit tells is whether it's a 16 or 32 bit access */
		if (insn & 0x1)
			lg->regs->eax = 0xFFFFFFFF;
			cpu->regs->eax = 0xFFFFFFFF;
		else
			lg->regs->eax |= (0xFFFF << shift);
			cpu->regs->eax |= (0xFFFF << shift);
	}
	/* Finally, we've "done" the instruction, so move past it. */
	lg->regs->eip += insnlen;
	cpu->regs->eip += insnlen;
	/* Success! */
	return 1;
}
@@ -287,12 +287,12 @@ static int emulate_insn(struct lg_cpu *cpu)
void lguest_arch_handle_trap(struct lg_cpu *cpu)
{
	struct lguest *lg = cpu->lg;
	switch (lg->regs->trapnum) {
	switch (cpu->regs->trapnum) {
	case 13: /* We've intercepted a General Protection Fault. */
		/* Check if this was one of those annoying IN or OUT
		 * instructions which we need to emulate.  If so, we just go
		 * back into the Guest after we've done it. */
		if (lg->regs->errcode == 0) {
		if (cpu->regs->errcode == 0) {
			if (emulate_insn(cpu))
				return;
		}
@@ -307,7 +307,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
		 *
		 * The errcode tells whether this was a read or a write, and
		 * whether kernel or userspace code. */
		if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode))
		if (demand_page(lg, lg->arch.last_pagefault, cpu->regs->errcode))
			return;

		/* OK, it's really not there (or not OK): the Guest needs to
@@ -338,19 +338,19 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
	case LGUEST_TRAP_ENTRY:
		/* Our 'struct hcall_args' maps directly over our regs: we set
		 * up the pointer now to indicate a hypercall is pending. */
		cpu->hcall = (struct hcall_args *)lg->regs;
		cpu->hcall = (struct hcall_args *)cpu->regs;
		return;
	}

	/* We didn't handle the trap, so it needs to go to the Guest. */
	if (!deliver_trap(cpu, lg->regs->trapnum))
	if (!deliver_trap(cpu, cpu->regs->trapnum))
		/* If the Guest doesn't have a handler (either it hasn't
		 * registered any yet, or it's one of the faults we don't let
		 * it handle), it dies with a cryptic error message. */
		kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
			   lg->regs->trapnum, lg->regs->eip,
			   lg->regs->trapnum == 14 ? lg->arch.last_pagefault
			   : lg->regs->errcode);
			   cpu->regs->trapnum, cpu->regs->eip,
			   cpu->regs->trapnum == 14 ? lg->arch.last_pagefault
			   : cpu->regs->errcode);
}

/* Now we can look at each of the routines this calls, in increasing order of
@@ -557,9 +557,9 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
 *
 * Most of the Guest's registers are left alone: we used get_zeroed_page() to
 * allocate the structure, so they will be 0. */
void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)
void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
{
	struct lguest_regs *regs = lg->regs;
	struct lguest_regs *regs = cpu->regs;

	/* There are four "segment" registers which the Guest needs to boot:
	 * The "code segment" register (cs) refers to the kernel code segment
@@ -586,5 +586,5 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)

	/* There are a couple of GDT entries the Guest expects when first
	 * booting. */
	setup_guest_gdt(lg);
	setup_guest_gdt(cpu->lg);
}