diff options
author | Andres Lagar-Cavilla <andres@lagarcavilla.org> | 2012-02-16 15:43:02 +0000 |
---|---|---|
committer | Andres Lagar-Cavilla <andres@lagarcavilla.org> | 2012-02-16 15:43:02 +0000 |
commit | 5cf63642892bbb673a576475c2a223c7caef169d (patch) | |
tree | 5fc9c09084df377eb85d2c481f620ea2dabb619b | |
parent | 5167dea268bb2e9174e18e9c1ff01de18a2b6ec6 (diff) | |
download | xen-5cf63642892bbb673a576475c2a223c7caef169d.tar.gz xen-5cf63642892bbb673a576475c2a223c7caef169d.tar.bz2 xen-5cf63642892bbb673a576475c2a223c7caef169d.zip |
x86/mm: Fix two PAE+paging bugs
In hap_paging_update_modes, we were getting the gpa of the cr3, rather
than the gfn.
Vmx_load_pdptrs was crashing the host if the cr3 is paged out. Now it
will only crash the guest.
Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org>
Signed-off-by: Tim Deegan <tim@xen.org>
Committed-by: Tim Deegan <tim@xen.org>
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 16 | ||||
-rw-r--r-- | xen/arch/x86/mm/hap/hap.c | 2 |
2 files changed, 14 insertions, 4 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0f65334bbd..61d1fda54d 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1010,12 +1010,22 @@ static void vmx_load_pdptrs(struct vcpu *v) if ( (cr3 & 0x1fUL) && !hvm_pcid_enabled(v) ) goto crash; - mfn = mfn_x(get_gfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt)); - if ( !p2m_is_ram(p2mt) ) + mfn = mfn_x(get_gfn_unshare(v->domain, cr3 >> PAGE_SHIFT, &p2mt)); + if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) || + /* If we didn't succeed in unsharing, get_page will fail + * (page still belongs to dom_cow) */ + !get_page(mfn_to_page(mfn), v->domain) ) { + /* Ideally you don't want to crash but rather go into a wait + * queue, but this is the wrong place. We're holding at least + * the paging lock */ + gdprintk(XENLOG_ERR, + "Bad cr3 on load pdptrs gfn %lx mfn %lx type %d\n", + cr3 >> PAGE_SHIFT, mfn, (int) p2mt); put_gfn(v->domain, cr3 >> PAGE_SHIFT); goto crash; } + put_gfn(v->domain, cr3 >> PAGE_SHIFT); p = map_domain_page(mfn); @@ -1043,7 +1053,7 @@ static void vmx_load_pdptrs(struct vcpu *v) vmx_vmcs_exit(v); unmap_domain_page(p); - put_gfn(v->domain, cr3 >> PAGE_SHIFT); + put_page(mfn_to_page(mfn)); return; crash: diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index debaba4f9e..9efb801ae8 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -786,7 +786,7 @@ hap_paging_get_mode(struct vcpu *v) static void hap_update_paging_modes(struct vcpu *v) { struct domain *d = v->domain; - unsigned long cr3_gfn = v->arch.hvm_vcpu.guest_cr[3]; + unsigned long cr3_gfn = v->arch.hvm_vcpu.guest_cr[3] >> PAGE_SHIFT; p2m_type_t t; /* We hold onto the cr3 as it may be modified later, and |