aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/svm/nestedsvm.c2
-rw-r--r--xen/arch/x86/hvm/vmx/vvmx.c4
-rw-r--r--xen/arch/x86/mm/hap/nested_ept.c5
-rw-r--r--xen/arch/x86/mm/hap/nested_hap.c39
-rw-r--r--xen/include/asm-x86/hvm/hvm.h4
-rw-r--r--xen/include/asm-x86/hvm/svm/nestedsvm.h2
-rw-r--r--xen/include/asm-x86/hvm/vmx/vvmx.h6
7 files changed, 42 insertions, 20 deletions
diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c
index 0a7da95b86..dc8d382deb 100644
--- a/xen/arch/x86/hvm/svm/nestedsvm.c
+++ b/xen/arch/x86/hvm/svm/nestedsvm.c
@@ -1177,7 +1177,7 @@ nsvm_vmcb_hap_enabled(struct vcpu *v)
*/
int
nsvm_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
- unsigned int *page_order,
+ unsigned int *page_order, uint8_t *p2m_acc,
bool_t access_r, bool_t access_w, bool_t access_x)
{
uint32_t pfec;
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index fdf4f65e2c..b274e59ffa 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1532,7 +1532,7 @@ int nvmx_msr_write_intercept(unsigned int msr, u64 msr_content)
*/
int
nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
- unsigned int *page_order,
+ unsigned int *page_order, uint8_t *p2m_acc,
bool_t access_r, bool_t access_w, bool_t access_x)
{
int rc;
@@ -1542,7 +1542,7 @@ nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
uint32_t rwx_rights = (access_x << 2) | (access_w << 1) | access_r;
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
- rc = nept_translate_l2ga(v, L2_gpa, page_order, rwx_rights, &gfn,
+ rc = nept_translate_l2ga(v, L2_gpa, page_order, rwx_rights, &gfn, p2m_acc,
&exit_qual, &exit_reason);
switch ( rc )
{
diff --git a/xen/arch/x86/mm/hap/nested_ept.c b/xen/arch/x86/mm/hap/nested_ept.c
index bc72c97139..34d6f7f8bb 100644
--- a/xen/arch/x86/mm/hap/nested_ept.c
+++ b/xen/arch/x86/mm/hap/nested_ept.c
@@ -224,8 +224,8 @@ out:
int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga,
unsigned int *page_order, uint32_t rwx_acc,
- unsigned long *l1gfn, uint64_t *exit_qual,
- uint32_t *exit_reason)
+ unsigned long *l1gfn, uint8_t *p2m_acc,
+ uint64_t *exit_qual, uint32_t *exit_reason)
{
uint32_t rc, rwx_bits = 0;
ept_walk_t gw;
@@ -262,6 +262,7 @@ int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga,
if ( nept_permission_check(rwx_acc, rwx_bits) )
{
*l1gfn = gw.lxe[0].mfn;
+ *p2m_acc = (uint8_t)rwx_bits;
break;
}
rc = EPT_TRANSLATE_VIOLATION;
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index d73bfa2d05..e447117562 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -143,13 +143,13 @@ nestedhap_fix_p2m(struct vcpu *v, struct p2m_domain *p2m,
*/
static int
nestedhap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
- unsigned int *page_order,
+ unsigned int *page_order, uint8_t *p2m_acc,
bool_t access_r, bool_t access_w, bool_t access_x)
{
ASSERT(hvm_funcs.nhvm_hap_walk_L1_p2m);
return hvm_funcs.nhvm_hap_walk_L1_p2m(v, L2_gpa, L1_gpa, page_order,
- access_r, access_w, access_x);
+ p2m_acc, access_r, access_w, access_x);
}
@@ -159,16 +159,15 @@ nestedhap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
*/
static int
nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa,
- p2m_type_t *p2mt,
+ p2m_type_t *p2mt, p2m_access_t *p2ma,
unsigned int *page_order,
bool_t access_r, bool_t access_w, bool_t access_x)
{
mfn_t mfn;
- p2m_access_t p2ma;
int rc;
/* walk L0 P2M table */
- mfn = get_gfn_type_access(p2m, L1_gpa >> PAGE_SHIFT, p2mt, &p2ma,
+ mfn = get_gfn_type_access(p2m, L1_gpa >> PAGE_SHIFT, p2mt, p2ma,
0, page_order);
rc = NESTEDHVM_PAGEFAULT_MMIO;
@@ -207,12 +206,14 @@ nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
struct p2m_domain *p2m, *nested_p2m;
unsigned int page_order_21, page_order_10, page_order_20;
p2m_type_t p2mt_10;
+ p2m_access_t p2ma_10 = p2m_access_rwx;
+ uint8_t p2ma_21 = p2m_access_rwx;
p2m = p2m_get_hostp2m(d); /* L0 p2m */
nested_p2m = p2m_get_nestedp2m(v, nhvm_vcpu_p2m_base(v));
/* walk the L1 P2M table */
- rv = nestedhap_walk_L1_p2m(v, *L2_gpa, &L1_gpa, &page_order_21,
+ rv = nestedhap_walk_L1_p2m(v, *L2_gpa, &L1_gpa, &page_order_21, &p2ma_21,
access_r, access_w, access_x);
/* let caller to handle these two cases */
@@ -230,7 +231,7 @@ nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
/* ==> we have to walk L0 P2M */
rv = nestedhap_walk_L0_p2m(p2m, L1_gpa, &L0_gpa,
- &p2mt_10, &page_order_10,
+ &p2mt_10, &p2ma_10, &page_order_10,
access_r, access_w, access_x);
/* let upper level caller to handle these two cases */
@@ -251,10 +252,30 @@ nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
page_order_20 = min(page_order_21, page_order_10);
+ ASSERT(p2ma_10 <= p2m_access_n2rwx);
+ /*NOTE: if assert fails, needs to handle new access type here */
+
+ switch ( p2ma_10 )
+ {
+ case p2m_access_n ... p2m_access_rwx:
+ break;
+ case p2m_access_rx2rw:
+ p2ma_10 = p2m_access_rx;
+ break;
+ case p2m_access_n2rwx:
+ p2ma_10 = p2m_access_n;
+ break;
+ default:
+ p2ma_10 = p2m_access_n;
+ /* For safety, remove all permissions. */
+ gdprintk(XENLOG_ERR, "Unhandled p2m access type:%d\n", p2ma_10);
+ }
+ /* Use minimal permission for nested p2m. */
+ p2ma_10 &= (p2m_access_t)p2ma_21;
+
/* fix p2m_get_pagetable(nested_p2m) */
nestedhap_fix_p2m(v, nested_p2m, *L2_gpa, L0_gpa, page_order_20,
- p2mt_10,
- p2m_access_rwx /* FIXME: Should use minimum permission. */);
+ p2mt_10, p2ma_10);
return NESTEDHVM_PAGEFAULT_DONE;
}
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index f8c9222c2b..50e1f0a865 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -187,8 +187,8 @@ struct hvm_function_table {
/*Walk nested p2m */
int (*nhvm_hap_walk_L1_p2m)(struct vcpu *v, paddr_t L2_gpa,
paddr_t *L1_gpa, unsigned int *page_order,
- bool_t access_r, bool_t access_w,
- bool_t access_x);
+ uint8_t *p2m_acc, bool_t access_r,
+ bool_t access_w, bool_t access_x);
};
extern struct hvm_function_table hvm_funcs;
diff --git a/xen/include/asm-x86/hvm/svm/nestedsvm.h b/xen/include/asm-x86/hvm/svm/nestedsvm.h
index 4062bae8a1..167171483f 100644
--- a/xen/include/asm-x86/hvm/svm/nestedsvm.h
+++ b/xen/include/asm-x86/hvm/svm/nestedsvm.h
@@ -134,7 +134,7 @@ void svm_vmexit_do_clgi(struct cpu_user_regs *regs, struct vcpu *v);
void svm_vmexit_do_stgi(struct cpu_user_regs *regs, struct vcpu *v);
bool_t nestedsvm_gif_isset(struct vcpu *v);
int nsvm_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
- unsigned int *page_order,
+ unsigned int *page_order, uint8_t *p2m_acc,
bool_t access_r, bool_t access_w, bool_t access_x);
#define NSVM_INTR_NOTHANDLED 3
diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h b/xen/include/asm-x86/hvm/vmx/vvmx.h
index 5f92784b9c..d09be577a3 100644
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h
@@ -123,7 +123,7 @@ int nvmx_handle_vmxoff(struct cpu_user_regs *regs);
int
nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
- unsigned int *page_order,
+ unsigned int *page_order, uint8_t *p2m_acc,
bool_t access_r, bool_t access_w, bool_t access_x);
/*
* Virtual VMCS layout
@@ -208,7 +208,7 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga,
unsigned int *page_order, uint32_t rwx_acc,
- unsigned long *l1gfn, uint64_t *exit_qual,
- uint32_t *exit_reason);
+ unsigned long *l1gfn, uint8_t *p2m_acc,
+ uint64_t *exit_qual, uint32_t *exit_reason);
#endif /* __ASM_X86_HVM_VVMX_H__ */