From: James Hogan <james.hogan@imgtec.com> To: <linux-mips@linux-mips.org> Cc: "James Hogan" <james.hogan@imgtec.com>, "Paolo Bonzini" <pbonzini@redhat.com>, "Radim Krčmář" <rkrcmar@redhat.com>, "Ralf Baechle" <ralf@linux-mips.org>, kvm@vger.kernel.org Subject: [PATCH 10/13] KVM: MIPS/MMU: Pass GPA PTE bits to KSeg0 GVA PTEs Date: Mon, 16 Jan 2017 12:49:31 +0000 [thread overview] Message-ID: <555238b387306895a8285cf719f3e9c6e520edde.1484570878.git-series.james.hogan@imgtec.com> (raw) In-Reply-To: <cover.99eec1b2ac935212acbcf2effacaab95cf6cdbf1.1484570878.git-series.james.hogan@imgtec.com> Propagate the GPA PTE protection bits on to the GVA PTEs on a KSeg0 fault (except _PAGE_WRITE), rather than always overriding the protection. This allows dirty page tracking to work in KSeg0 as a clear dirty bit in the GPA PTE will propagate to the GVA PTEs. This makes it simpler to use a single kvm_mips_map_page() to obtain both the main GPA PTE and its buddy (which may be invalid), which also allows memory regions to be fully accessible when they don't start and end on a 2*PAGE_SIZE boundary. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org --- arch/mips/kvm/mmu.c | 49 ++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 7962eea4ebc3..9cc941864aa8 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -769,15 +769,27 @@ void kvm_mips_flush_gva_pt(pgd_t *pgd, enum kvm_mips_flush flags) } } +static pte_t kvm_mips_gpa_pte_to_gva_unmapped(pte_t pte) +{ + /* + * Don't leak writeable but clean entries from GPA page tables. We don't + * want the normal Linux tlbmod handler to handle dirtying when KVM + * accesses guest memory. + */ + if (!pte_dirty(pte)) + pte = pte_wrprotect(pte); + + return pte; +} + /* XXXKYMA: Must be called with interrupts disabled */ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, struct kvm_vcpu *vcpu, bool write_fault) { unsigned long gpa; - kvm_pfn_t pfn0, pfn1; - unsigned long vaddr; pte_t pte_gpa[2], *ptep_gva; + int idx; if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) { kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr); @@ -785,35 +797,26 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, return -1; } - /* Find host PFNs */ - - gpa = KVM_GUEST_CPHYSADDR(badvaddr & (PAGE_MASK << 1)); - vaddr = badvaddr & (PAGE_MASK << 1); - - if (kvm_mips_map_page(vcpu, gpa, write_fault, &pte_gpa[0], NULL) < 0) - return -1; - - if (kvm_mips_map_page(vcpu, gpa | PAGE_SIZE, write_fault, &pte_gpa[1], - NULL) < 0) + /* Get the GPA page table entry */ + gpa = KVM_GUEST_CPHYSADDR(badvaddr); + idx = (badvaddr >> PAGE_SHIFT) & 1; + if (kvm_mips_map_page(vcpu, gpa, write_fault, &pte_gpa[idx], + &pte_gpa[!idx]) < 0) return -1; - pfn0 = pte_pfn(pte_gpa[0]); - pfn1 = pte_pfn(pte_gpa[1]); - - /* Find GVA page table entry */ - - ptep_gva = kvm_trap_emul_pte_for_gva(vcpu, vaddr); + /* Get the GVA page table entry */ + ptep_gva = kvm_trap_emul_pte_for_gva(vcpu, badvaddr & ~PAGE_SIZE); if (!ptep_gva) { - kvm_err("No ptep for gva %lx\n", vaddr); + kvm_err("No ptep for gva %lx\n", badvaddr); return -1; } - /* Write host PFNs into GVA page table */ - ptep_gva[0] = pte_mkyoung(pte_mkdirty(pfn_pte(pfn0, PAGE_SHARED))); - ptep_gva[1] = pte_mkyoung(pte_mkdirty(pfn_pte(pfn1, PAGE_SHARED))); + /* Copy a pair of entries from GPA page table to GVA page table */ + ptep_gva[0] = kvm_mips_gpa_pte_to_gva_unmapped(pte_gpa[0]); + ptep_gva[1] = kvm_mips_gpa_pte_to_gva_unmapped(pte_gpa[1]); /* Invalidate this entry in the TLB, guest kernel ASID only */ - kvm_mips_host_tlb_inv(vcpu, vaddr, false, true); + kvm_mips_host_tlb_inv(vcpu, badvaddr, false, true); return 0; } -- git-series 0.8.10
WARNING: multiple messages have this Message-ID (diff)
From: James Hogan <james.hogan@imgtec.com> To: linux-mips@linux-mips.org Cc: "James Hogan" <james.hogan@imgtec.com>, "Paolo Bonzini" <pbonzini@redhat.com>, "Radim Krčmář" <rkrcmar@redhat.com>, "Ralf Baechle" <ralf@linux-mips.org>, kvm@vger.kernel.org Subject: [PATCH 10/13] KVM: MIPS/MMU: Pass GPA PTE bits to KSeg0 GVA PTEs Date: Mon, 16 Jan 2017 12:49:31 +0000 [thread overview] Message-ID: <555238b387306895a8285cf719f3e9c6e520edde.1484570878.git-series.james.hogan@imgtec.com> (raw) Message-ID: <20170116124931.pAs40MEtQ5HbsxZ0kxf7BfL_zPHrd4lrjnBbd7R1mbE@z> (raw) In-Reply-To: <cover.99eec1b2ac935212acbcf2effacaab95cf6cdbf1.1484570878.git-series.james.hogan@imgtec.com> Propagate the GPA PTE protection bits on to the GVA PTEs on a KSeg0 fault (except _PAGE_WRITE), rather than always overriding the protection. This allows dirty page tracking to work in KSeg0 as a clear dirty bit in the GPA PTE will propagate to the GVA PTEs. This makes it simpler to use a single kvm_mips_map_page() to obtain both the main GPA PTE and its buddy (which may be invalid), which also allows memory regions to be fully accessible when they don't start and end on a 2*PAGE_SIZE boundary. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: "Radim Krčmář" <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org --- arch/mips/kvm/mmu.c | 49 ++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 7962eea4ebc3..9cc941864aa8 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -769,15 +769,27 @@ void kvm_mips_flush_gva_pt(pgd_t *pgd, enum kvm_mips_flush flags) } } +static pte_t kvm_mips_gpa_pte_to_gva_unmapped(pte_t pte) +{ + /* + * Don't leak writeable but clean entries from GPA page tables. We don't + * want the normal Linux tlbmod handler to handle dirtying when KVM + * accesses guest memory. + */ + if (!pte_dirty(pte)) + pte = pte_wrprotect(pte); + + return pte; +} + /* XXXKYMA: Must be called with interrupts disabled */ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, struct kvm_vcpu *vcpu, bool write_fault) { unsigned long gpa; - kvm_pfn_t pfn0, pfn1; - unsigned long vaddr; pte_t pte_gpa[2], *ptep_gva; + int idx; if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) { kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr); @@ -785,35 +797,26 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, return -1; } - /* Find host PFNs */ - - gpa = KVM_GUEST_CPHYSADDR(badvaddr & (PAGE_MASK << 1)); - vaddr = badvaddr & (PAGE_MASK << 1); - - if (kvm_mips_map_page(vcpu, gpa, write_fault, &pte_gpa[0], NULL) < 0) - return -1; - - if (kvm_mips_map_page(vcpu, gpa | PAGE_SIZE, write_fault, &pte_gpa[1], - NULL) < 0) + /* Get the GPA page table entry */ + gpa = KVM_GUEST_CPHYSADDR(badvaddr); + idx = (badvaddr >> PAGE_SHIFT) & 1; + if (kvm_mips_map_page(vcpu, gpa, write_fault, &pte_gpa[idx], + &pte_gpa[!idx]) < 0) return -1; - pfn0 = pte_pfn(pte_gpa[0]); - pfn1 = pte_pfn(pte_gpa[1]); - - /* Find GVA page table entry */ - - ptep_gva = kvm_trap_emul_pte_for_gva(vcpu, vaddr); + /* Get the GVA page table entry */ + ptep_gva = kvm_trap_emul_pte_for_gva(vcpu, badvaddr & ~PAGE_SIZE); if (!ptep_gva) { - kvm_err("No ptep for gva %lx\n", vaddr); + kvm_err("No ptep for gva %lx\n", badvaddr); return -1; } - /* Write host PFNs into GVA page table */ - ptep_gva[0] = pte_mkyoung(pte_mkdirty(pfn_pte(pfn0, PAGE_SHARED))); - ptep_gva[1] = pte_mkyoung(pte_mkdirty(pfn_pte(pfn1, PAGE_SHARED))); + /* Copy a pair of entries from GPA page table to GVA page table */ + ptep_gva[0] = kvm_mips_gpa_pte_to_gva_unmapped(pte_gpa[0]); + ptep_gva[1] = kvm_mips_gpa_pte_to_gva_unmapped(pte_gpa[1]); /* Invalidate this entry in the TLB, guest kernel ASID only */ - kvm_mips_host_tlb_inv(vcpu, vaddr, false, true); + kvm_mips_host_tlb_inv(vcpu, badvaddr, false, true); return 0; } -- git-series 0.8.10
next prev parent reply other threads:[~2017-01-16 12:53 UTC|newest] Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-01-16 12:49 [PATCH 0/13] KVM: MIPS: Dirty logging, SYNC_MMU & READONLY_MEM James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 1/13] KVM: MIPS/T&E: Ignore user writes to CP0_Config7 James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 2/13] KVM: MIPS: Pass type of fault down to kvm_mips_map_page() James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 3/13] KVM: MIPS/T&E: Abstract bad access handling James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 4/13] KVM: MIPS/T&E: Treat unhandled guest KSeg0 as MMIO James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 5/13] KVM: MIPS/T&E: Handle read only GPA in TLB mod James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 6/13] KVM: MIPS/MMU: Add GPA PT mkclean helper James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 7/13] KVM: MIPS/MMU: Use generic dirty log & protect helper James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 8/13] KVM: MIPS: Clean & flush on dirty page logging enable James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 9/13] KVM: MIPS/MMU: Handle dirty logging on GPA faults James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` James Hogan [this message] 2017-01-16 12:49 ` [PATCH 10/13] KVM: MIPS/MMU: Pass GPA PTE bits to KSeg0 GVA PTEs James Hogan 2017-01-16 12:49 ` [PATCH 11/13] KVM: MIPS/MMU: Pass GPA PTE bits to mapped " James Hogan 2017-01-16 12:49 ` James Hogan 2017-01-16 12:49 ` [PATCH 12/13] KVM: MIPS/MMU: Implement KVM_CAP_SYNC_MMU James Hogan 2017-01-16 12:49 ` James Hogan 2017-02-02 12:45 ` [PATCH v2 " James Hogan 2017-02-02 12:45 ` James Hogan 2017-01-16 12:49 ` [PATCH 13/13] KVM: MIPS: Claim KVM_CAP_READONLY_MEM support James Hogan 2017-01-16 12:49 ` James Hogan
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=555238b387306895a8285cf719f3e9c6e520edde.1484570878.git-series.james.hogan@imgtec.com \ --to=james.hogan@imgtec.com \ --cc=kvm@vger.kernel.org \ --cc=linux-mips@linux-mips.org \ --cc=pbonzini@redhat.com \ --cc=ralf@linux-mips.org \ --cc=rkrcmar@redhat.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).