ia64/xen-unstable
changeset 18830:c2a018cdb45d
Fix PSE PAT handling in guest walk.
Guest walk was currently checking for _PAGE_PSE_PAT flag in
guest_l2e_get_flags(). The problem is that this function only checks
for the first 12 bits of the PDE, while _PAGE_PSE_PAT is actually on bit
12 (that is the 13th bit). This caused _PAGE_PAT bit to never been set on
splintered L1s.
Signed-off-by: Gianluca Guida <gianluca.guida@eu.citrix.com>
Guest walk was currently checking for _PAGE_PSE_PAT flag in
guest_l2e_get_flags(). The problem is that this function only checks
for the first 12 bits of the PDE, while _PAGE_PSE_PAT is actually on bit
12 (that is the 13th bit). This caused _PAGE_PAT bit to never been set on
splintered L1s.
Signed-off-by: Gianluca Guida <gianluca.guida@eu.citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Tue Nov 25 11:17:57 2008 +0000 (2008-11-25) |
parents | e7c421510be9 |
children | b3265ff6c613 4ccee1299bc7 |
files | xen/arch/x86/mm/guest_walk.c |
line diff
1.1 --- a/xen/arch/x86/mm/guest_walk.c Mon Nov 24 13:57:48 2008 +0000 1.2 +++ b/xen/arch/x86/mm/guest_walk.c Tue Nov 25 11:17:57 2008 +0000 1.3 @@ -193,15 +193,15 @@ guest_walk_tables(struct vcpu *v, unsign 1.4 * access controls are enforced in the shadow l2e. */ 1.5 int flags = (_PAGE_PRESENT|_PAGE_USER|_PAGE_RW| 1.6 _PAGE_ACCESSED|_PAGE_DIRTY); 1.7 - /* PSE level 2 entries use bit 12 for PAT; propagate it to bit 7 1.8 - * of the level 1. */ 1.9 - if ( (guest_l2e_get_flags(gw->l2e) & _PAGE_PSE_PAT) ) 1.10 - flags |= _PAGE_PAT; 1.11 - /* Copy the cache-control bits to the l1 as well, because we 1.12 - * can't represent PAT in the (non-PSE) shadow l2e. :( 1.13 - * This could cause problems if a guest ever maps an area of 1.14 - * memory with superpages using more than one caching mode. */ 1.15 - flags |= guest_l2e_get_flags(gw->l2e) & (_PAGE_PWT|_PAGE_PCD); 1.16 + /* Import cache-control bits. Note that _PAGE_PAT is actually 1.17 + * _PAGE_PSE, and it is always set. We will clear it in case 1.18 + * _PAGE_PSE_PAT (bit 12, i.e. first bit of gfn) is clear. */ 1.19 + flags |= (guest_l2e_get_flags(gw->l2e) 1.20 + & (_PAGE_PAT|_PAGE_PWT|_PAGE_PCD)); 1.21 + if ( !(gfn_x(start) & 1) ) 1.22 + /* _PAGE_PSE_PAT not set: remove _PAGE_PAT from flags. */ 1.23 + flags &= ~_PAGE_PAT; 1.24 + 1.25 /* Increment the pfn by the right number of 4k pages. 1.26 * The ~0x1 is to mask out the PAT bit mentioned above. */ 1.27 start = _gfn((gfn_x(start) & ~0x1) + guest_l1_table_offset(va));