# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1166615697 0
# Node ID caa1987679bddcb330e87adf787936ab94162e8d
# Parent f7a2cd8b0a8e03e94babc88c9c25fb5008f7a125
[XEN] Skip shadowing of guest PTE writes when known to be safe
That is, when the guest replaces a not-present pte with another one
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
xen/arch/x86/mm/shadow/multi.c | 49 +++++++++++++++++++++++++++++++++++----
xen/arch/x86/mm/shadow/private.h | 4 +++
xen/include/asm-x86/shadow.h | 5 ++-
3 files changed, 51 insertions(+), 7 deletions(-)
diff -r f7a2cd8b0a8e -r caa1987679bd xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Wed Dec 20 11:53:01 2006 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c Wed Dec 20 11:54:57 2006 +0000
@@ -3839,12 +3839,43 @@ static inline void * emulate_map_dest(st
return NULL;
}
+static int safe_not_to_verify_write(mfn_t gmfn, void *dst, void *src,
+ int bytes)
+{
+#if (SHADOW_OPTIMIZATIONS & SHOPT_SKIP_VERIFY)
+ struct page_info *pg = mfn_to_page(gmfn);
+ if ( !(pg->shadow_flags & SHF_32)
+ && bytes == 4
+ && ((unsigned long)dst & 3) == 0 )
+ {
+ /* Not shadowed 32-bit: aligned 64-bit writes that leave the
+ * present bit unset are safe to ignore. */
+ if ( (*(u64*)src & _PAGE_PRESENT) == 0
+ && (*(u64*)dst & _PAGE_PRESENT) == 0 )
+ return 1;
+ }
+ else if ( !(pg->shadow_flags & (SHF_PAE|SHF_64))
+ && bytes == 8
+ && ((unsigned long)dst & 7) == 0 )
+ {
+ /* Not shadowed PAE/64-bit: aligned 32-bit writes that leave the
+ * present bit unset are safe to ignore. */
+ if ( (*(u32*)src & _PAGE_PRESENT) == 0
+ && (*(u32*)dst & _PAGE_PRESENT) == 0 )
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+
int
sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src,
u32 bytes, struct sh_emulate_ctxt *sh_ctxt)
{
mfn_t mfn;
void *addr;
+ int skip;
if ( vaddr & (bytes-1) )
return X86EMUL_UNHANDLEABLE;
@@ -3855,8 +3886,9 @@ sh_x86_emulate_write(struct vcpu *v, uns
if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL )
return X86EMUL_PROPAGATE_FAULT;
+ skip = safe_not_to_verify_write(mfn, addr, src, bytes);
memcpy(addr, src, bytes);
- shadow_validate_guest_pt_write(v, mfn, addr, bytes);
+ if ( !skip ) shadow_validate_guest_pt_write(v, mfn, addr, bytes);
/* If we are writing zeros to this page, might want to unshadow */
if ( likely(bytes >= 4) && (*(u32 *)addr == 0) )
@@ -3875,7 +3907,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
mfn_t mfn;
void *addr;
unsigned long prev;
- int rv = X86EMUL_CONTINUE;
+ int rv = X86EMUL_CONTINUE, skip;
ASSERT(shadow_locked_by_me(v->domain));
ASSERT(bytes <= sizeof(unsigned long));
@@ -3885,6 +3917,8 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL )
return X86EMUL_PROPAGATE_FAULT;
+
+ skip = safe_not_to_verify_write(mfn, &new, &old, bytes);
switch ( bytes )
{
@@ -3898,7 +3932,9 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
}
if ( prev == old )
- shadow_validate_guest_pt_write(v, mfn, addr, bytes);
+ {
+ if ( !skip ) shadow_validate_guest_pt_write(v, mfn, addr, bytes);
+ }
else
rv = X86EMUL_CMPXCHG_FAILED;
@@ -3924,7 +3960,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
mfn_t mfn;
void *addr;
u64 old, new, prev;
- int rv = X86EMUL_CONTINUE;
+ int rv = X86EMUL_CONTINUE, skip;
ASSERT(shadow_locked_by_me(v->domain));
@@ -3936,10 +3972,13 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
old = (((u64) old_hi) << 32) | (u64) old_lo;
new = (((u64) new_hi) << 32) | (u64) new_lo;
+ skip = safe_not_to_verify_write(mfn, &new, &old, 8);
prev = cmpxchg(((u64 *)addr), old, new);
if ( prev == old )
- shadow_validate_guest_pt_write(v, mfn, addr, 8);
+ {
+ if ( !skip ) shadow_validate_guest_pt_write(v, mfn, addr, 8);
+ }
else
rv = X86EMUL_CMPXCHG_FAILED;
diff -r f7a2cd8b0a8e -r caa1987679bd xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h Wed Dec 20 11:53:01 2006 +0000
+++ b/xen/arch/x86/mm/shadow/private.h Wed Dec 20 11:54:57 2006 +0000
@@ -249,6 +249,10 @@ static inline int sh_type_is_pinnable(st
#define SHF_L3_64 (1u << SH_type_l3_64_shadow)
#define SHF_L4_64 (1u << SH_type_l4_64_shadow)
+#define SHF_32 (SHF_L1_32|SHF_FL1_32|SHF_L2_32)
+#define SHF_PAE (SHF_L1_PAE|SHF_FL1_PAE|SHF_L2_PAE|SHF_L2H_PAE)
+#define SHF_64 (SHF_L1_64|SHF_FL1_64|SHF_L2_64|SHF_L3_64|SHF_L4_64)
+
/* Used for hysteresis when automatically unhooking mappings on fork/exit */
#define SHF_unhooked_mappings (1u<<31)
diff -r f7a2cd8b0a8e -r caa1987679bd xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h Wed Dec 20 11:53:01 2006 +0000
+++ b/xen/include/asm-x86/shadow.h Wed Dec 20 11:54:57 2006 +0000
@@ -159,8 +159,9 @@ extern int shadow_audit_enable;
#define SHOPT_FAST_FAULT_PATH 0x04 /* Fast-path MMIO and not-present */
#define SHOPT_PREFETCH 0x08 /* Shadow multiple entries per fault */
#define SHOPT_LINUX_L3_TOPLEVEL 0x10 /* Pin l3es on early 64bit linux */
-
-#define SHADOW_OPTIMIZATIONS 0x1f
+#define SHOPT_SKIP_VERIFY 0x20 /* Skip PTE v'fy when safe to do so */
+
+#define SHADOW_OPTIMIZATIONS 0x3f
/* With shadow pagetables, the different kinds of address start
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|