aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/mm
diff options
context:
space:
mode:
authorZhang Xiantao <xiantao.zhang@intel.com>2013-01-15 11:28:23 +0100
committerZhang Xiantao <xiantao.zhang@intel.com>2013-01-15 11:28:23 +0100
commit073c2ea3084bf78d324ad8b4f360f6297c57185d (patch)
treeb878180557136a31cf5b213c547725ff60bbcac3 /xen/arch/x86/mm
parent89f366ba53f52b1a2b0d16c47ac275372ce86ebb (diff)
downloadxen-073c2ea3084bf78d324ad8b4f360f6297c57185d.tar.gz
xen-073c2ea3084bf78d324ad8b4f360f6297c57185d.tar.bz2
xen-073c2ea3084bf78d324ad8b4f360f6297c57185d.zip
nEPT: Use minimal permission for nested p2m
Emulate permission check for the nested p2m. Current solution is to use minimal permission, and once meet permission violation in L0, then determin whether it is caused by guest EPT or host EPT Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com> Acked-by: Tim Deegan <tim@xen.org> Acked-by: Jun Nakajima <jun.nakajima@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com> Committed-by: Jan Beulich <jbeulich@suse.com>
Diffstat (limited to 'xen/arch/x86/mm')
-rw-r--r--xen/arch/x86/mm/hap/nested_ept.c5
-rw-r--r--xen/arch/x86/mm/hap/nested_hap.c39
2 files changed, 33 insertions, 11 deletions
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;
}