Commit 3af1817a authored by Lai Jiangshan's avatar Lai Jiangshan Committed by Avi Kivity

KVM: MMU: calculate correct gfn for small host pages backing large guest pages

In Documentation/kvm/mmu.txt:
  gfn:
    Either the guest page table containing the translations shadowed by this
    page, or the base page frame for linear translations. See role.direct.

But in function FNAME(fetch)(), sp->gfn is incorrect when one of following
situations occurred:

 1) guest is 32bit paging and the guest PDE maps a 4-MByte page
    (backed by 4k host pages), FNAME(fetch)() miss handling the quadrant.

    And if guest use pse-36, "table_gfn = gpte_to_gfn(gw->ptes[level - delta]);"
    is incorrect.

 2) guest is long mode paging and the guest PDPTE maps a 1-GByte page
    (backed by 4k or 2M host pages).

So we fix it to suit to the document and suit to the code which
requires sp->gfn correct when sp->role.direct=1.

We use the goal mapping gfn(gw->gfn) to calculate the base page frame
for linear translations, it is simple and easy to be understood.
Reported-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Reported-by: default avatarGui Jianfeng <guijianfeng@cn.fujitsu.com>
Signed-off-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent c9fa0b3b
...@@ -339,10 +339,13 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -339,10 +339,13 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
direct = 1; direct = 1;
if (!is_dirty_gpte(gw->ptes[level - delta])) if (!is_dirty_gpte(gw->ptes[level - delta]))
access &= ~ACC_WRITE_MASK; access &= ~ACC_WRITE_MASK;
table_gfn = gpte_to_gfn(gw->ptes[level - delta]); /*
/* advance table_gfn when emulating 1gb pages with 4k */ * It is a large guest pages backed by small host pages,
if (delta == 0) * So we set @direct(@shadow_page->role.direct)=1, and
table_gfn += PT_INDEX(addr, level); * set @table_gfn(@shadow_page->gfn)=the base page frame
* for linear translations.
*/
table_gfn = gw->gfn & ~(KVM_PAGES_PER_HPAGE(level) - 1);
access &= gw->pte_access; access &= gw->pte_access;
} else { } else {
direct = 0; direct = 0;
......
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