[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Shadow-mode-refcount PTE update fix.
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxxx # Node ID f5121d001d1ad66165d67c96a6e1f8f18375b1c3 # Parent 245f7ce8763e2f4968a4f0ce2ac7022b0eddb723 [XEN] Shadow-mode-refcount PTE update fix. Add back in support for emulated PTE updates which is critical for shdow_refcount operation. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/mm/shadow/common.c | 328 +++++++++++++++++++++---------------- xen/arch/x86/mm/shadow/multi.c | 20 +- xen/arch/x86/mm/shadow/private.h | 11 - xen/include/asm-x86/guest_access.h | 16 - 4 files changed, 217 insertions(+), 158 deletions(-) diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Sat Dec 09 15:04:27 2006 +0000 +++ b/xen/arch/x86/mm/shadow/common.c Sat Dec 09 16:29:52 2006 +0000 @@ -185,15 +185,7 @@ hvm_read(enum x86_segment seg, // In this case, that is only a user vs supervisor access check. // if ( (rc = hvm_copy_from_guest_virt(val, addr, bytes)) == 0 ) - { -#if 0 - struct vcpu *v = current; - SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", - v->domain->domain_id, v->vcpu_id, - addr, *val, bytes); -#endif return X86EMUL_CONTINUE; - } /* If we got here, there was nothing mapped here, or a bad GFN * was mapped here. This should never happen: we're here because @@ -206,14 +198,202 @@ hvm_read(enum x86_segment seg, return X86EMUL_PROPAGATE_FAULT; } -void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt, - struct cpu_user_regs *regs) +static int +hvm_emulate_read(enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + return hvm_read(seg, offset, val, bytes, hvm_access_read, + container_of(ctxt, struct sh_emulate_ctxt, ctxt)); +} + +static int +hvm_emulate_insn_fetch(enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + unsigned int insn_off = offset - ctxt->regs->eip; + + /* Fall back if requested bytes are not in the prefetch cache. */ + if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) ) + return hvm_read(seg, offset, val, bytes, + hvm_access_insn_fetch, sh_ctxt); + + /* Hit the cache. Simple memcpy. */ + *val = 0; + memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes); + return X86EMUL_CONTINUE; +} + +static int +hvm_emulate_write(enum x86_segment seg, + unsigned long offset, + unsigned long val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + + return v->arch.shadow.mode->x86_emulate_write( + v, addr, &val, bytes, sh_ctxt); +} + +static int +hvm_emulate_cmpxchg(enum x86_segment seg, + unsigned long offset, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + + return v->arch.shadow.mode->x86_emulate_cmpxchg( + v, addr, old, new, bytes, sh_ctxt); +} + +static int +hvm_emulate_cmpxchg8b(enum x86_segment seg, + unsigned long offset, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + unsigned long addr; + int rc; + + rc = hvm_translate_linear_addr( + seg, offset, 8, hvm_access_write, sh_ctxt, &addr); + if ( rc ) + return rc; + + return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt); +} + +static struct x86_emulate_ops hvm_shadow_emulator_ops = { + .read = hvm_emulate_read, + .insn_fetch = hvm_emulate_insn_fetch, + .write = hvm_emulate_write, + .cmpxchg = hvm_emulate_cmpxchg, + .cmpxchg8b = hvm_emulate_cmpxchg8b, +}; + +static int +pv_emulate_read(enum x86_segment seg, + unsigned long offset, + unsigned long *val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + unsigned int rc; + + *val = 0; + if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 ) + { + propagate_page_fault(offset + bytes - rc, 0); /* read fault */ + return X86EMUL_PROPAGATE_FAULT; + } + + return X86EMUL_CONTINUE; +} + +static int +pv_emulate_write(enum x86_segment seg, + unsigned long offset, + unsigned long val, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + return v->arch.shadow.mode->x86_emulate_write( + v, offset, &val, bytes, sh_ctxt); +} + +static int +pv_emulate_cmpxchg(enum x86_segment seg, + unsigned long offset, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + return v->arch.shadow.mode->x86_emulate_cmpxchg( + v, offset, old, new, bytes, sh_ctxt); +} + +static int +pv_emulate_cmpxchg8b(enum x86_segment seg, + unsigned long offset, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct x86_emulate_ctxt *ctxt) +{ + struct sh_emulate_ctxt *sh_ctxt = + container_of(ctxt, struct sh_emulate_ctxt, ctxt); + struct vcpu *v = current; + return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt); +} + +static struct x86_emulate_ops pv_shadow_emulator_ops = { + .read = pv_emulate_read, + .insn_fetch = pv_emulate_read, + .write = pv_emulate_write, + .cmpxchg = pv_emulate_cmpxchg, + .cmpxchg8b = pv_emulate_cmpxchg8b, +}; + +struct x86_emulate_ops *shadow_init_emulation( + struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs) { struct segment_register *creg; struct vcpu *v = current; unsigned long addr; sh_ctxt->ctxt.regs = regs; + + if ( !is_hvm_vcpu(v) ) + { + sh_ctxt->ctxt.mode = X86EMUL_MODE_HOST; + return &pv_shadow_emulator_ops; + } /* Segment cache initialisation. Primed with CS. */ sh_ctxt->valid_seg_regs = 0; @@ -237,131 +417,9 @@ void shadow_init_emulation(struct sh_emu !hvm_copy_from_guest_virt( sh_ctxt->insn_buf, addr, sizeof(sh_ctxt->insn_buf))) ? sizeof(sh_ctxt->insn_buf) : 0; -} - -static int -sh_x86_emulate_read(enum x86_segment seg, - unsigned long offset, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - return hvm_read(seg, offset, val, bytes, hvm_access_read, - container_of(ctxt, struct sh_emulate_ctxt, ctxt)); -} - -static int -sh_x86_emulate_insn_fetch(enum x86_segment seg, - unsigned long offset, - unsigned long *val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct sh_emulate_ctxt *sh_ctxt = - container_of(ctxt, struct sh_emulate_ctxt, ctxt); - unsigned int insn_off = offset - ctxt->regs->eip; - - /* Fall back if requested bytes are not in the prefetch cache. */ - if ( unlikely((insn_off + bytes) > sh_ctxt->insn_buf_bytes) ) - return hvm_read(seg, offset, val, bytes, - hvm_access_insn_fetch, sh_ctxt); - - /* Hit the cache. Simple memcpy. */ - *val = 0; - memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes); - return X86EMUL_CONTINUE; -} - -static int -sh_x86_emulate_write(enum x86_segment seg, - unsigned long offset, - unsigned long val, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct sh_emulate_ctxt *sh_ctxt = - container_of(ctxt, struct sh_emulate_ctxt, ctxt); - struct vcpu *v = current; - unsigned long addr; - int rc; - - rc = hvm_translate_linear_addr( - seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); - if ( rc ) - return rc; - -#if 0 - SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", - v->domain->domain_id, v->vcpu_id, addr, val, bytes); -#endif - return v->arch.shadow.mode->x86_emulate_write( - v, addr, &val, bytes, sh_ctxt); -} - -static int -sh_x86_emulate_cmpxchg(enum x86_segment seg, - unsigned long offset, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct x86_emulate_ctxt *ctxt) -{ - struct sh_emulate_ctxt *sh_ctxt = - container_of(ctxt, struct sh_emulate_ctxt, ctxt); - struct vcpu *v = current; - unsigned long addr; - int rc; - - rc = hvm_translate_linear_addr( - seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); - if ( rc ) - return rc; - -#if 0 - SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx n:=%#lx bytes=%u\n", - v->domain->domain_id, v->vcpu_id, addr, old, new, bytes); -#endif - return v->arch.shadow.mode->x86_emulate_cmpxchg( - v, addr, old, new, bytes, sh_ctxt); -} - -static int -sh_x86_emulate_cmpxchg8b(enum x86_segment seg, - unsigned long offset, - unsigned long old_lo, - unsigned long old_hi, - unsigned long new_lo, - unsigned long new_hi, - struct x86_emulate_ctxt *ctxt) -{ - struct sh_emulate_ctxt *sh_ctxt = - container_of(ctxt, struct sh_emulate_ctxt, ctxt); - struct vcpu *v = current; - unsigned long addr; - int rc; - - rc = hvm_translate_linear_addr( - seg, offset, 8, hvm_access_write, sh_ctxt, &addr); - if ( rc ) - return rc; - -#if 0 - SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx:%lx n:=%#lx:%lx\n", - v->domain->domain_id, v->vcpu_id, addr, old_hi, old_lo, - new_hi, new_lo, ctxt); -#endif - return v->arch.shadow.mode->x86_emulate_cmpxchg8b( - v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt); -} - - -struct x86_emulate_ops shadow_emulator_ops = { - .read = sh_x86_emulate_read, - .insn_fetch = sh_x86_emulate_insn_fetch, - .write = sh_x86_emulate_write, - .cmpxchg = sh_x86_emulate_cmpxchg, - .cmpxchg8b = sh_x86_emulate_cmpxchg8b, -}; + + return &hvm_shadow_emulator_ops; +} /**************************************************************************/ /* Code for "promoting" a guest page to the point where the shadow code is diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Sat Dec 09 15:04:27 2006 +0000 +++ b/xen/arch/x86/mm/shadow/multi.c Sat Dec 09 16:29:52 2006 +0000 @@ -2585,6 +2585,7 @@ static int sh_page_fault(struct vcpu *v, shadow_l1e_t sl1e, *ptr_sl1e; paddr_t gpa; struct sh_emulate_ctxt emul_ctxt; + struct x86_emulate_ops *emul_ops; int r, mmio; fetch_type_t ft = 0; @@ -2811,13 +2812,14 @@ static int sh_page_fault(struct vcpu *v, return EXCRET_fault_fixed; emulate: - if ( !is_hvm_domain(d) || !guest_mode(regs) ) + if ( !shadow_mode_refcounts(d) || !guest_mode(regs) ) goto not_a_shadow_fault; - hvm_store_cpu_guest_regs(v, regs, NULL); + if ( is_hvm_domain(d) ) + hvm_store_cpu_guest_regs(v, regs, NULL); SHADOW_PRINTK("emulate: eip=%#lx\n", regs->eip); - shadow_init_emulation(&emul_ctxt, regs); + emul_ops = shadow_init_emulation(&emul_ctxt, regs); /* * We do not emulate user writes. Instead we use them as a hint that the @@ -2825,7 +2827,7 @@ static int sh_page_fault(struct vcpu *v, * it seems very unlikely that any OS grants user access to page tables. */ if ( (regs->error_code & PFEC_user_mode) || - x86_emulate_memop(&emul_ctxt.ctxt, &shadow_emulator_ops) ) + x86_emulate_memop(&emul_ctxt.ctxt, emul_ops) ) { SHADOW_PRINTK("emulator failure, unshadowing mfn %#lx\n", mfn_x(gmfn)); @@ -2837,7 +2839,8 @@ static int sh_page_fault(struct vcpu *v, } /* Emulator has changed the user registers: write back */ - hvm_load_cpu_guest_regs(v, regs); + if ( is_hvm_domain(d) ) + hvm_load_cpu_guest_regs(v, regs); goto done; mmio: @@ -3814,9 +3817,10 @@ static inline void * emulate_map_dest(st page_fault: errcode |= PFEC_write_access; - if ( ring_3(sh_ctxt->ctxt.regs) ) - errcode |= PFEC_user_mode; - hvm_inject_exception(TRAP_page_fault, errcode, vaddr); + if ( is_hvm_vcpu(v) ) + hvm_inject_exception(TRAP_page_fault, errcode, vaddr); + else + propagate_page_fault(vaddr, errcode); return NULL; } diff -r 245f7ce8763e -r f5121d001d1a xen/arch/x86/mm/shadow/private.h --- a/xen/arch/x86/mm/shadow/private.h Sat Dec 09 15:04:27 2006 +0000 +++ b/xen/arch/x86/mm/shadow/private.h Sat Dec 09 16:29:52 2006 +0000 @@ -257,9 +257,6 @@ static inline int sh_type_is_pinnable(st * Various function declarations */ -/* x86 emulator support */ -extern struct x86_emulate_ops shadow_emulator_ops; - /* Hash table functions */ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t); void shadow_hash_insert(struct vcpu *v, @@ -513,17 +510,17 @@ struct sh_emulate_ctxt { struct sh_emulate_ctxt { struct x86_emulate_ctxt ctxt; - /* Cache of up to 15 bytes of instruction. */ + /* [HVM] Cache of up to 15 bytes of instruction. */ uint8_t insn_buf[15]; uint8_t insn_buf_bytes; - /* Cache of segment registers already gathered for this emulation. */ + /* [HVM] Cache of segment registers already gathered for this emulation. */ unsigned int valid_seg_regs; struct segment_register seg_reg[6]; }; -void shadow_init_emulation(struct sh_emulate_ctxt *sh_ctxt, - struct cpu_user_regs *regs); +struct x86_emulate_ops *shadow_init_emulation( + struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs); #endif /* _XEN_SHADOW_PRIVATE_H */ diff -r 245f7ce8763e -r f5121d001d1a xen/include/asm-x86/guest_access.h --- a/xen/include/asm-x86/guest_access.h Sat Dec 09 15:04:27 2006 +0000 +++ b/xen/include/asm-x86/guest_access.h Sat Dec 09 16:29:52 2006 +0000 @@ -34,7 +34,7 @@ #define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ }) @@ -46,7 +46,7 @@ #define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x+(off), sizeof(*_x)*(nr)) :\ copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ }) @@ -55,7 +55,7 @@ #define copy_field_to_guest(hnd, ptr, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ copy_to_user(_x, _y, sizeof(*_x)); \ }) @@ -64,7 +64,7 @@ #define copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x, sizeof(*_x)) : \ copy_from_user(_y, _x, sizeof(*_x)); \ }) @@ -80,7 +80,7 @@ #define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ }) @@ -88,7 +88,7 @@ #define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x+(off),sizeof(*_x)*(nr)) : \ __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ }) @@ -96,7 +96,7 @@ #define __copy_field_to_guest(hnd, ptr, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ __copy_to_user(_x, _y, sizeof(*_x)); \ }) @@ -104,7 +104,7 @@ #define __copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - shadow_mode_translate(current->domain) ? \ + is_hvm_vcpu(current) ? \ copy_from_user_hvm(_x, _y, sizeof(*_x)) : \ __copy_from_user(_y, _x, sizeof(*_x)); \ }) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |