diff options
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 10 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 9 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 1 | ||||
-rw-r--r-- | include/linux/kvm.h | 6 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 7 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 96 |
7 files changed, 102 insertions, 28 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index bf33aaa4c59f..b91bfd43f007 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -857,7 +857,8 @@ struct kvm_userspace_memory_region { | |||
857 | }; | 857 | }; |
858 | 858 | ||
859 | /* for kvm_memory_region::flags */ | 859 | /* for kvm_memory_region::flags */ |
860 | #define KVM_MEM_LOG_DIRTY_PAGES 1UL | 860 | #define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0) |
861 | #define KVM_MEM_READONLY (1UL << 1) | ||
861 | 862 | ||
862 | This ioctl allows the user to create or modify a guest physical memory | 863 | This ioctl allows the user to create or modify a guest physical memory |
863 | slot. When changing an existing slot, it may be moved in the guest | 864 | slot. When changing an existing slot, it may be moved in the guest |
@@ -873,9 +874,12 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr | |||
873 | be identical. This allows large pages in the guest to be backed by large | 874 | be identical. This allows large pages in the guest to be backed by large |
874 | pages in the host. | 875 | pages in the host. |
875 | 876 | ||
876 | The flags field supports just one flag, KVM_MEM_LOG_DIRTY_PAGES, which | 877 | The flags field supports two flag, KVM_MEM_LOG_DIRTY_PAGES, which |
877 | instructs kvm to keep track of writes to memory within the slot. See | 878 | instructs kvm to keep track of writes to memory within the slot. See |
878 | the KVM_GET_DIRTY_LOG ioctl. | 879 | the KVM_GET_DIRTY_LOG ioctl. Another flag is KVM_MEM_READONLY when the |
880 | KVM_CAP_READONLY_MEM capability, it indicates the guest memory is read-only, | ||
881 | that means, guest is only allowed to read it. Writes will be posted to | ||
882 | userspace as KVM_EXIT_MMIO exits. | ||
879 | 883 | ||
880 | When the KVM_CAP_SYNC_MMU capability, changes in the backing of the memory | 884 | When the KVM_CAP_SYNC_MMU capability, changes in the backing of the memory |
881 | region are automatically reflected into the guest. For example, an mmap() | 885 | region are automatically reflected into the guest. For example, an mmap() |
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 246617efd67f..521bf252e34b 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define __KVM_HAVE_DEBUGREGS | 25 | #define __KVM_HAVE_DEBUGREGS |
26 | #define __KVM_HAVE_XSAVE | 26 | #define __KVM_HAVE_XSAVE |
27 | #define __KVM_HAVE_XCRS | 27 | #define __KVM_HAVE_XCRS |
28 | #define __KVM_HAVE_READONLY_MEM | ||
28 | 29 | ||
29 | /* Architectural interrupt line count. */ | 30 | /* Architectural interrupt line count. */ |
30 | #define KVM_NR_INTERRUPTS 256 | 31 | #define KVM_NR_INTERRUPTS 256 |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 5548971ae80d..8e312a2e1412 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -2647,6 +2647,15 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct * | |||
2647 | 2647 | ||
2648 | static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn) | 2648 | static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn) |
2649 | { | 2649 | { |
2650 | /* | ||
2651 | * Do not cache the mmio info caused by writing the readonly gfn | ||
2652 | * into the spte otherwise read access on readonly gfn also can | ||
2653 | * caused mmio page fault and treat it as mmio access. | ||
2654 | * Return 1 to tell kvm to emulate it. | ||
2655 | */ | ||
2656 | if (pfn == KVM_PFN_ERR_RO_FAULT) | ||
2657 | return 1; | ||
2658 | |||
2650 | if (pfn == KVM_PFN_ERR_HWPOISON) { | 2659 | if (pfn == KVM_PFN_ERR_HWPOISON) { |
2651 | kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current); | 2660 | kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current); |
2652 | return 0; | 2661 | return 0; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 704680d0fa3e..42bbf4187d20 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2175,6 +2175,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
2175 | case KVM_CAP_GET_TSC_KHZ: | 2175 | case KVM_CAP_GET_TSC_KHZ: |
2176 | case KVM_CAP_PCI_2_3: | 2176 | case KVM_CAP_PCI_2_3: |
2177 | case KVM_CAP_KVMCLOCK_CTRL: | 2177 | case KVM_CAP_KVMCLOCK_CTRL: |
2178 | case KVM_CAP_READONLY_MEM: | ||
2178 | r = 1; | 2179 | r = 1; |
2179 | break; | 2180 | break; |
2180 | case KVM_CAP_COALESCED_MMIO: | 2181 | case KVM_CAP_COALESCED_MMIO: |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 2de335d7f63e..d808694673f9 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -106,7 +106,8 @@ struct kvm_userspace_memory_region { | |||
106 | * other bits are reserved for kvm internal use which are defined in | 106 | * other bits are reserved for kvm internal use which are defined in |
107 | * include/linux/kvm_host.h. | 107 | * include/linux/kvm_host.h. |
108 | */ | 108 | */ |
109 | #define KVM_MEM_LOG_DIRTY_PAGES 1UL | 109 | #define KVM_MEM_LOG_DIRTY_PAGES (1UL << 0) |
110 | #define KVM_MEM_READONLY (1UL << 1) | ||
110 | 111 | ||
111 | /* for KVM_IRQ_LINE */ | 112 | /* for KVM_IRQ_LINE */ |
112 | struct kvm_irq_level { | 113 | struct kvm_irq_level { |
@@ -621,6 +622,9 @@ struct kvm_ppc_smmu_info { | |||
621 | #define KVM_CAP_PPC_GET_SMMU_INFO 78 | 622 | #define KVM_CAP_PPC_GET_SMMU_INFO 78 |
622 | #define KVM_CAP_S390_COW 79 | 623 | #define KVM_CAP_S390_COW 79 |
623 | #define KVM_CAP_PPC_ALLOC_HTAB 80 | 624 | #define KVM_CAP_PPC_ALLOC_HTAB 80 |
625 | #ifdef __KVM_HAVE_READONLY_MEM | ||
626 | #define KVM_CAP_READONLY_MEM 81 | ||
627 | #endif | ||
624 | 628 | ||
625 | #ifdef KVM_CAP_IRQ_ROUTING | 629 | #ifdef KVM_CAP_IRQ_ROUTING |
626 | 630 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a913ac709a9d..5972c9845ddb 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -465,6 +465,7 @@ int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, | |||
465 | 465 | ||
466 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); | 466 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); |
467 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); | 467 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); |
468 | unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn); | ||
468 | void kvm_release_page_clean(struct page *page); | 469 | void kvm_release_page_clean(struct page *page); |
469 | void kvm_release_page_dirty(struct page *page); | 470 | void kvm_release_page_dirty(struct page *page); |
470 | void kvm_set_page_dirty(struct page *page); | 471 | void kvm_set_page_dirty(struct page *page); |
@@ -792,12 +793,6 @@ hva_to_gfn_memslot(unsigned long hva, struct kvm_memory_slot *slot) | |||
792 | return slot->base_gfn + gfn_offset; | 793 | return slot->base_gfn + gfn_offset; |
793 | } | 794 | } |
794 | 795 | ||
795 | static inline unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, | ||
796 | gfn_t gfn) | ||
797 | { | ||
798 | return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; | ||
799 | } | ||
800 | |||
801 | static inline gpa_t gfn_to_gpa(gfn_t gfn) | 796 | static inline gpa_t gfn_to_gpa(gfn_t gfn) |
802 | { | 797 | { |
803 | return (gpa_t)gfn << PAGE_SHIFT; | 798 | return (gpa_t)gfn << PAGE_SHIFT; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e3e1658c491d..3416f8a31f63 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -680,7 +680,13 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new) | |||
680 | 680 | ||
681 | static int check_memory_region_flags(struct kvm_userspace_memory_region *mem) | 681 | static int check_memory_region_flags(struct kvm_userspace_memory_region *mem) |
682 | { | 682 | { |
683 | if (mem->flags & ~KVM_MEM_LOG_DIRTY_PAGES) | 683 | u32 valid_flags = KVM_MEM_LOG_DIRTY_PAGES; |
684 | |||
685 | #ifdef KVM_CAP_READONLY_MEM | ||
686 | valid_flags |= KVM_MEM_READONLY; | ||
687 | #endif | ||
688 | |||
689 | if (mem->flags & ~valid_flags) | ||
684 | return -EINVAL; | 690 | return -EINVAL; |
685 | 691 | ||
686 | return 0; | 692 | return 0; |
@@ -973,18 +979,45 @@ out: | |||
973 | return size; | 979 | return size; |
974 | } | 980 | } |
975 | 981 | ||
976 | static unsigned long gfn_to_hva_many(struct kvm_memory_slot *slot, gfn_t gfn, | 982 | static bool memslot_is_readonly(struct kvm_memory_slot *slot) |
977 | gfn_t *nr_pages) | 983 | { |
984 | return slot->flags & KVM_MEM_READONLY; | ||
985 | } | ||
986 | |||
987 | static unsigned long __gfn_to_hva_memslot(struct kvm_memory_slot *slot, | ||
988 | gfn_t gfn) | ||
989 | { | ||
990 | return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; | ||
991 | } | ||
992 | |||
993 | static unsigned long __gfn_to_hva_many(struct kvm_memory_slot *slot, gfn_t gfn, | ||
994 | gfn_t *nr_pages, bool write) | ||
978 | { | 995 | { |
979 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | 996 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) |
980 | return KVM_HVA_ERR_BAD; | 997 | return KVM_HVA_ERR_BAD; |
981 | 998 | ||
999 | if (memslot_is_readonly(slot) && write) | ||
1000 | return KVM_HVA_ERR_RO_BAD; | ||
1001 | |||
982 | if (nr_pages) | 1002 | if (nr_pages) |
983 | *nr_pages = slot->npages - (gfn - slot->base_gfn); | 1003 | *nr_pages = slot->npages - (gfn - slot->base_gfn); |
984 | 1004 | ||
985 | return gfn_to_hva_memslot(slot, gfn); | 1005 | return __gfn_to_hva_memslot(slot, gfn); |
986 | } | 1006 | } |
987 | 1007 | ||
1008 | static unsigned long gfn_to_hva_many(struct kvm_memory_slot *slot, gfn_t gfn, | ||
1009 | gfn_t *nr_pages) | ||
1010 | { | ||
1011 | return __gfn_to_hva_many(slot, gfn, nr_pages, true); | ||
1012 | } | ||
1013 | |||
1014 | unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, | ||
1015 | gfn_t gfn) | ||
1016 | { | ||
1017 | return gfn_to_hva_many(slot, gfn, NULL); | ||
1018 | } | ||
1019 | EXPORT_SYMBOL_GPL(gfn_to_hva_memslot); | ||
1020 | |||
988 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | 1021 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) |
989 | { | 1022 | { |
990 | return gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL); | 1023 | return gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL); |
@@ -997,7 +1030,7 @@ EXPORT_SYMBOL_GPL(gfn_to_hva); | |||
997 | */ | 1030 | */ |
998 | static unsigned long gfn_to_hva_read(struct kvm *kvm, gfn_t gfn) | 1031 | static unsigned long gfn_to_hva_read(struct kvm *kvm, gfn_t gfn) |
999 | { | 1032 | { |
1000 | return gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL); | 1033 | return __gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL, false); |
1001 | } | 1034 | } |
1002 | 1035 | ||
1003 | static int kvm_read_hva(void *data, void __user *hva, int len) | 1036 | static int kvm_read_hva(void *data, void __user *hva, int len) |
@@ -1106,6 +1139,17 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault, | |||
1106 | return npages; | 1139 | return npages; |
1107 | } | 1140 | } |
1108 | 1141 | ||
1142 | static bool vma_is_valid(struct vm_area_struct *vma, bool write_fault) | ||
1143 | { | ||
1144 | if (unlikely(!(vma->vm_flags & VM_READ))) | ||
1145 | return false; | ||
1146 | |||
1147 | if (write_fault && (unlikely(!(vma->vm_flags & VM_WRITE)))) | ||
1148 | return false; | ||
1149 | |||
1150 | return true; | ||
1151 | } | ||
1152 | |||
1109 | /* | 1153 | /* |
1110 | * Pin guest page in memory and return its pfn. | 1154 | * Pin guest page in memory and return its pfn. |
1111 | * @addr: host virtual address which maps memory to the guest | 1155 | * @addr: host virtual address which maps memory to the guest |
@@ -1130,8 +1174,6 @@ static pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async, | |||
1130 | /* we can do it either atomically or asynchronously, not both */ | 1174 | /* we can do it either atomically or asynchronously, not both */ |
1131 | BUG_ON(atomic && async); | 1175 | BUG_ON(atomic && async); |
1132 | 1176 | ||
1133 | BUG_ON(!write_fault && !writable); | ||
1134 | |||
1135 | if (hva_to_pfn_fast(addr, atomic, async, write_fault, writable, &pfn)) | 1177 | if (hva_to_pfn_fast(addr, atomic, async, write_fault, writable, &pfn)) |
1136 | return pfn; | 1178 | return pfn; |
1137 | 1179 | ||
@@ -1158,7 +1200,7 @@ static pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async, | |||
1158 | vma->vm_pgoff; | 1200 | vma->vm_pgoff; |
1159 | BUG_ON(!kvm_is_mmio_pfn(pfn)); | 1201 | BUG_ON(!kvm_is_mmio_pfn(pfn)); |
1160 | } else { | 1202 | } else { |
1161 | if (async && (vma->vm_flags & VM_WRITE)) | 1203 | if (async && vma_is_valid(vma, write_fault)) |
1162 | *async = true; | 1204 | *async = true; |
1163 | pfn = KVM_PFN_ERR_FAULT; | 1205 | pfn = KVM_PFN_ERR_FAULT; |
1164 | } | 1206 | } |
@@ -1167,19 +1209,40 @@ exit: | |||
1167 | return pfn; | 1209 | return pfn; |
1168 | } | 1210 | } |
1169 | 1211 | ||
1212 | static pfn_t | ||
1213 | __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn, bool atomic, | ||
1214 | bool *async, bool write_fault, bool *writable) | ||
1215 | { | ||
1216 | unsigned long addr = __gfn_to_hva_many(slot, gfn, NULL, write_fault); | ||
1217 | |||
1218 | if (addr == KVM_HVA_ERR_RO_BAD) | ||
1219 | return KVM_PFN_ERR_RO_FAULT; | ||
1220 | |||
1221 | if (kvm_is_error_hva(addr)) | ||
1222 | return KVM_PFN_ERR_BAD; | ||
1223 | |||
1224 | /* Do not map writable pfn in the readonly memslot. */ | ||
1225 | if (writable && memslot_is_readonly(slot)) { | ||
1226 | *writable = false; | ||
1227 | writable = NULL; | ||
1228 | } | ||
1229 | |||
1230 | return hva_to_pfn(addr, atomic, async, write_fault, | ||
1231 | writable); | ||
1232 | } | ||
1233 | |||
1170 | static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async, | 1234 | static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async, |
1171 | bool write_fault, bool *writable) | 1235 | bool write_fault, bool *writable) |
1172 | { | 1236 | { |
1173 | unsigned long addr; | 1237 | struct kvm_memory_slot *slot; |
1174 | 1238 | ||
1175 | if (async) | 1239 | if (async) |
1176 | *async = false; | 1240 | *async = false; |
1177 | 1241 | ||
1178 | addr = gfn_to_hva(kvm, gfn); | 1242 | slot = gfn_to_memslot(kvm, gfn); |
1179 | if (kvm_is_error_hva(addr)) | ||
1180 | return KVM_PFN_ERR_BAD; | ||
1181 | 1243 | ||
1182 | return hva_to_pfn(addr, atomic, async, write_fault, writable); | 1244 | return __gfn_to_pfn_memslot(slot, gfn, atomic, async, write_fault, |
1245 | writable); | ||
1183 | } | 1246 | } |
1184 | 1247 | ||
1185 | pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn) | 1248 | pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn) |
@@ -1210,15 +1273,12 @@ EXPORT_SYMBOL_GPL(gfn_to_pfn_prot); | |||
1210 | 1273 | ||
1211 | pfn_t gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn) | 1274 | pfn_t gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn) |
1212 | { | 1275 | { |
1213 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); | 1276 | return __gfn_to_pfn_memslot(slot, gfn, false, NULL, true, NULL); |
1214 | return hva_to_pfn(addr, false, NULL, true, NULL); | ||
1215 | } | 1277 | } |
1216 | 1278 | ||
1217 | pfn_t gfn_to_pfn_memslot_atomic(struct kvm_memory_slot *slot, gfn_t gfn) | 1279 | pfn_t gfn_to_pfn_memslot_atomic(struct kvm_memory_slot *slot, gfn_t gfn) |
1218 | { | 1280 | { |
1219 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); | 1281 | return __gfn_to_pfn_memslot(slot, gfn, true, NULL, true, NULL); |
1220 | |||
1221 | return hva_to_pfn(addr, true, NULL, true, NULL); | ||
1222 | } | 1282 | } |
1223 | EXPORT_SYMBOL_GPL(gfn_to_pfn_memslot_atomic); | 1283 | EXPORT_SYMBOL_GPL(gfn_to_pfn_memslot_atomic); |
1224 | 1284 | ||