From d0953d42c3445a120299fac9ad70e672d77898e9 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:25 -0200 Subject: lguest: per-cpu run guest This patch makes the run_guest() routine use the lg_cpu struct. This is required since in a smp guest environment, there's no more the notion of "running the guest", but rather, it is "running the vcpu" Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 96d0fd07c57..3d2131e169f 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -73,8 +73,9 @@ static DEFINE_PER_CPU(struct lguest *, last_guest); * since it last ran. We saw this set in interrupts_and_traps.c and * segments.c. */ -static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages) +static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) { + struct lguest *lg = cpu->lg; /* Copying all this data can be quite expensive. We usually run the * same Guest we ran last time (and that Guest hasn't run anywhere else * meanwhile). If that's not the case, we pretend everything in the @@ -113,14 +114,15 @@ static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages) } /* Finally: the code to actually call into the Switcher to run the Guest. */ -static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) +static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) { /* This is a dummy value we need for GCC's sake. */ unsigned int clobber; + struct lguest *lg = cpu->lg; /* Copy the guest-specific information into this CPU's "struct * lguest_pages". */ - copy_in_guest_info(lg, pages); + copy_in_guest_info(cpu, pages); /* Set the trap number to 256 (impossible value). If we fault while * switching to the Guest (bad segment registers or bug), this will @@ -161,8 +163,10 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages) /*H:040 This is the i386-specific code to setup and run the Guest. Interrupts * are disabled: we own the CPU. */ -void lguest_arch_run_guest(struct lguest *lg) +void lguest_arch_run_guest(struct lg_cpu *cpu) { + struct lguest *lg = cpu->lg; + /* Remember the awfully-named TS bit? If the Guest has asked to set it * we set it now, so we can trap and pass that trap to the Guest if it * uses the FPU. */ @@ -180,7 +184,7 @@ void lguest_arch_run_guest(struct lguest *lg) /* Now we actually run the Guest. It will return when something * interesting happens, and we can examine its registers to see what it * was doing. */ - run_guest_once(lg, lguest_pages(raw_smp_processor_id())); + run_guest_once(cpu, lguest_pages(raw_smp_processor_id())); /* Note that the "regs" pointer contains two extra entries which are * not really registers: a trap number which says what interrupt or -- cgit v1.2.3 From 73044f05a4ac65f2df42753e9566444b9d2a660f Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:27 -0200 Subject: lguest: make hypercalls use the vcpu struct this patch changes do_hcall() and do_async_hcall() interfaces (and obviously their callers) to get a vcpu struct. Again, a vcpu services the hypercall, not the whole guest Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 3d2131e169f..5962160aff3 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -283,8 +283,9 @@ static int emulate_insn(struct lguest *lg) } /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */ -void lguest_arch_handle_trap(struct lguest *lg) +void lguest_arch_handle_trap(struct lg_cpu *cpu) { + struct lguest *lg = cpu->lg; switch (lg->regs->trapnum) { case 13: /* We've intercepted a General Protection Fault. */ /* Check if this was one of those annoying IN or OUT @@ -336,7 +337,7 @@ void lguest_arch_handle_trap(struct lguest *lg) 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. */ - lg->hcall = (struct hcall_args *)lg->regs; + cpu->hcall = (struct hcall_args *)lg->regs; return; } @@ -491,8 +492,10 @@ void __exit lguest_arch_host_fini(void) /*H:122 The i386-specific hypercalls simply farm out to the right functions. */ -int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args) +int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args) { + struct lguest *lg = cpu->lg; + switch (args->arg0) { case LHCALL_LOAD_GDT: load_guest_gdt(lg, args->arg1, args->arg2); @@ -511,13 +514,14 @@ int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args) } /*H:126 i386-specific hypercall initialization: */ -int lguest_arch_init_hypercalls(struct lguest *lg) +int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; + struct lguest *lg = cpu->lg; /* The pointer to the Guest's "struct lguest_data" is the only * argument. We check that address now. */ - if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data))) + if (!lguest_address_ok(lg, cpu->hcall->arg1, sizeof(*lg->lguest_data))) return -EFAULT; /* Having checked it, we simply set lg->lguest_data to point straight @@ -525,7 +529,7 @@ int lguest_arch_init_hypercalls(struct lguest *lg) * copy_to_user/from_user from now on, instead of lgread/write. I put * this in to show that I'm not immune to writing stupid * optimizations. */ - lg->lguest_data = lg->mem_base + lg->hcall->arg1; + lg->lguest_data = lg->mem_base + cpu->hcall->arg1; /* We insist that the Time Stamp Counter exist and doesn't change with * cpu frequency. Some devious chip manufacturers decided that TSC -- cgit v1.2.3 From 177e449dc5bd4cf8dc48d66abee61ddf34b126b9 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:29 -0200 Subject: lguest: per-vcpu interrupt processing. This patch adapts interrupt processing for using the vcpu struct. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 5962160aff3..66f48fcc119 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -342,7 +342,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) } /* We didn't handle the trap, so it needs to go to the Guest. */ - if (!deliver_trap(lg, lg->regs->trapnum)) + if (!deliver_trap(cpu, lg->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. */ -- cgit v1.2.3 From 0c78441cf4dd66f66e23dc085f0cc1e3e8669b96 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:30 -0200 Subject: lguest: map_switcher_in_guest() per-vcpu The switcher needs to be mapped per-vcpu, because different vcpus will potentially have different page tables (they don't have to, because threads will share the same). So our first step is the make the function receive a vcpu struct Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 66f48fcc119..d35f6299c92 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -91,7 +91,7 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) pages->state.host_cr3 = __pa(current->mm->pgd); /* Set up the Guest's page tables to see this CPU's pages (and no * other CPU's pages). */ - map_switcher_in_guest(lg, pages); + map_switcher_in_guest(cpu, pages); /* Set up the two "TSS" members which tell the CPU what stack to use * for traps which do directly into the Guest (ie. traps at privilege * level 1). */ -- cgit v1.2.3 From a3863f68b0d7fe2073c0f4efe534ec87a685c4fa Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:31 -0200 Subject: lguest: make emulate_insn receive a vcpu struct. emulate_insn() needs to know about current eip, which will be, in the future, a per-vcpu thing. So in this patch, the function prototype is modified to receive a vcpu struct Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index d35f6299c92..ae46c6b1f2f 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -218,8 +218,9 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * When the Guest uses one of these instructions, we get a trap (General * Protection Fault) and come here. We see if it's one of those troublesome * instructions and skip over it. We return true if we did. */ -static int emulate_insn(struct lguest *lg) +static int emulate_insn(struct lg_cpu *cpu) { + struct lguest *lg = cpu->lg; u8 insn; unsigned int insnlen = 0, in = 0, shift = 0; /* The eip contains the *virtual* address of the Guest's instruction: @@ -292,7 +293,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) * 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 (emulate_insn(lg)) + if (emulate_insn(cpu)) return; } break; -- cgit v1.2.3 From a53a35a8b485b9c16b73e5177bddaa4321971199 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:32 -0200 Subject: 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: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index ae46c6b1f2f..d96a93d95ae 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -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); } -- cgit v1.2.3 From fc708b3e407dfd2e12ba9a6cf35bd0bffad1796d Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:33 -0200 Subject: lguest: replace lguest_arch with lg_cpu_arch. The fields found in lguest_arch are not really per-guest, but per-cpu (gdt, idt, etc). So this patch turns lguest_arch into lg_cpu_arch. It makes sense to have a per-guest per-arch struct, but this can be addressed later, when the need arrives. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index d96a93d95ae..e989b835886 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -100,14 +100,14 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) /* Copy direct-to-Guest trap entries. */ if (lg->changed & CHANGED_IDT) - copy_traps(lg, pages->state.guest_idt, default_idt_entries); + copy_traps(cpu, pages->state.guest_idt, default_idt_entries); /* Copy all GDT entries which the Guest can change. */ if (lg->changed & CHANGED_GDT) - copy_gdt(lg, pages->state.guest_gdt); + copy_gdt(cpu, pages->state.guest_gdt); /* If only the TLS entries have changed, copy them. */ else if (lg->changed & CHANGED_GDT_TLS) - copy_gdt_tls(lg, pages->state.guest_gdt); + copy_gdt_tls(cpu, pages->state.guest_gdt); /* Mark the Guest as unchanged for next time. */ lg->changed = 0; @@ -196,7 +196,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * re-enable interrupts an interrupt could fault and thus overwrite * cr2, or we could even move off to a different CPU. */ if (cpu->regs->trapnum == 14) - lg->arch.last_pagefault = read_cr2(); + cpu->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 (cpu->regs->trapnum == 7) @@ -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, cpu->regs->errcode)) + if (demand_page(lg,cpu->arch.last_pagefault,cpu->regs->errcode)) return; /* OK, it's really not there (or not OK): the Guest needs to @@ -318,7 +318,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) * happen before it's done the LHCALL_LGUEST_INIT hypercall, so * lg->lguest_data could be NULL */ if (lg->lguest_data && - put_user(lg->arch.last_pagefault, &lg->lguest_data->cr2)) + put_user(cpu->arch.last_pagefault, &lg->lguest_data->cr2)) kill_guest(lg, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ @@ -349,7 +349,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) * it handle), it dies with a cryptic error message. */ kill_guest(lg, "unhandled trap %li at %#lx (%#lx)", cpu->regs->trapnum, cpu->regs->eip, - cpu->regs->trapnum == 14 ? lg->arch.last_pagefault + cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault : cpu->regs->errcode); } @@ -495,17 +495,15 @@ void __exit lguest_arch_host_fini(void) /*H:122 The i386-specific hypercalls simply farm out to the right functions. */ int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args) { - struct lguest *lg = cpu->lg; - switch (args->arg0) { case LHCALL_LOAD_GDT: - load_guest_gdt(lg, args->arg1, args->arg2); + load_guest_gdt(cpu, args->arg1, args->arg2); break; case LHCALL_LOAD_IDT_ENTRY: - load_guest_idt_entry(lg, args->arg1, args->arg2, args->arg3); + load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3); break; case LHCALL_LOAD_TLS: - guest_load_tls(lg, args->arg1); + guest_load_tls(cpu, args->arg1); break; default: /* Bad Guest. Bad! */ @@ -586,5 +584,5 @@ void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start) /* There are a couple of GDT entries the Guest expects when first * booting. */ - setup_guest_gdt(cpu->lg); + setup_guest_gdt(cpu); } -- cgit v1.2.3 From 4665ac8e28c30c2a015c617c55783c0bf3a49c05 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:35 -0200 Subject: lguest: makes special fields be per-vcpu lguest struct have room for some fields, namely, cr2, ts, esp1 and ss1, that are not really guest-wide, but rather, vcpu-wide. This patch puts it in the vcpu struct Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index e989b835886..65f2e380947 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -95,8 +95,8 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) /* Set up the two "TSS" members which tell the CPU what stack to use * for traps which do directly into the Guest (ie. traps at privilege * level 1). */ - pages->state.guest_tss.esp1 = lg->esp1; - pages->state.guest_tss.ss1 = lg->ss1; + pages->state.guest_tss.esp1 = cpu->esp1; + pages->state.guest_tss.ss1 = cpu->ss1; /* Copy direct-to-Guest trap entries. */ if (lg->changed & CHANGED_IDT) @@ -165,12 +165,10 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) * are disabled: we own the CPU. */ void lguest_arch_run_guest(struct lg_cpu *cpu) { - struct lguest *lg = cpu->lg; - /* Remember the awfully-named TS bit? If the Guest has asked to set it * we set it now, so we can trap and pass that trap to the Guest if it * uses the FPU. */ - if (lg->ts) + if (cpu->ts) lguest_set_ts(); /* SYSENTER is an optimized way of doing system calls. We can't allow @@ -325,7 +323,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) /* If the Guest doesn't want to know, we already restored the * Floating Point Unit, so we just continue without telling * it. */ - if (!lg->ts) + if (!cpu->ts) return; break; case 32 ... 255: -- cgit v1.2.3 From 1713608f280002d9ffc6de89d7de5cf367072d63 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Mon, 7 Jan 2008 11:05:37 -0200 Subject: lguest: per-vcpu lguest pgdir management this patch makes the pgdir management per-vcpu. The pgdirs pool is still guest-wide (although it'll probably need to grow when we are really executing more vcpus), but the pgdidx index is gone, since it makes no sense anymore. Instead, we use a per-vcpu index. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 65f2e380947..8c723555ffb 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -145,7 +145,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) * 0-th argument above, ie "a"). %ebx contains the * physical address of the Guest's top-level page * directory. */ - : "0"(pages), "1"(__pa(lg->pgdirs[lg->pgdidx].pgdir)) + : "0"(pages), "1"(__pa(lg->pgdirs[cpu->cpu_pgd].pgdir)) /* We tell gcc that all these registers could change, * which means we don't have to save and restore them in * the Switcher. */ @@ -223,7 +223,7 @@ 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, cpu->regs->eip); + unsigned long physaddr = guest_pa(cpu, 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 @@ -305,7 +305,8 @@ 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,cpu->arch.last_pagefault,cpu->regs->errcode)) + if (demand_page(cpu, cpu->arch.last_pagefault, + cpu->regs->errcode)) return; /* OK, it's really not there (or not OK): the Guest needs to -- cgit v1.2.3 From c40a9f4719d36841a2d7ff4fe866dce7bfb454b7 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Thu, 17 Jan 2008 19:11:20 -0200 Subject: lguest: change last_guest to last_cpu in our model, a guest does not run in a cpu anymore: a virtual cpu does. So we change last_guest to last_cpu Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 8c723555ffb..10eab6748d8 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -60,7 +60,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu) (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]); } -static DEFINE_PER_CPU(struct lguest *, last_guest); +static DEFINE_PER_CPU(struct lg_cpu *, last_cpu); /*S:010 * We approach the Switcher. @@ -80,8 +80,8 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) * same Guest we ran last time (and that Guest hasn't run anywhere else * meanwhile). If that's not the case, we pretend everything in the * Guest has changed. */ - if (__get_cpu_var(last_guest) != lg || lg->last_pages != pages) { - __get_cpu_var(last_guest) = lg; + if (__get_cpu_var(last_cpu) != cpu || lg->last_pages != pages) { + __get_cpu_var(last_cpu) = cpu; lg->last_pages = pages; lg->changed = CHANGED_ALL; } -- cgit v1.2.3 From f34f8c5fea079065671163c37d98328cff31980b Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Thu, 17 Jan 2008 19:13:26 -0200 Subject: lguest: move last_pages to lg_cpu in our new model, pages are assigned to a virtual cpu, not to a guest. We move it to the lg_cpu structure. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 10eab6748d8..f8dfdc9a3e5 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -80,9 +80,9 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) * same Guest we ran last time (and that Guest hasn't run anywhere else * meanwhile). If that's not the case, we pretend everything in the * Guest has changed. */ - if (__get_cpu_var(last_cpu) != cpu || lg->last_pages != pages) { + if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) { __get_cpu_var(last_cpu) = cpu; - lg->last_pages = pages; + cpu->last_pages = pages; lg->changed = CHANGED_ALL; } -- cgit v1.2.3 From ae3749dcd8c31dcfbab14ea28c68a944c93f418f Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Thu, 17 Jan 2008 19:14:46 -0200 Subject: lguest: move changed bitmap to lg_cpu events represented in the 'changed' bitmap are per-cpu, not per-guest. move it to the lg_cpu structure Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index f8dfdc9a3e5..fd6a8512443 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -75,7 +75,6 @@ static DEFINE_PER_CPU(struct lg_cpu *, last_cpu); */ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) { - struct lguest *lg = cpu->lg; /* Copying all this data can be quite expensive. We usually run the * same Guest we ran last time (and that Guest hasn't run anywhere else * meanwhile). If that's not the case, we pretend everything in the @@ -83,7 +82,7 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) { __get_cpu_var(last_cpu) = cpu; cpu->last_pages = pages; - lg->changed = CHANGED_ALL; + cpu->changed = CHANGED_ALL; } /* These copies are pretty cheap, so we do them unconditionally: */ @@ -99,18 +98,18 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) pages->state.guest_tss.ss1 = cpu->ss1; /* Copy direct-to-Guest trap entries. */ - if (lg->changed & CHANGED_IDT) + if (cpu->changed & CHANGED_IDT) copy_traps(cpu, pages->state.guest_idt, default_idt_entries); /* Copy all GDT entries which the Guest can change. */ - if (lg->changed & CHANGED_GDT) + if (cpu->changed & CHANGED_GDT) copy_gdt(cpu, pages->state.guest_gdt); /* If only the TLS entries have changed, copy them. */ - else if (lg->changed & CHANGED_GDT_TLS) + else if (cpu->changed & CHANGED_GDT_TLS) copy_gdt_tls(cpu, pages->state.guest_gdt); /* Mark the Guest as unchanged for next time. */ - lg->changed = 0; + cpu->changed = 0; } /* Finally: the code to actually call into the Switcher to run the Guest. */ -- cgit v1.2.3 From 382ac6b3fbc0ea6a5697fc6caaf7e7de12fa8b96 Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Thu, 17 Jan 2008 19:19:42 -0200 Subject: lguest: get rid of lg variable assignments We can save some lines of code by getting rid of *lg = cpu... lines of code spread everywhere by now. Signed-off-by: Glauber de Oliveira Costa Signed-off-by: Rusty Russell --- drivers/lguest/x86/core.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers/lguest/x86') diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index fd6a8512443..e9c3ba8aa1e 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -117,7 +117,6 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) { /* This is a dummy value we need for GCC's sake. */ unsigned int clobber; - struct lguest *lg = cpu->lg; /* Copy the guest-specific information into this CPU's "struct * lguest_pages". */ @@ -144,7 +143,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) * 0-th argument above, ie "a"). %ebx contains the * physical address of the Guest's top-level page * directory. */ - : "0"(pages), "1"(__pa(lg->pgdirs[cpu->cpu_pgd].pgdir)) + : "0"(pages), "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir)) /* We tell gcc that all these registers could change, * which means we don't have to save and restore them in * the Switcher. */ @@ -217,7 +216,6 @@ void lguest_arch_run_guest(struct lg_cpu *cpu) * instructions and skip over it. We return true if we did. */ static int emulate_insn(struct lg_cpu *cpu) { - struct lguest *lg = cpu->lg; u8 insn; unsigned int insnlen = 0, in = 0, shift = 0; /* The eip contains the *virtual* address of the Guest's instruction: @@ -231,7 +229,7 @@ static int emulate_insn(struct lg_cpu *cpu) return 0; /* Decoding x86 instructions is icky. */ - insn = lgread(lg, physaddr, u8); + insn = lgread(cpu, physaddr, u8); /* 0x66 is an "operand prefix". It means it's using the upper 16 bits of the eax register. */ @@ -239,7 +237,7 @@ static int emulate_insn(struct lg_cpu *cpu) shift = 16; /* The instruction is 1 byte so far, read the next byte. */ insnlen = 1; - insn = lgread(lg, physaddr + insnlen, u8); + insn = lgread(cpu, physaddr + insnlen, u8); } /* We can ignore the lower bit for the moment and decode the 4 opcodes @@ -283,7 +281,6 @@ static int emulate_insn(struct lg_cpu *cpu) /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */ void lguest_arch_handle_trap(struct lg_cpu *cpu) { - struct lguest *lg = cpu->lg; switch (cpu->regs->trapnum) { case 13: /* We've intercepted a General Protection Fault. */ /* Check if this was one of those annoying IN or OUT @@ -315,9 +312,10 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) * Note that if the Guest were really messed up, this could * happen before it's done the LHCALL_LGUEST_INIT hypercall, so * lg->lguest_data could be NULL */ - if (lg->lguest_data && - put_user(cpu->arch.last_pagefault, &lg->lguest_data->cr2)) - kill_guest(lg, "Writing cr2"); + if (cpu->lg->lguest_data && + put_user(cpu->arch.last_pagefault, + &cpu->lg->lguest_data->cr2)) + kill_guest(cpu, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ /* If the Guest doesn't want to know, we already restored the @@ -345,7 +343,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) /* 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)", + kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)", cpu->regs->trapnum, cpu->regs->eip, cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault : cpu->regs->errcode); @@ -514,11 +512,11 @@ int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args) int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; - struct lguest *lg = cpu->lg; /* The pointer to the Guest's "struct lguest_data" is the only * argument. We check that address now. */ - if (!lguest_address_ok(lg, cpu->hcall->arg1, sizeof(*lg->lguest_data))) + if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1, + sizeof(*cpu->lg->lguest_data))) return -EFAULT; /* Having checked it, we simply set lg->lguest_data to point straight @@ -526,7 +524,7 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) * copy_to_user/from_user from now on, instead of lgread/write. I put * this in to show that I'm not immune to writing stupid * optimizations. */ - lg->lguest_data = lg->mem_base + cpu->hcall->arg1; + cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1; /* We insist that the Time Stamp Counter exist and doesn't change with * cpu frequency. Some devious chip manufacturers decided that TSC @@ -539,12 +537,12 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) tsc_speed = tsc_khz; else tsc_speed = 0; - if (put_user(tsc_speed, &lg->lguest_data->tsc_khz)) + if (put_user(tsc_speed, &cpu->lg->lguest_data->tsc_khz)) return -EFAULT; /* The interrupt code might not like the system call vector. */ - if (!check_syscall_vector(lg)) - kill_guest(lg, "bad syscall vector"); + if (!check_syscall_vector(cpu->lg)) + kill_guest(cpu, "bad syscall vector"); return 0; } -- cgit v1.2.3