diff -r bc573e4f7319 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Tue Jan 23 18:03:02 2007 -0600 +++ b/xen/arch/x86/Makefile Tue Jan 23 18:54:33 2007 -0600 @@ -45,6 +45,7 @@ obj-y += x86_emulate.o obj-y += x86_emulate.o obj-y += machine_kexec.o obj-y += crash.o +obj-y += paging.o obj-$(crash_debug) += gdbstub.o diff -r bc573e4f7319 xen/arch/x86/paging.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/paging.c Tue Jan 23 18:56:16 2007 -0600 @@ -0,0 +1,53 @@ +/****************************************************************************** + * arch/x86/paging.c + * + * x86 specific paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + + +/* check whether hap option is enabled in Xen boot option */ +static int opt_hap_enabled = 0; /* hardware assisted paging option */ +boolean_param("hap", opt_hap_enabled); + +/* Domain paging struct initilization. */ +void paging_domain_init(struct domain *d) +{ + shadow_domain_init(d); + d->arch.paging.domctl = &shadow_domctl; + d->arch.paging.teardown = &shadow_teardown; + d->arch.paging.final_teardown = &shadow_final_teardown; +} + +/* vcpu paging struct initialization goes here */ +void paging_vcpu_init(struct vcpu *v) +{ + shadow_vcpu_init(v); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff -r bc573e4f7319 xen/include/asm-x86/paging.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/paging.h Tue Jan 23 18:56:16 2007 -0600 @@ -0,0 +1,258 @@ +/****************************************************************************** + * include/asm-x86/paging.h + * + * Common interface for paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_PAGING_H +#define _XEN_PAGING_H + +#include +#include +#include +#include +#include +#include +#include + +/************************************************/ +/* type definition */ +/************************************************/ +/****************************************************************************** + * With shadow pagetables, the different kinds of address start + * to get get confusing. + * + * Virtual addresses are what they usually are: the addresses that are used + * to accessing memory while the guest is running. The MMU translates from + * virtual addresses to machine addresses. + * + * (Pseudo-)physical addresses are the abstraction of physical memory the + * guest uses for allocation and so forth. For the purposes of this code, + * we can largely ignore them. + * + * Guest frame numbers (gfns) are the entries that the guest puts in its + * pagetables. For normal paravirtual guests, they are actual frame numbers, + * with the translation done by the guest. + * + * Machine frame numbers (mfns) are the entries that the hypervisor puts + * in the shadow page tables. + * + * Elsewhere in the xen code base, the name "gmfn" is generally used to refer + * to a "machine frame number, from the guest's perspective", or in other + * words, pseudo-physical frame numbers. However, in the shadow code, the + * term "gmfn" means "the mfn of a guest page"; this combines naturally with + * other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a + * guest L2 page), etc... + */ + +/* With this defined, we do some ugly things to force the compiler to + * give us type safety between mfns and gfns and other integers. + * TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions + * that translate beween int and foo_t. + * + * It does have some performance cost because the types now have + * a different storage attribute, so may not want it on all the time. */ + +#ifndef NDEBUG +#define TYPE_SAFETY 1 +#endif + +#ifdef TYPE_SAFETY +#define TYPE_SAFE(_type,_name) \ +typedef struct { _type _name; } _name##_t; \ +static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \ +static inline _type _name##_x(_name##_t n) { return n._name; } +#else +#define TYPE_SAFE(_type,_name) \ +typedef _type _name##_t; \ +static inline _name##_t _##_name(_type n) { return n; } \ +static inline _type _name##_x(_name##_t n) { return n; } +#endif + +TYPE_SAFE(unsigned long,mfn); + +/************************************************/ +/* shadow paging extension */ +/************************************************/ +struct sh_emulate_ctxt; +struct shadow_paging_mode { + int (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn, + void *new_guest_entry, u32 size); + int (*map_and_validate_gl2e )(struct vcpu *v, mfn_t gmfn, + void *new_guest_entry, u32 size); + int (*map_and_validate_gl2he)(struct vcpu *v, mfn_t gmfn, + void *new_guest_entry, u32 size); + int (*map_and_validate_gl3e )(struct vcpu *v, mfn_t gmfn, + void *new_guest_entry, u32 size); + int (*map_and_validate_gl4e )(struct vcpu *v, mfn_t gmfn, + void *new_guest_entry, u32 size); + void (*detach_old_tables )(struct vcpu *v); + int (*x86_emulate_write )(struct vcpu *v, unsigned long va, + void *src, u32 bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct sh_emulate_ctxt *sh_ctxt); + mfn_t (*make_monitor_table )(struct vcpu *v); + void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); + void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, + unsigned long *gl1mfn); + void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, + void *eff_l1e); + int (*guess_wrmap )(struct vcpu *v, + unsigned long vaddr, mfn_t gmfn); + /* For outsiders to tell what mode we're in */ + unsigned int shadow_levels; +}; + +/************************************************/ +/* common paging interface */ +/************************************************/ +struct paging_mode { + int (*page_fault )(struct vcpu *v, unsigned long va, + struct cpu_user_regs *regs); + int (*invlpg )(struct vcpu *v, unsigned long va); + paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va); + unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va); + void (*update_cr3 )(struct vcpu *v, int do_locking); + void (*update_paging_modes )(struct vcpu *v); + unsigned int guest_levels; + + /* paging support extension */ + struct shadow_paging_mode shadow; +}; + +/*************************************************/ +/* paging mode functions */ +/*************************************************/ +/* Is this vcpu using the P2M table to translate between GFNs and MFNs? + * + * This is true of translated HVM domains on a vcpu which has paging + * enabled. (HVM vcpus with paging disabled are using the p2m table as + * its paging table, so no translation occurs in this case.) + * It is also true for all vcpus of translated PV domains. */ +#define paging_vcpu_mode_translate(_v) ((_v)->arch.paging.translate_enabled) + + +/* Page fault handler + * Called from pagefault handler in Xen, and from the HVM trap handlers + * for pagefaults. Returns 1 if this fault was an artefact of the + * paging code (and the guest should retry) or 0 if it is not (and the + * fault should be handled elsewhere or passed to the guest). + * + * Note: under shadow paging, this function handles guest page fault; + * However, for hardware-assisted paging, this function handles host + * page fault (i.e. nested page fault). */ +static inline int +paging_fault(unsigned long va, struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + return v->arch.paging.mode->page_fault(v, va, regs); +} + +/* Handle invlpg requests on vcpus. + * Returns 1 if the invlpg instruction should be issued on the hardware, + * or 0 if it's safe not to do so. */ +static inline int paging_invlpg(struct vcpu *v, unsigned long va) +{ + return v->arch.paging.mode->invlpg(v, va); +} + +/* Translate a guest virtual address to the physical address that the + * *guest* pagetables would map it to. */ +static inline paddr_t paging_gva_to_gpa(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return (paddr_t) va; + + return v->arch.paging.mode->gva_to_gpa(v, va); +} + +/* Translate a guest virtual address to the frame number that the + * *guest* pagetables would map it to. */ +static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return va >> PAGE_SHIFT; + + return v->arch.paging.mode->gva_to_gfn(v, va); +} + +/* Update all the things that are derived from the guest's CR3. + * Called when the guest changes CR3; the caller can then use v->arch.cr3 + * as the value to load into the host CR3 to schedule this vcpu */ +static inline void paging_update_cr3(struct vcpu *v) +{ + v->arch.paging.mode->update_cr3(v, 1); +} + +/* Update all the things that are derived from the guest's CR0/CR3/CR4. + * Called to initialize paging structures if the paging mode + * has changed, and when bringing up a VCPU for the first time. */ +static inline void paging_update_paging_modes(struct vcpu *v) +{ + v->arch.paging.mode->update_paging_modes(v); +} + +/* initialize the paging resource for vcpu struct. It is called by + * vcpu_initialise() in domain.c */ +void paging_vcpu_init(struct vcpu *v); + +/************************************************/ +/* domain level paging functions */ +/************************************************/ +void paging_domain_init(struct domain *d); + +static inline int +paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE(void) u_domctl) +{ + return d->arch.paging.domctl(d, sc, u_domctl); +} + +static inline void paging_teardown(struct domain *d) +{ + d->arch.paging.teardown(d); +} + +static inline void paging_final_teardown(struct domain *d) +{ + d->arch.paging.final_teardown(d); +} +#endif /* XEN_PAGING_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */