From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andres Lagar-Cavilla Subject: [PATCH] x86/mm/p2m-pt: Clip mfn to allowable width when building a PTE Date: Thu, 22 Mar 2012 14:17:43 -0400 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: keir@xen.org, andres@gridcentric.ca, tim@xen.org, JBeulich@suse.com List-Id: xen-devel@lists.xenproject.org xen/arch/x86/mm/p2m-pt.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) Otherwise, INVALID_MFN tramples over high order bits used for additional flags. Signed-off-by: Andres Lagar-Cavilla diff -r 642c0e6a01c2 -r d07ac807db6d xen/arch/x86/mm/p2m-pt.c --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -48,6 +48,13 @@ #undef page_to_mfn #define page_to_mfn(_pg) _mfn(__page_to_mfn(_pg)) +/* We may store INVALID_MFN in l1 PTEs. We need to clip this + * to avoid trampling over higher-order bits (NX, p2m type, IOMMU flags). We + * seem to not need to unclip on the return path, as callers are concerned only + * with p2m type in such cases. + */ +#define p2m_l1e_from_pfn(pfn, flags) \ + l1e_from_pfn((pfn) & (PADDR_MASK >> PAGE_SHIFT), (flags)) /* PTE flags for the various types of p2m entry */ #define P2M_BASE_FLAGS \ @@ -385,8 +392,8 @@ p2m_set_entry(struct p2m_domain *p2m, un ASSERT(p2m_entry); if ( mfn_valid(mfn) || (p2mt == p2m_mmio_direct) ) - entry_content = l1e_from_pfn(mfn_x(mfn), - p2m_type_to_flags(p2mt, mfn)); + entry_content = p2m_l1e_from_pfn(mfn_x(mfn), + p2m_type_to_flags(p2mt, mfn)); else entry_content = l1e_empty(); @@ -923,7 +930,7 @@ static void p2m_change_type_global(struc * L2_PAGETABLE_ENTRIES) * L1_PAGETABLE_ENTRIES; /* create a new 1le entry with the new type */ flags = p2m_type_to_flags(nt, _mfn(mfn)); - l1e_content = l1e_from_pfn(mfn, flags); + l1e_content = p2m_l1e_from_pfn(mfn, flags); p2m->write_p2m_entry(p2m, gfn, &l1e[i1], l1mfn, l1e_content, 1); }