mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
KVM: mmu: allow page tables to be in read-only slots
Page tables in a read-only memory slot will currently cause a triple fault because the page walker uses gfn_to_hva and it fails on such a slot. OVMF uses such a page table; however, real hardware seems to be fine with that as long as the accessed/dirty bits are set. Save whether the slot is readonly, and later check it when updating the accessed and dirty bits. Reviewed-by: Xiao Guangrong <[email protected]> Reviewed-by: Gleb Natapov <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
This commit is contained in:
parent
3261107ebf
commit
ba6a354154
3 changed files with 29 additions and 6 deletions
|
|
@ -1058,11 +1058,15 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
|
|||
EXPORT_SYMBOL_GPL(gfn_to_hva);
|
||||
|
||||
/*
|
||||
* The hva returned by this function is only allowed to be read.
|
||||
* It should pair with kvm_read_hva() or kvm_read_hva_atomic().
|
||||
* If writable is set to false, the hva returned by this function is only
|
||||
* allowed to be read.
|
||||
*/
|
||||
static unsigned long gfn_to_hva_read(struct kvm *kvm, gfn_t gfn)
|
||||
unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable)
|
||||
{
|
||||
struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
|
||||
if (writable)
|
||||
*writable = !memslot_is_readonly(slot);
|
||||
|
||||
return __gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL, false);
|
||||
}
|
||||
|
||||
|
|
@ -1430,7 +1434,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
|
|||
int r;
|
||||
unsigned long addr;
|
||||
|
||||
addr = gfn_to_hva_read(kvm, gfn);
|
||||
addr = gfn_to_hva_prot(kvm, gfn, NULL);
|
||||
if (kvm_is_error_hva(addr))
|
||||
return -EFAULT;
|
||||
r = kvm_read_hva(data, (void __user *)addr + offset, len);
|
||||
|
|
@ -1468,7 +1472,7 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
|
|||
gfn_t gfn = gpa >> PAGE_SHIFT;
|
||||
int offset = offset_in_page(gpa);
|
||||
|
||||
addr = gfn_to_hva_read(kvm, gfn);
|
||||
addr = gfn_to_hva_prot(kvm, gfn, NULL);
|
||||
if (kvm_is_error_hva(addr))
|
||||
return -EFAULT;
|
||||
pagefault_disable();
|
||||
|
|
|
|||
Loading…
Reference in a new issue