aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/paging.h
diff options
context:
space:
mode:
authorcegger <none@none>2011-04-05 15:44:09 +0200
committercegger <none@none>2011-04-05 15:44:09 +0200
commitdd6de3ab99855dfac06633814a52c263726668c1 (patch)
tree5c6f796611e27676772e714066c83b9ace69e7ad /xen/include/asm-x86/paging.h
parente006a0e0aaae4e70e86238afcbd964de5af84dfc (diff)
downloadxen-dd6de3ab99855dfac06633814a52c263726668c1.tar.gz
xen-dd6de3ab99855dfac06633814a52c263726668c1.tar.bz2
xen-dd6de3ab99855dfac06633814a52c263726668c1.zip
Implement Nested-on-Nested.
This allows the guest to run nested guest with hap enabled. Signed-off-by: Christoph Egger <Christoph.Egger@amd.com> Acked-by: Tim Deegan <Tim.Deegan@citrix.com> Committed-by: Tim Deegan <Tim.Deegan@citrix.com>
Diffstat (limited to 'xen/include/asm-x86/paging.h')
-rw-r--r--xen/include/asm-x86/paging.h75
1 files changed, 47 insertions, 28 deletions
diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h
index a176c96877..b408e41273 100644
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -108,8 +108,14 @@ 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);
- unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va,
+ unsigned long (*gva_to_gfn )(struct vcpu *v,
+ struct p2m_domain *p2m,
+ unsigned long va,
uint32_t *pfec);
+ unsigned long (*p2m_ga_to_gfn )(struct vcpu *v,
+ struct p2m_domain *p2m,
+ unsigned long cr3,
+ paddr_t ga, uint32_t *pfec);
void (*update_cr3 )(struct vcpu *v, int do_locking);
void (*update_paging_modes )(struct vcpu *v);
void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn,
@@ -219,6 +225,10 @@ void paging_final_teardown(struct domain *d);
* creation. */
int paging_enable(struct domain *d, u32 mode);
+#define paging_get_hostmode(v) ((v)->arch.paging.mode)
+#define paging_get_nestedmode(v) ((v)->arch.paging.nestedmode)
+const struct paging_mode *paging_get_mode(struct vcpu *v);
+void paging_update_nestedmode(struct vcpu *v);
/* Page fault handler
* Called from pagefault handler in Xen, and from the HVM trap handlers
@@ -233,7 +243,7 @@ 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);
+ return paging_get_hostmode(v)->page_fault(v, va, regs);
}
/* Handle invlpg requests on vcpus.
@@ -241,7 +251,7 @@ paging_fault(unsigned long va, struct cpu_user_regs *regs)
* 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);
+ return paging_get_hostmode(v)->invlpg(v, va);
}
/* Translate a guest virtual address to the frame number that the
@@ -251,11 +261,30 @@ static inline int paging_invlpg(struct vcpu *v, unsigned long va)
* walking the tables. The caller should set the PFEC_page_present bit
* in pfec[0]; in the failure case, that bit will be cleared if appropriate. */
#define INVALID_GFN (-1UL)
-static inline unsigned long paging_gva_to_gfn(struct vcpu *v,
- unsigned long va,
- uint32_t *pfec)
+unsigned long paging_gva_to_gfn(struct vcpu *v,
+ unsigned long va,
+ uint32_t *pfec);
+
+/* Translates a guest virtual address to guest physical address
+ * where the specified cr3 is translated to host physical address
+ * using the specified p2m table.
+ * This allows to do page walks in the guest or even in the nested guest.
+ * It returns the guest's gfn or the nested guest's gfn.
+ * Use 'paddr_t' for the guest address so it won't overflow when
+ * guest or nested guest is in 32bit PAE mode.
+ */
+static inline unsigned long paging_p2m_ga_to_gfn(struct vcpu *v,
+ struct p2m_domain *p2m,
+ const struct paging_mode *mode,
+ unsigned long cr3,
+ paddr_t ga,
+ uint32_t *pfec)
{
- return v->arch.paging.mode->gva_to_gfn(v, va, pfec);
+ if ( is_hvm_domain(v->domain) && paging_mode_hap(v->domain) )
+ return mode->p2m_ga_to_gfn(v, p2m, cr3, ga, pfec);
+
+ /* shadow paging */
+ return paging_gva_to_gfn(v, ga, pfec);
}
/* Update all the things that are derived from the guest's CR3.
@@ -263,7 +292,7 @@ static inline unsigned long paging_gva_to_gfn(struct vcpu *v,
* 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);
+ paging_get_hostmode(v)->update_cr3(v, 1);
}
/* Update all the things that are derived from the guest's CR0/CR3/CR4.
@@ -271,7 +300,7 @@ static inline void paging_update_cr3(struct vcpu *v)
* 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);
+ paging_get_hostmode(v)->update_paging_modes(v);
}
@@ -283,7 +312,7 @@ static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p,
{
if ( unlikely(paging_mode_enabled(v->domain)
&& v->arch.paging.mode != NULL) )
- return v->arch.paging.mode->write_guest_entry(v, p, new, gmfn);
+ return paging_get_hostmode(v)->write_guest_entry(v, p, new, gmfn);
else
return (!__copy_to_user(p, &new, sizeof(new)));
}
@@ -299,7 +328,7 @@ static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
{
if ( unlikely(paging_mode_enabled(v->domain)
&& v->arch.paging.mode != NULL) )
- return v->arch.paging.mode->cmpxchg_guest_entry(v, p, old, new, gmfn);
+ return paging_get_hostmode(v)->cmpxchg_guest_entry(v, p, old, new, gmfn);
else
return (!cmpxchg_user(p, *old, new));
}
@@ -327,21 +356,11 @@ static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new)
* a pointer to the entry to be written, the MFN in which the entry resides,
* the new contents of the entry, and the level in the p2m tree at which
* we are writing. */
-static inline void paging_write_p2m_entry(struct domain *d, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn,
- l1_pgentry_t new, unsigned int level)
-{
- struct vcpu *v = current;
- if ( v->domain != d )
- v = d->vcpu ? d->vcpu[0] : NULL;
- if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
- {
- return v->arch.paging.mode->write_p2m_entry(v, gfn, p, table_mfn,
- new, level);
- }
- else
- safe_write_pte(p, new);
-}
+struct p2m_domain;
+
+void paging_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
+ l1_pgentry_t *p, mfn_t table_mfn,
+ l1_pgentry_t new, unsigned int level);
/* Called from the guest to indicate that the a process is being
* torn down and its pagetables will soon be discarded */
@@ -362,7 +381,7 @@ guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn)
l2_pgentry_t l2e;
if ( unlikely(paging_mode_translate(v->domain)) )
- return v->arch.paging.mode->guest_map_l1e(v, addr, gl1mfn);
+ return paging_get_hostmode(v)->guest_map_l1e(v, addr, gl1mfn);
/* Find this l1e and its enclosing l1mfn in the linear map */
if ( __copy_from_user(&l2e,
@@ -398,7 +417,7 @@ guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e)
return;
}
- v->arch.paging.mode->guest_get_eff_l1e(v, addr, eff_l1e);
+ paging_get_hostmode(v)->guest_get_eff_l1e(v, addr, eff_l1e);
}
/* Read the guest's l1e that maps this address, from the kernel-mode