aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2010-10-22 12:18:18 -0400
committerAvi Kivity <avi@redhat.com>2011-01-12 04:28:40 -0500
commit612819c3c6e67bac8fceaa7cc402f13b1b63f7e4 (patch)
tree3739b8420660fc4de8d37d26004d9992e92acbe3 /virt/kvm/kvm_main.c
parent7905d9a5ad7a83f1c1c00559839857ab90afbdfc (diff)
KVM: propagate fault r/w information to gup(), allow read-only memory
As suggested by Andrea, pass r/w error code to gup(), upgrading read fault to writable if host pte allows it. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 475a100f3a22..2803b4db2a38 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -959,7 +959,7 @@ static pfn_t get_fault_pfn(void)
959} 959}
960 960
961static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, 961static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
962 bool *async) 962 bool *async, bool write_fault, bool *writable)
963{ 963{
964 struct page *page[1]; 964 struct page *page[1];
965 int npages = 0; 965 int npages = 0;
@@ -968,12 +968,34 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
968 /* we can do it either atomically or asynchronously, not both */ 968 /* we can do it either atomically or asynchronously, not both */
969 BUG_ON(atomic && async); 969 BUG_ON(atomic && async);
970 970
971 BUG_ON(!write_fault && !writable);
972
973 if (writable)
974 *writable = true;
975
971 if (atomic || async) 976 if (atomic || async)
972 npages = __get_user_pages_fast(addr, 1, 1, page); 977 npages = __get_user_pages_fast(addr, 1, 1, page);
973 978
974 if (unlikely(npages != 1) && !atomic) { 979 if (unlikely(npages != 1) && !atomic) {
975 might_sleep(); 980 might_sleep();
976 npages = get_user_pages_fast(addr, 1, 1, page); 981
982 if (writable)
983 *writable = write_fault;
984
985 npages = get_user_pages_fast(addr, 1, write_fault, page);
986
987 /* map read fault as writable if possible */
988 if (unlikely(!write_fault) && npages == 1) {
989 struct page *wpage[1];
990
991 npages = __get_user_pages_fast(addr, 1, 1, wpage);
992 if (npages == 1) {
993 *writable = true;
994 put_page(page[0]);
995 page[0] = wpage[0];
996 }
997 npages = 1;
998 }
977 } 999 }
978 1000
979 if (unlikely(npages != 1)) { 1001 if (unlikely(npages != 1)) {
@@ -1011,11 +1033,12 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
1011 1033
1012pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr) 1034pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr)
1013{ 1035{
1014 return hva_to_pfn(kvm, addr, true, NULL); 1036 return hva_to_pfn(kvm, addr, true, NULL, true, NULL);
1015} 1037}
1016EXPORT_SYMBOL_GPL(hva_to_pfn_atomic); 1038EXPORT_SYMBOL_GPL(hva_to_pfn_atomic);
1017 1039
1018static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async) 1040static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async,
1041 bool write_fault, bool *writable)
1019{ 1042{
1020 unsigned long addr; 1043 unsigned long addr;
1021 1044
@@ -1028,32 +1051,40 @@ static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async)
1028 return page_to_pfn(bad_page); 1051 return page_to_pfn(bad_page);
1029 } 1052 }
1030 1053
1031 return hva_to_pfn(kvm, addr, atomic, async); 1054 return hva_to_pfn(kvm, addr, atomic, async, write_fault, writable);
1032} 1055}
1033 1056
1034pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn) 1057pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn)
1035{ 1058{
1036 return __gfn_to_pfn(kvm, gfn, true, NULL); 1059 return __gfn_to_pfn(kvm, gfn, true, NULL, true, NULL);
1037} 1060}
1038EXPORT_SYMBOL_GPL(gfn_to_pfn_atomic); 1061EXPORT_SYMBOL_GPL(gfn_to_pfn_atomic);
1039 1062
1040pfn_t gfn_to_pfn_async(struct kvm *kvm, gfn_t gfn, bool *async) 1063pfn_t gfn_to_pfn_async(struct kvm *kvm, gfn_t gfn, bool *async,
1064 bool write_fault, bool *writable)
1041{ 1065{
1042 return __gfn_to_pfn(kvm, gfn, false, async); 1066 return __gfn_to_pfn(kvm, gfn, false, async, write_fault, writable);
1043} 1067}
1044EXPORT_SYMBOL_GPL(gfn_to_pfn_async); 1068EXPORT_SYMBOL_GPL(gfn_to_pfn_async);
1045 1069
1046pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) 1070pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
1047{ 1071{
1048 return __gfn_to_pfn(kvm, gfn, false, NULL); 1072 return __gfn_to_pfn(kvm, gfn, false, NULL, true, NULL);
1049} 1073}
1050EXPORT_SYMBOL_GPL(gfn_to_pfn); 1074EXPORT_SYMBOL_GPL(gfn_to_pfn);
1051 1075
1076pfn_t gfn_to_pfn_prot(struct kvm *kvm, gfn_t gfn, bool write_fault,
1077 bool *writable)
1078{
1079 return __gfn_to_pfn(kvm, gfn, false, NULL, write_fault, writable);
1080}
1081EXPORT_SYMBOL_GPL(gfn_to_pfn_prot);
1082
1052pfn_t gfn_to_pfn_memslot(struct kvm *kvm, 1083pfn_t gfn_to_pfn_memslot(struct kvm *kvm,
1053 struct kvm_memory_slot *slot, gfn_t gfn) 1084 struct kvm_memory_slot *slot, gfn_t gfn)
1054{ 1085{
1055 unsigned long addr = gfn_to_hva_memslot(slot, gfn); 1086 unsigned long addr = gfn_to_hva_memslot(slot, gfn);
1056 return hva_to_pfn(kvm, addr, false, NULL); 1087 return hva_to_pfn(kvm, addr, false, NULL, true, NULL);
1057} 1088}
1058 1089
1059int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, 1090int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages,