KVM: MMU: large page update_pte issue with non-PAE 32-bit guests
kvm_mmu_pte_write() does not handle 32-bit non-PAE large page backed guests properly. It will instantiate two 2MB sptes pointing to the same physical 2MB page when a guest large pte update is trapped.
Instead of duplicating code to handle this, disallow directory level updates to happen through kvm_mmu_pte_write(), so the two 2MB sptes emulating one guest 4MB pte can be correctly created by the page fault handling path.
arch/x86/kvm/mmu.c +7 -5
@@ -1586,11 +1587,13 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu, u64 *spte, const void *new) { -if ((sp->role.level !=PT_PAGE_TABLE_LEVEL ) - && !vcpu->arch.update_pte.largepage) { - ++vcpu->kvm->stat.mmu_pde_zapped; -return ; - } +if (sp->role.level !=PT_PAGE_TABLE_LEVEL ) { +if (!vcpu->arch.update_pte.largepage || + sp->role.glevels ==PT32_ROOT_LEVEL ) { + ++vcpu->kvm->stat.mmu_pde_zapped; +return ; + } + } ++vcpu->kvm->stat.mmu_pte_updated;if (sp->role.glevels ==PT32_ROOT_LEVEL )
Quoted 9 lines · Marcelo Tosatti
kvm_mmu_pte_write()does not handle 32-bit non-PAE large page backed guests properly. It will instantiate two 2MB sptes pointing to the same physical 2MB page when a guest large pte update is trapped.Instead of duplicating code to handle this, disallow directory level updates to happen through
kvm_mmu_pte_write(), so the two 2MB sptes emulating one guest 4MB pte can be correctly created by the page fault handling path.
This fix reminded me of this stack trace I looked some time ago, it was also related to a 4M user pte IIRC, may they be related? In such a case we can should update the bug status.
http://sourceforge.net/tracker/index.php?func=detail&aid=1929279&group_id=180599&atid=893831
7916:Mar 30 11:18:59 hmf kernel: RIP: 0010:[<ffffffff8882c99d>] [<ffffffff8882c99d>] :kvm:rmap_remove+0x12d/0x1e0 7917:Mar 30 11:18:59 hmf kernel: RSP: 0018:ffff8100715a1a98 EFLAGS: 00010296
7918:Mar 30 11:18:59 hmf kernel: RAX: 0000000000000031 RBX: ffff810001a62f98 RCX: ffffffff80b04168 7919:Mar 30 11:18:59 hmf kernel: RDX: ffffffff80b04168 RSI: 0000000000000006 RDI: ffffffff80b04160 7920:Mar 30 11:18:59 hmf kernel: RBP: ffff810005fb2000 R08: 000000e1aeb7ed38 R09: 0000000000000000 7921:Mar 30 11:18:59 hmf kernel: R10: ffff810002c13b60 R11: 0000000000000001 R12: ffff810039518b30 7922:Mar 30 11:18:59 hmf kernel: R13: ffff81007cc78000 R14: 000000002f7b5063 R15: ffff810039518b30 7923:Mar 30 11:18:59 hmf kernel: FS: 00000000ffdff000(0000) GS:ffffffff80b8f000(0000) knlGS:0000000000000000 7924:Mar 30 11:18:59 hmf kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
7925:Mar 30 11:18:59 hmf kernel: CR2: 00002aaaaaafb000 CR3: 000000007dfc0000 CR4: 00000000000006e0 7926:Mar 30 11:18:59 hmf kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 7927:Mar 30 11:18:59 hmf kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 7928:Mar 30 11:18:59 hmf kernel: Process qemu-system-x86 (pid: 6262, threadinfo ffff8100715a0000, task ffff81000e90a810) 7929:Mar 30 11:18:59 hmf kernel: Stack: ffff810079af4fa0 0000000000000000 ffff810005fb2000 ffff81000e99c040 7930:Mar 30 11:18:59 hmf kernel: ffff81000e99c040 ffffffff8882e870 00000000040df863 ffffffff8882f3fe 7931:Mar 30 11:18:59 hmf kernel: ffff810000000001 000000000000000f 0000000000000000 00000000c0600000 7932:Mar 30 11:18:59 hmf kernel: Call Trace:
7933:Mar 30 11:18:59 hmf kernel: [<ffffffff8882e870>] :kvm:kvm_mmu_pte_write+0x220/0x850 7934:Mar 30 11:18:59 hmf kernel: [<ffffffff8882f3fe>] :kvm:paging64_walk_addr+0x29e/0x340 7935:Mar 30 11:18:59 hmf kernel: [<ffffffff88827cf4>] :kvm:__emulator_write_phys+0x44/0x70 7936:Mar 30 11:18:59 hmf kernel: [<ffffffff8882966a>] :kvm:emulator_write_emulated_onepage+0xba/0x150 7937:Mar 30 11:18:59 hmf kernel: [<ffffffff88831819>] :kvm:x86_emulate_insn+0x419/0x4430 7938:Mar 30 11:18:59 hmf kernel: [<ffffffff8884716b>] :kvm_amd:svm_get_segment+0xb/0xa0 7939:Mar 30 11:18:59 hmf kernel: [<ffffffff888264ee>] :kvm:kvm_get_cs_db_l_bits+0x1e/0x40 7940:Mar 30 11:18:59 hmf kernel: [<ffffffff88827b4f>] :kvm:emulate_instruction+0x1df/0x340 7941:Mar 30 11:18:59 hmf kernel: [<ffffffff8882e618>] :kvm:kvm_mmu_page_fault+0x58/0x90
Thanks!
Quoted 15 lines · Andrea Arcangeli
Quoted 9 lines · Marcelo Tosatti
kvm_mmu_pte_write()does not handle 32-bit non-PAE large page backed guests properly. It will instantiate two 2MB sptes pointing to the same physical 2MB page when a guest large pte update is trapped.Instead of duplicating code to handle this, disallow directory level updates to happen through
kvm_mmu_pte_write(), so the two 2MB sptes emulating one guest 4MB pte can be correctly created by the page fault handling path.This fix reminded me of this stack trace I looked some time ago, it was also related to a 4M user pte IIRC, may they be related? In such a case we can should update the bug status.
Quoted 5 lines
http://sourceforge.net/tracker/index.php?func=detail&aid=1929279&group_id=180599&atid=893831
7916:Mar 30 11:18:59 hmf kernel: RIP: 0010:[<ffffffff8882c99d>] [<
ffffffff8882c99d>] :kvm:rmap_remove+0x12d/0x1e0 7932:Mar 30 11:18:59 hmf kernel: Call Trace:
7933:Mar 30 11:18:59 hmf kernel: [<ffffffff8882e870>] :kvm:kvm_mmu_pte_write+0x220/0x850
Don't think it is related, the bug which patch fixes can only be triggered if the guest is large page backed, which does not seem to be the case of this bug report.
7909:Mar 30 11:18:59 hmf kernel: rmap_remove: ffff810005fb2000 2f7b5063 0->BUG
This seems to be a regular 4k shadow pte:
0x63 = PT_PRESENT|PT_WRITABLE|PT_ACCESSED|PT_DIRTY
Its tainted too: nvidia(P)