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 <gcosta@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
a3863f68b0
commit
a53a35a8b4
5 changed files with 60 additions and 56 deletions
|
@ -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
|
/* 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
|
* in the kernel, and a more complex one where the Guest is in
|
||||||
* userspace. We check the privilege level to find out. */
|
* 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
|
/* The Guest told us their kernel stack with the SET_STACK
|
||||||
* hypercall: both the virtual address and the segment */
|
* hypercall: both the virtual address and the segment */
|
||||||
virtstack = lg->esp1;
|
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
|
* stack: when the Guest does an "iret" back from the interrupt
|
||||||
* handler the CPU will notice they're dropping privilege
|
* handler the CPU will notice they're dropping privilege
|
||||||
* levels and expect these here. */
|
* levels and expect these here. */
|
||||||
push_guest_stack(lg, &gstack, lg->regs->ss);
|
push_guest_stack(lg, &gstack, cpu->regs->ss);
|
||||||
push_guest_stack(lg, &gstack, lg->regs->esp);
|
push_guest_stack(lg, &gstack, cpu->regs->esp);
|
||||||
} else {
|
} else {
|
||||||
/* We're staying on the same Guest (kernel) stack. */
|
/* We're staying on the same Guest (kernel) stack. */
|
||||||
virtstack = lg->regs->esp;
|
virtstack = cpu->regs->esp;
|
||||||
ss = lg->regs->ss;
|
ss = cpu->regs->ss;
|
||||||
|
|
||||||
origstack = gstack = guest_pa(lg, virtstack);
|
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
|
* 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
|
* Guest's "irq_enabled" field into the eflags word: we saw the Guest
|
||||||
* copy it back in "lguest_iret". */
|
* 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
|
if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
|
||||||
&& !(irq_enable & X86_EFLAGS_IF))
|
&& !(irq_enable & X86_EFLAGS_IF))
|
||||||
eflags &= ~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
|
* "eflags" word, the old code segment, and the old instruction
|
||||||
* pointer. */
|
* pointer. */
|
||||||
push_guest_stack(lg, &gstack, eflags);
|
push_guest_stack(lg, &gstack, eflags);
|
||||||
push_guest_stack(lg, &gstack, lg->regs->cs);
|
push_guest_stack(lg, &gstack, cpu->regs->cs);
|
||||||
push_guest_stack(lg, &gstack, lg->regs->eip);
|
push_guest_stack(lg, &gstack, cpu->regs->eip);
|
||||||
|
|
||||||
/* For the six traps which supply an error code, we push that, too. */
|
/* For the six traps which supply an error code, we push that, too. */
|
||||||
if (has_err)
|
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
|
/* Now we've pushed all the old state, we change the stack, the code
|
||||||
* segment and the address to execute. */
|
* segment and the address to execute. */
|
||||||
lg->regs->ss = ss;
|
cpu->regs->ss = ss;
|
||||||
lg->regs->esp = virtstack + (gstack - origstack);
|
cpu->regs->esp = virtstack + (gstack - origstack);
|
||||||
lg->regs->cs = (__KERNEL_CS|GUEST_PL);
|
cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
|
||||||
lg->regs->eip = idt_address(lo, hi);
|
cpu->regs->eip = idt_address(lo, hi);
|
||||||
|
|
||||||
/* There are two kinds of interrupt handlers: 0xE is an "interrupt
|
/* There are two kinds of interrupt handlers: 0xE is an "interrupt
|
||||||
* gate" which expects interrupts to be disabled on entry. */
|
* 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
|
/* They may be in the middle of an iret, where they asked us never to
|
||||||
* deliver interrupts. */
|
* 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;
|
return;
|
||||||
|
|
||||||
/* If they're halted, interrupts restart them. */
|
/* If they're halted, interrupts restart them. */
|
||||||
|
|
|
@ -44,6 +44,10 @@ struct lg_cpu {
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
struct lguest *lg;
|
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. */
|
/* If a hypercall was asked for, this points to the arguments. */
|
||||||
struct hcall_args *hcall;
|
struct hcall_args *hcall;
|
||||||
u32 next_hcall;
|
u32 next_hcall;
|
||||||
|
@ -58,9 +62,6 @@ struct lg_cpu {
|
||||||
/* The private info the thread maintains about the guest. */
|
/* The private info the thread maintains about the guest. */
|
||||||
struct lguest
|
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 lguest_data __user *lguest_data;
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
|
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);
|
void lguest_arch_handle_trap(struct lg_cpu *cpu);
|
||||||
int lguest_arch_init_hypercalls(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);
|
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: */
|
/* <arch>/switcher.S: */
|
||||||
extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
|
extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
|
||||||
|
|
|
@ -106,6 +106,19 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
|
||||||
cpu->lg->nr_cpus++;
|
cpu->lg->nr_cpus++;
|
||||||
init_clockdev(cpu);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,16 +173,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
|
||||||
if (err)
|
if (err)
|
||||||
goto release_guest;
|
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
|
/* Initialize the Guest's shadow page tables, using the toplevel
|
||||||
* address the Launcher gave us. This allocates memory, so can
|
* address the Launcher gave us. This allocates memory, so can
|
||||||
* fail. */
|
* fail. */
|
||||||
|
@ -177,10 +180,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
|
||||||
if (err)
|
if (err)
|
||||||
goto free_regs;
|
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
|
/* We keep a pointer to the Launcher task (ie. current task) for when
|
||||||
* other Guests want to wake this one (inter-Guest I/O). */
|
* other Guests want to wake this one (inter-Guest I/O). */
|
||||||
lg->tsk = current;
|
lg->tsk = current;
|
||||||
|
@ -205,7 +204,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
|
||||||
return sizeof(args);
|
return sizeof(args);
|
||||||
|
|
||||||
free_regs:
|
free_regs:
|
||||||
free_page(lg->regs_page);
|
/* FIXME: This should be in free_vcpu */
|
||||||
|
free_page(lg->cpus[0].regs_page);
|
||||||
release_guest:
|
release_guest:
|
||||||
kfree(lg);
|
kfree(lg);
|
||||||
unlock:
|
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
|
/* We need the big lock, to protect from inter-guest I/O and other
|
||||||
* Launchers initializing guests. */
|
* Launchers initializing guests. */
|
||||||
mutex_lock(&lguest_lock);
|
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. */
|
/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
|
||||||
hrtimer_cancel(&lg->cpus[i].hrt);
|
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 up the shadow page tables for the Guest. */
|
||||||
free_guest_pagetable(lg);
|
free_guest_pagetable(lg);
|
||||||
/* Now all the memory cleanups are done, it's safe to release the
|
/* 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(). */
|
* kmalloc()ed string, either of which is ok to hand to kfree(). */
|
||||||
if (!IS_ERR(lg->dead))
|
if (!IS_ERR(lg->dead))
|
||||||
kfree(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
|
/* We clear the entire structure, which also marks it as free for the
|
||||||
* next user. */
|
* next user. */
|
||||||
memset(lg, 0, sizeof(*lg));
|
memset(lg, 0, sizeof(*lg));
|
||||||
|
|
|
@ -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);
|
pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
|
||||||
pgd_t switcher_pgd;
|
pgd_t switcher_pgd;
|
||||||
pte_t regs_pte;
|
pte_t regs_pte;
|
||||||
|
unsigned long pfn;
|
||||||
|
|
||||||
/* Make the last PGD entry for this Guest point to the Switcher's PTE
|
/* Make the last PGD entry for this Guest point to the Switcher's PTE
|
||||||
* page for this CPU (with appropriate flags). */
|
* 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
|
* 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
|
* page is already mapped there, we don't have to copy them out
|
||||||
* again. */
|
* 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;
|
switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTRS_PER_PTE] = regs_pte;
|
||||||
}
|
}
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
|
@ -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
|
/* Set the trap number to 256 (impossible value). If we fault while
|
||||||
* switching to the Guest (bad segment registers or bug), this will
|
* switching to the Guest (bad segment registers or bug), this will
|
||||||
* cause us to abort the Guest. */
|
* 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".
|
/* 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
|
* 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
|
* bad virtual address. We have to grab this now, because once we
|
||||||
* re-enable interrupts an interrupt could fault and thus overwrite
|
* re-enable interrupts an interrupt could fault and thus overwrite
|
||||||
* cr2, or we could even move off to a different CPU. */
|
* 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();
|
lg->arch.last_pagefault = read_cr2();
|
||||||
/* Similarly, if we took a trap because the Guest used the FPU,
|
/* Similarly, if we took a trap because the Guest used the FPU,
|
||||||
* we have to restore the FPU it expects to see. */
|
* 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();
|
math_state_restore();
|
||||||
|
|
||||||
/* Restore SYSENTER if it's supposed to be on. */
|
/* 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;
|
unsigned int insnlen = 0, in = 0, shift = 0;
|
||||||
/* The eip contains the *virtual* address of the Guest's instruction:
|
/* The eip contains the *virtual* address of the Guest's instruction:
|
||||||
* guest_pa just subtracts the Guest's page_offset. */
|
* 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!
|
/* This must be the Guest kernel trying to do something, not userspace!
|
||||||
* The bottom two bits of the CS segment register are the privilege
|
* The bottom two bits of the CS segment register are the privilege
|
||||||
* level. */
|
* level. */
|
||||||
if ((lg->regs->cs & 3) != GUEST_PL)
|
if ((cpu->regs->cs & 3) != GUEST_PL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Decoding x86 instructions is icky. */
|
/* Decoding x86 instructions is icky. */
|
||||||
|
@ -273,12 +273,12 @@ static int emulate_insn(struct lg_cpu *cpu)
|
||||||
if (in) {
|
if (in) {
|
||||||
/* Lower bit tells is whether it's a 16 or 32 bit access */
|
/* Lower bit tells is whether it's a 16 or 32 bit access */
|
||||||
if (insn & 0x1)
|
if (insn & 0x1)
|
||||||
lg->regs->eax = 0xFFFFFFFF;
|
cpu->regs->eax = 0xFFFFFFFF;
|
||||||
else
|
else
|
||||||
lg->regs->eax |= (0xFFFF << shift);
|
cpu->regs->eax |= (0xFFFF << shift);
|
||||||
}
|
}
|
||||||
/* Finally, we've "done" the instruction, so move past it. */
|
/* Finally, we've "done" the instruction, so move past it. */
|
||||||
lg->regs->eip += insnlen;
|
cpu->regs->eip += insnlen;
|
||||||
/* Success! */
|
/* Success! */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -287,12 +287,12 @@ static int emulate_insn(struct lg_cpu *cpu)
|
||||||
void lguest_arch_handle_trap(struct lg_cpu *cpu)
|
void lguest_arch_handle_trap(struct lg_cpu *cpu)
|
||||||
{
|
{
|
||||||
struct lguest *lg = cpu->lg;
|
struct lguest *lg = cpu->lg;
|
||||||
switch (lg->regs->trapnum) {
|
switch (cpu->regs->trapnum) {
|
||||||
case 13: /* We've intercepted a General Protection Fault. */
|
case 13: /* We've intercepted a General Protection Fault. */
|
||||||
/* Check if this was one of those annoying IN or OUT
|
/* Check if this was one of those annoying IN or OUT
|
||||||
* instructions which we need to emulate. If so, we just go
|
* instructions which we need to emulate. If so, we just go
|
||||||
* back into the Guest after we've done it. */
|
* back into the Guest after we've done it. */
|
||||||
if (lg->regs->errcode == 0) {
|
if (cpu->regs->errcode == 0) {
|
||||||
if (emulate_insn(cpu))
|
if (emulate_insn(cpu))
|
||||||
return;
|
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
|
* The errcode tells whether this was a read or a write, and
|
||||||
* whether kernel or userspace code. */
|
* 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;
|
return;
|
||||||
|
|
||||||
/* OK, it's really not there (or not OK): the Guest needs to
|
/* 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:
|
case LGUEST_TRAP_ENTRY:
|
||||||
/* Our 'struct hcall_args' maps directly over our regs: we set
|
/* Our 'struct hcall_args' maps directly over our regs: we set
|
||||||
* up the pointer now to indicate a hypercall is pending. */
|
* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We didn't handle the trap, so it needs to go to the Guest. */
|
/* 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
|
/* 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
|
* registered any yet, or it's one of the faults we don't let
|
||||||
* it handle), it dies with a cryptic error message. */
|
* it handle), it dies with a cryptic error message. */
|
||||||
kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
|
kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
|
||||||
lg->regs->trapnum, lg->regs->eip,
|
cpu->regs->trapnum, cpu->regs->eip,
|
||||||
lg->regs->trapnum == 14 ? lg->arch.last_pagefault
|
cpu->regs->trapnum == 14 ? lg->arch.last_pagefault
|
||||||
: lg->regs->errcode);
|
: cpu->regs->errcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we can look at each of the routines this calls, in increasing order of
|
/* 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
|
* Most of the Guest's registers are left alone: we used get_zeroed_page() to
|
||||||
* allocate the structure, so they will be 0. */
|
* 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:
|
/* There are four "segment" registers which the Guest needs to boot:
|
||||||
* The "code segment" register (cs) refers to the kernel code segment
|
* 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
|
/* There are a couple of GDT entries the Guest expects when first
|
||||||
* booting. */
|
* booting. */
|
||||||
setup_guest_gdt(lg);
|
setup_guest_gdt(cpu->lg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue