Commit b554c560 authored by Andres Lagar-Cavilla's avatar Andres Lagar-Cavilla

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: default avatarAndres Lagar-Cavilla <andres@lagarcavilla.org>
Signed-off-by: default avatarTim Deegan <tim@xen.org>
Committed-by: default avatarTim Deegan <tim@xen.org>
parent 2f4d2702
......@@ -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:
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment