# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 28e9bba0342574ff971d1246f74d24009c897b36
# Parent d40dfbef8e5d37f89de3654843c1aefdc6462bad
[XEN] Work around a Linux PAE issue where it sometimes sets
the top half of a PTE without first clearing the bottom half
(to make the PTE not-present) hence the PTE fails validation
checks.
Also remove dead revalidation function after shadow2 checkin.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/mm.c | 75 +++++++++++++----------------------------------
xen/include/asm-x86/mm.h | 1
2 files changed, 21 insertions(+), 55 deletions(-)
diff -r d40dfbef8e5d -r 28e9bba03425 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Aug 18 15:22:54 2006 +0100
+++ b/xen/arch/x86/mm.c Fri Aug 18 15:24:10 2006 +0100
@@ -3050,56 +3050,6 @@ long arch_memory_op(int op, XEN_GUEST_HA
* Writable Pagetables
*/
-/* Re-validate a given p.t. page, given its prior snapshot */
-int revalidate_l1(
- struct domain *d, l1_pgentry_t *l1page, l1_pgentry_t *snapshot)
-{
- l1_pgentry_t ol1e, nl1e;
- int modified = 0, i;
-
- for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
- {
- ol1e = snapshot[i];
- nl1e = l1page[i];
-
- if ( likely(l1e_get_intpte(ol1e) == l1e_get_intpte(nl1e)) )
- continue;
-
- /* Update number of entries modified. */
- modified++;
-
- /*
- * Fast path for PTEs that have merely been write-protected
- * (e.g., during a Unix fork()). A strict reduction in privilege.
- */
- if ( likely(l1e_get_intpte(ol1e) == (l1e_get_intpte(nl1e)|_PAGE_RW)) )
- {
- if ( likely(l1e_get_flags(nl1e) & _PAGE_PRESENT) )
- put_page_type(mfn_to_page(l1e_get_pfn(nl1e)));
- continue;
- }
-
- if ( unlikely(!get_page_from_l1e(nl1e, d)) )
- {
- /*
- * Make the remaining p.t's consistent before crashing, so the
- * reference counts are correct.
- */
- memcpy(&l1page[i], &snapshot[i],
- (L1_PAGETABLE_ENTRIES - i) * sizeof(l1_pgentry_t));
-
- /* Crash the offending domain. */
- MEM_LOG("ptwr: Could not revalidate l1 page");
- domain_crash(d);
- break;
- }
-
- put_page_from_l1e(ol1e, d);
- }
-
- return modified;
-}
-
static int ptwr_emulated_update(
unsigned long addr,
paddr_t old,
@@ -3167,10 +3117,27 @@ static int ptwr_emulated_update(
nl1e = l1e_from_intpte(val);
if ( unlikely(!get_page_from_l1e(nl1e, d)) )
{
- MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
- return X86EMUL_UNHANDLEABLE;
- }
-
+ if ( (CONFIG_PAGING_LEVELS == 3) &&
+ (bytes == 4) &&
+ !do_cmpxchg &&
+ (l1e_get_flags(nl1e) & _PAGE_PRESENT) )
+ {
+ /*
+ * If this is a half-write to a PAE PTE then we assume that the
+ * guest has simply got the two writes the wrong way round. We
+ * zap the PRESENT bit on the assumption the bottom half will be
+ * written immediately after we return to the guest.
+ */
+ MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte"\n",
+ l1e_get_intpte(nl1e));
+ l1e_remove_flags(nl1e, _PAGE_PRESENT);
+ }
+ else
+ {
+ MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
+ return X86EMUL_UNHANDLEABLE;
+ }
+ }
/* Checked successfully: do the update (write or cmpxchg). */
pl1e = map_domain_page(page_to_mfn(page));
diff -r d40dfbef8e5d -r 28e9bba03425 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h Fri Aug 18 15:22:54 2006 +0100
+++ b/xen/include/asm-x86/mm.h Fri Aug 18 15:24:10 2006 +0100
@@ -397,7 +397,6 @@ void memguard_guard_stack(void *p);
int ptwr_do_page_fault(struct domain *, unsigned long,
struct cpu_user_regs *);
-int revalidate_l1(struct domain *, l1_pgentry_t *, l1_pgentry_t *);
int audit_adjust_pgtables(struct domain *d, int dir, int noisy);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|