[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86/64: Save/restore user pagetable pointer for x86/64 PV guests.
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1172876247 0 # Node ID d5ca4c37b3c53688cd556af6730017b902da5bc2 # Parent 87087954247ac63165482c1e59fd3b1ea23fd22f x86/64: Save/restore user pagetable pointer for x86/64 PV guests. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/libxc/xc_linux_restore.c | 24 +++++++++++++++++++++++- tools/libxc/xc_linux_save.c | 16 ++++++++++++++-- xen/arch/x86/domain.c | 25 +++++++++++++++++++++++++ xen/arch/x86/domctl.c | 7 +++++++ xen/include/public/arch-x86/xen.h | 1 + 5 files changed, 70 insertions(+), 3 deletions(-) diff -r 87087954247a -r d5ca4c37b3c5 tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Fri Mar 02 16:57:24 2007 +0000 +++ b/tools/libxc/xc_linux_restore.c Fri Mar 02 22:57:27 2007 +0000 @@ -19,7 +19,7 @@ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ static unsigned long hvirt_start; -/* #levels of page tables used by the currrent guest */ +/* #levels of page tables used by the current guest */ static unsigned int pt_levels; /* total number of pages used by the current guest */ @@ -857,6 +857,28 @@ int xc_linux_restore(int xc_handle, int ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]); + /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */ + if ( (pt_levels == 4) && ctxt.ctrlreg[1] ) + { + pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]); + + if (pfn >= max_pfn) { + ERROR("User PT base is bad: pfn=%lu max_pfn=%lu type=%08lx", + pfn, max_pfn, pfn_type[pfn]); + goto out; + } + + if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) != + ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) { + ERROR("User PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx", + pfn, max_pfn, pfn_type[pfn], + (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT); + goto out; + } + + ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]); + } + domctl.cmd = XEN_DOMCTL_setvcpucontext; domctl.domain = (domid_t)dom; domctl.u.vcpucontext.vcpu = i; diff -r 87087954247a -r d5ca4c37b3c5 tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Fri Mar 02 16:57:24 2007 +0000 +++ b/tools/libxc/xc_linux_save.c Fri Mar 02 22:57:27 2007 +0000 @@ -34,7 +34,7 @@ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ static unsigned long hvirt_start; -/* #levels of page tables used by the currrent guest */ +/* #levels of page tables used by the current guest */ static unsigned int pt_levels; /* total number of pages used by the current guest */ @@ -491,7 +491,7 @@ static int canonicalize_pagetable(unsign ** reserved hypervisor mappings. This depends on the current ** page table type as well as the number of paging levels. */ - xen_start = xen_end = pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8); + xen_start = xen_end = pte_last = PAGE_SIZE / ((pt_levels == 2) ? 4 : 8); if (pt_levels == 2 && type == XEN_DOMCTL_PFINFO_L2TAB) xen_start = (hvirt_start >> L2_PAGETABLE_SHIFT); @@ -1279,6 +1279,18 @@ int xc_linux_save(int xc_handle, int io_ ctxt.ctrlreg[3] = xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3]))); + /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */ + if ( (pt_levels == 4) && ctxt.ctrlreg[1] ) + { + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[1])) ) { + ERROR("PT base is not in range of pseudophys map"); + goto out; + } + /* Least-significant bit means 'valid PFN'. */ + ctxt.ctrlreg[1] = 1 | + xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[1]))); + } + if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) { ERROR("Error when writing to state file (1) (errno %d)", errno); goto out; diff -r 87087954247a -r d5ca4c37b3c5 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Mar 02 16:57:24 2007 +0000 +++ b/xen/arch/x86/domain.c Fri Mar 02 22:57:27 2007 +0000 @@ -641,6 +641,31 @@ int arch_set_info_guest( } v->arch.guest_table = pagetable_from_pfn(cr3_pfn); + +#ifdef __x86_64__ + if ( c.nat->ctrlreg[1] ) + { + cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[1])); + + if ( !mfn_valid(cr3_pfn) || + (paging_mode_refcounts(d) + ? !get_page(mfn_to_page(cr3_pfn), d) + : !get_page_and_type(mfn_to_page(cr3_pfn), d, + PGT_base_page_table)) ) + { + cr3_pfn = pagetable_get_pfn(v->arch.guest_table); + v->arch.guest_table = pagetable_null(); + if ( paging_mode_refcounts(d) ) + put_page(mfn_to_page(cr3_pfn)); + else + put_page_and_type(mfn_to_page(cr3_pfn)); + destroy_gdt(v); + return -EINVAL; + } + + v->arch.guest_table_user = pagetable_from_pfn(cr3_pfn); + } +#endif } #ifdef CONFIG_COMPAT else diff -r 87087954247a -r d5ca4c37b3c5 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Fri Mar 02 16:57:24 2007 +0000 +++ b/xen/arch/x86/domctl.c Fri Mar 02 22:57:27 2007 +0000 @@ -470,8 +470,15 @@ void arch_get_info_guest(struct vcpu *v, c(user_regs.eflags |= v->arch.iopl << 12); if ( !IS_COMPAT(v->domain) ) + { c.nat->ctrlreg[3] = xen_pfn_to_cr3( pagetable_get_pfn(v->arch.guest_table)); +#ifdef __x86_64__ + if ( !pagetable_is_null(v->arch.guest_table_user) ) + c.nat->ctrlreg[1] = xen_pfn_to_cr3( + pagetable_get_pfn(v->arch.guest_table_user)); +#endif + } #ifdef CONFIG_COMPAT else { diff -r 87087954247a -r d5ca4c37b3c5 xen/include/public/arch-x86/xen.h --- a/xen/include/public/arch-x86/xen.h Fri Mar 02 16:57:24 2007 +0000 +++ b/xen/include/public/arch-x86/xen.h Fri Mar 02 22:57:27 2007 +0000 @@ -132,6 +132,7 @@ struct vcpu_guest_context { unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */ + /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */ #ifdef __i386__ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |