diff options
author | Avi Kivity <avi@qumranet.com> | 2007-03-20 06:46:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-05-03 03:52:25 -0400 |
commit | 039576c03c35e2f990ad9bb9c39e1bad3cd60d34 (patch) | |
tree | fa6c81a40a36d2c0da1cf20c5deb45cb9bd7ba95 /drivers/kvm/kvm.h | |
parent | f0fe510864a4520a85dfa35ae14f5f376c56efc7 (diff) |
KVM: Avoid guest virtual addresses in string pio userspace interface
The current string pio interface communicates using guest virtual addresses,
relying on userspace to translate addresses and to check permissions. This
interface cannot fully support guest smp, as the check needs to take into
account two pages at one in case an unaligned string transfer straddles a
page boundary.
Change the interface not to communicate guest addresses at all; instead use
a buffer page (mmaped by userspace) and do transfers there. The kernel
manages the virtual to physical translation and can perform the checks
atomically by taking the appropriate locks.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm.h')
-rw-r--r-- | drivers/kvm/kvm.h | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 1c4a581938bf..7866b34b6c96 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -74,6 +74,8 @@ | |||
74 | 74 | ||
75 | #define IOPL_SHIFT 12 | 75 | #define IOPL_SHIFT 12 |
76 | 76 | ||
77 | #define KVM_PIO_PAGE_OFFSET 1 | ||
78 | |||
77 | /* | 79 | /* |
78 | * Address types: | 80 | * Address types: |
79 | * | 81 | * |
@@ -220,6 +222,18 @@ enum { | |||
220 | VCPU_SREG_LDTR, | 222 | VCPU_SREG_LDTR, |
221 | }; | 223 | }; |
222 | 224 | ||
225 | struct kvm_pio_request { | ||
226 | unsigned long count; | ||
227 | int cur_count; | ||
228 | struct page *guest_pages[2]; | ||
229 | unsigned guest_page_offset; | ||
230 | int in; | ||
231 | int size; | ||
232 | int string; | ||
233 | int down; | ||
234 | int rep; | ||
235 | }; | ||
236 | |||
223 | struct kvm_vcpu { | 237 | struct kvm_vcpu { |
224 | struct kvm *kvm; | 238 | struct kvm *kvm; |
225 | union { | 239 | union { |
@@ -275,7 +289,8 @@ struct kvm_vcpu { | |||
275 | int mmio_size; | 289 | int mmio_size; |
276 | unsigned char mmio_data[8]; | 290 | unsigned char mmio_data[8]; |
277 | gpa_t mmio_phys_addr; | 291 | gpa_t mmio_phys_addr; |
278 | int pio_pending; | 292 | struct kvm_pio_request pio; |
293 | void *pio_data; | ||
279 | 294 | ||
280 | int sigset_active; | 295 | int sigset_active; |
281 | sigset_t sigset; | 296 | sigset_t sigset; |
@@ -421,6 +436,7 @@ hpa_t gpa_to_hpa(struct kvm_vcpu *vcpu, gpa_t gpa); | |||
421 | #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB) | 436 | #define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB) |
422 | static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } | 437 | static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } |
423 | hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva); | 438 | hpa_t gva_to_hpa(struct kvm_vcpu *vcpu, gva_t gva); |
439 | struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva); | ||
424 | 440 | ||
425 | void kvm_emulator_want_group7_invlpg(void); | 441 | void kvm_emulator_want_group7_invlpg(void); |
426 | 442 | ||
@@ -453,6 +469,9 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long value, | |||
453 | 469 | ||
454 | struct x86_emulate_ctxt; | 470 | struct x86_emulate_ctxt; |
455 | 471 | ||
472 | int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, | ||
473 | int size, unsigned long count, int string, int down, | ||
474 | gva_t address, int rep, unsigned port); | ||
456 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu); | 475 | void kvm_emulate_cpuid(struct kvm_vcpu *vcpu); |
457 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); | 476 | int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address); |
458 | int emulate_clts(struct kvm_vcpu *vcpu); | 477 | int emulate_clts(struct kvm_vcpu *vcpu); |