diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index bf040c4e02b3..a9dd682cf5e3 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -1058,12 +1058,18 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | |||
1058 | EXPORT_SYMBOL_GPL(gfn_to_hva); | 1058 | EXPORT_SYMBOL_GPL(gfn_to_hva); |
1059 | 1059 | ||
1060 | /* | 1060 | /* |
1061 | * The hva returned by this function is only allowed to be read. | 1061 | * If writable is set to false, the hva returned by this function is only |
1062 | * It should pair with kvm_read_hva() or kvm_read_hva_atomic(). | 1062 | * allowed to be read. |
1063 | */ | 1063 | */ |
1064 | static unsigned long gfn_to_hva_read(struct kvm *kvm, gfn_t gfn) | 1064 | unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable) |
1065 | { | 1065 | { |
1066 | return __gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL, false); | 1066 | struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn); |
1067 | unsigned long hva = __gfn_to_hva_many(slot, gfn, NULL, false); | ||
1068 | |||
1069 | if (!kvm_is_error_hva(hva) && writable) | ||
1070 | *writable = !memslot_is_readonly(slot); | ||
1071 | |||
1072 | return hva; | ||
1067 | } | 1073 | } |
1068 | 1074 | ||
1069 | static int kvm_read_hva(void *data, void __user *hva, int len) | 1075 | static int kvm_read_hva(void *data, void __user *hva, int len) |
@@ -1430,7 +1436,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, | |||
1430 | int r; | 1436 | int r; |
1431 | unsigned long addr; | 1437 | unsigned long addr; |
1432 | 1438 | ||
1433 | addr = gfn_to_hva_read(kvm, gfn); | 1439 | addr = gfn_to_hva_prot(kvm, gfn, NULL); |
1434 | if (kvm_is_error_hva(addr)) | 1440 | if (kvm_is_error_hva(addr)) |
1435 | return -EFAULT; | 1441 | return -EFAULT; |
1436 | r = kvm_read_hva(data, (void __user *)addr + offset, len); | 1442 | r = kvm_read_hva(data, (void __user *)addr + offset, len); |
@@ -1468,7 +1474,7 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, | |||
1468 | gfn_t gfn = gpa >> PAGE_SHIFT; | 1474 | gfn_t gfn = gpa >> PAGE_SHIFT; |
1469 | int offset = offset_in_page(gpa); | 1475 | int offset = offset_in_page(gpa); |
1470 | 1476 | ||
1471 | addr = gfn_to_hva_read(kvm, gfn); | 1477 | addr = gfn_to_hva_prot(kvm, gfn, NULL); |
1472 | if (kvm_is_error_hva(addr)) | 1478 | if (kvm_is_error_hva(addr)) |
1473 | return -EFAULT; | 1479 | return -EFAULT; |
1474 | pagefault_disable(); | 1480 | pagefault_disable(); |