diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/kvm.h | 17 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 74 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 3 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 19 |
4 files changed, 25 insertions, 88 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 1072c8322d4f..030b93bcdf1b 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -561,15 +561,14 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); | |||
561 | void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); | 561 | void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); |
562 | void kvm_flush_remote_tlbs(struct kvm *kvm); | 562 | void kvm_flush_remote_tlbs(struct kvm *kvm); |
563 | 563 | ||
564 | int kvm_read_guest(struct kvm_vcpu *vcpu, | 564 | int emulator_read_std(unsigned long addr, |
565 | gva_t addr, | 565 | void *val, |
566 | unsigned long size, | 566 | unsigned int bytes, |
567 | void *dest); | 567 | struct kvm_vcpu *vcpu); |
568 | 568 | int emulator_write_emulated(unsigned long addr, | |
569 | int kvm_write_guest(struct kvm_vcpu *vcpu, | 569 | const void *val, |
570 | gva_t addr, | 570 | unsigned int bytes, |
571 | unsigned long size, | 571 | struct kvm_vcpu *vcpu); |
572 | void *data); | ||
573 | 572 | ||
574 | unsigned long segment_base(u16 selector); | 573 | unsigned long segment_base(u16 selector); |
575 | 574 | ||
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a65a145f3050..4bbd89e03324 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -146,74 +146,6 @@ static inline int valid_vcpu(int n) | |||
146 | return likely(n >= 0 && n < KVM_MAX_VCPUS); | 146 | return likely(n >= 0 && n < KVM_MAX_VCPUS); |
147 | } | 147 | } |
148 | 148 | ||
149 | int kvm_read_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, | ||
150 | void *dest) | ||
151 | { | ||
152 | unsigned char *host_buf = dest; | ||
153 | unsigned long req_size = size; | ||
154 | |||
155 | while (size) { | ||
156 | hpa_t paddr; | ||
157 | unsigned now; | ||
158 | unsigned offset; | ||
159 | hva_t guest_buf; | ||
160 | |||
161 | paddr = gva_to_hpa(vcpu, addr); | ||
162 | |||
163 | if (is_error_hpa(paddr)) | ||
164 | break; | ||
165 | |||
166 | guest_buf = (hva_t)kmap_atomic( | ||
167 | pfn_to_page(paddr >> PAGE_SHIFT), | ||
168 | KM_USER0); | ||
169 | offset = addr & ~PAGE_MASK; | ||
170 | guest_buf |= offset; | ||
171 | now = min(size, PAGE_SIZE - offset); | ||
172 | memcpy(host_buf, (void*)guest_buf, now); | ||
173 | host_buf += now; | ||
174 | addr += now; | ||
175 | size -= now; | ||
176 | kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); | ||
177 | } | ||
178 | return req_size - size; | ||
179 | } | ||
180 | EXPORT_SYMBOL_GPL(kvm_read_guest); | ||
181 | |||
182 | int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, | ||
183 | void *data) | ||
184 | { | ||
185 | unsigned char *host_buf = data; | ||
186 | unsigned long req_size = size; | ||
187 | |||
188 | while (size) { | ||
189 | hpa_t paddr; | ||
190 | unsigned now; | ||
191 | unsigned offset; | ||
192 | hva_t guest_buf; | ||
193 | gfn_t gfn; | ||
194 | |||
195 | paddr = gva_to_hpa(vcpu, addr); | ||
196 | |||
197 | if (is_error_hpa(paddr)) | ||
198 | break; | ||
199 | |||
200 | gfn = vcpu->mmu.gva_to_gpa(vcpu, addr) >> PAGE_SHIFT; | ||
201 | mark_page_dirty(vcpu->kvm, gfn); | ||
202 | guest_buf = (hva_t)kmap_atomic( | ||
203 | pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0); | ||
204 | offset = addr & ~PAGE_MASK; | ||
205 | guest_buf |= offset; | ||
206 | now = min(size, PAGE_SIZE - offset); | ||
207 | memcpy((void*)guest_buf, host_buf, now); | ||
208 | host_buf += now; | ||
209 | addr += now; | ||
210 | size -= now; | ||
211 | kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); | ||
212 | } | ||
213 | return req_size - size; | ||
214 | } | ||
215 | EXPORT_SYMBOL_GPL(kvm_write_guest); | ||
216 | |||
217 | void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) | 149 | void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) |
218 | { | 150 | { |
219 | if (!vcpu->fpu_active || vcpu->guest_fpu_loaded) | 151 | if (!vcpu->fpu_active || vcpu->guest_fpu_loaded) |
@@ -1017,7 +949,7 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) | |||
1017 | } | 949 | } |
1018 | } | 950 | } |
1019 | 951 | ||
1020 | static int emulator_read_std(unsigned long addr, | 952 | int emulator_read_std(unsigned long addr, |
1021 | void *val, | 953 | void *val, |
1022 | unsigned int bytes, | 954 | unsigned int bytes, |
1023 | struct kvm_vcpu *vcpu) | 955 | struct kvm_vcpu *vcpu) |
@@ -1051,6 +983,7 @@ static int emulator_read_std(unsigned long addr, | |||
1051 | 983 | ||
1052 | return X86EMUL_CONTINUE; | 984 | return X86EMUL_CONTINUE; |
1053 | } | 985 | } |
986 | EXPORT_SYMBOL_GPL(emulator_read_std); | ||
1054 | 987 | ||
1055 | static int emulator_write_std(unsigned long addr, | 988 | static int emulator_write_std(unsigned long addr, |
1056 | const void *val, | 989 | const void *val, |
@@ -1169,7 +1102,7 @@ static int emulator_write_emulated_onepage(unsigned long addr, | |||
1169 | return X86EMUL_CONTINUE; | 1102 | return X86EMUL_CONTINUE; |
1170 | } | 1103 | } |
1171 | 1104 | ||
1172 | static int emulator_write_emulated(unsigned long addr, | 1105 | int emulator_write_emulated(unsigned long addr, |
1173 | const void *val, | 1106 | const void *val, |
1174 | unsigned int bytes, | 1107 | unsigned int bytes, |
1175 | struct kvm_vcpu *vcpu) | 1108 | struct kvm_vcpu *vcpu) |
@@ -1188,6 +1121,7 @@ static int emulator_write_emulated(unsigned long addr, | |||
1188 | } | 1121 | } |
1189 | return emulator_write_emulated_onepage(addr, val, bytes, vcpu); | 1122 | return emulator_write_emulated_onepage(addr, val, bytes, vcpu); |
1190 | } | 1123 | } |
1124 | EXPORT_SYMBOL_GPL(emulator_write_emulated); | ||
1191 | 1125 | ||
1192 | static int emulator_cmpxchg_emulated(unsigned long addr, | 1126 | static int emulator_cmpxchg_emulated(unsigned long addr, |
1193 | const void *old, | 1127 | const void *old, |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index cd966739970f..b25f4e117e71 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -1019,7 +1019,8 @@ static int io_get_override(struct vcpu_svm *svm, | |||
1019 | svm->vmcb->control.exit_info_2, | 1019 | svm->vmcb->control.exit_info_2, |
1020 | ins_length); | 1020 | ins_length); |
1021 | 1021 | ||
1022 | if (kvm_read_guest(&svm->vcpu, rip, ins_length, inst) != ins_length) | 1022 | if (emulator_read_std(rip, inst, ins_length, &svm->vcpu) |
1023 | != X86EMUL_CONTINUE) | ||
1023 | /* #PF */ | 1024 | /* #PF */ |
1024 | return 0; | 1025 | return 0; |
1025 | 1026 | ||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index cc7ee3d484fb..f770f55d46cd 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "kvm.h" | 18 | #include "kvm.h" |
19 | #include "x86_emulate.h" | ||
19 | #include "vmx.h" | 20 | #include "vmx.h" |
20 | #include "segment_descriptor.h" | 21 | #include "segment_descriptor.h" |
21 | 22 | ||
@@ -1553,8 +1554,8 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) | |||
1553 | return; | 1554 | return; |
1554 | } | 1555 | } |
1555 | 1556 | ||
1556 | if (kvm_read_guest(vcpu, irq * sizeof(ent), sizeof(ent), &ent) != | 1557 | if (emulator_read_std(irq * sizeof(ent), &ent, sizeof(ent), vcpu) != |
1557 | sizeof(ent)) { | 1558 | X86EMUL_CONTINUE) { |
1558 | vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__); | 1559 | vcpu_printf(vcpu, "%s: read guest err\n", __FUNCTION__); |
1559 | return; | 1560 | return; |
1560 | } | 1561 | } |
@@ -1564,9 +1565,9 @@ static void inject_rmode_irq(struct kvm_vcpu *vcpu, int irq) | |||
1564 | ip = vmcs_readl(GUEST_RIP); | 1565 | ip = vmcs_readl(GUEST_RIP); |
1565 | 1566 | ||
1566 | 1567 | ||
1567 | if (kvm_write_guest(vcpu, ss_base + sp - 2, 2, &flags) != 2 || | 1568 | if (emulator_write_emulated(ss_base + sp - 2, &flags, 2, vcpu) != X86EMUL_CONTINUE || |
1568 | kvm_write_guest(vcpu, ss_base + sp - 4, 2, &cs) != 2 || | 1569 | emulator_write_emulated(ss_base + sp - 4, &cs, 2, vcpu) != X86EMUL_CONTINUE || |
1569 | kvm_write_guest(vcpu, ss_base + sp - 6, 2, &ip) != 2) { | 1570 | emulator_write_emulated(ss_base + sp - 6, &ip, 2, vcpu) != X86EMUL_CONTINUE) { |
1570 | vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__); | 1571 | vcpu_printf(vcpu, "%s: write guest err\n", __FUNCTION__); |
1571 | return; | 1572 | return; |
1572 | } | 1573 | } |
@@ -1767,7 +1768,7 @@ static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count) | |||
1767 | u64 inst; | 1768 | u64 inst; |
1768 | gva_t rip; | 1769 | gva_t rip; |
1769 | int countr_size; | 1770 | int countr_size; |
1770 | int i, n; | 1771 | int i; |
1771 | 1772 | ||
1772 | if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) { | 1773 | if ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_VM)) { |
1773 | countr_size = 2; | 1774 | countr_size = 2; |
@@ -1782,9 +1783,11 @@ static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count) | |||
1782 | if (countr_size != 8) | 1783 | if (countr_size != 8) |
1783 | rip += vmcs_readl(GUEST_CS_BASE); | 1784 | rip += vmcs_readl(GUEST_CS_BASE); |
1784 | 1785 | ||
1785 | n = kvm_read_guest(vcpu, rip, sizeof(inst), &inst); | 1786 | if (emulator_read_std(rip, &inst, sizeof(inst), vcpu) != |
1787 | X86EMUL_CONTINUE) | ||
1788 | return 0; | ||
1786 | 1789 | ||
1787 | for (i = 0; i < n; i++) { | 1790 | for (i = 0; i < sizeof(inst); i++) { |
1788 | switch (((u8*)&inst)[i]) { | 1791 | switch (((u8*)&inst)[i]) { |
1789 | case 0xf0: | 1792 | case 0xf0: |
1790 | case 0xf2: | 1793 | case 0xf2: |