* [PATCH 0/2] remove kvm vmap usage
@ 2008-12-28 23:42 Izik Eidus
2008-12-28 23:42 ` [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt Izik Eidus
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Izik Eidus @ 2008-12-28 23:42 UTC (permalink / raw)
To: kvm; +Cc: avi
Remove the vmap usage from kvm, this is needed both for ksm and
get_user_pages != write.
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt. 2008-12-28 23:42 [PATCH 0/2] remove kvm vmap usage Izik Eidus @ 2008-12-28 23:42 ` Izik Eidus 2008-12-28 23:42 ` [PATCH 2/2] KVM: remove the vmap usage Izik Eidus 2008-12-29 0:06 ` [PATCH 0/2] remove kvm " Izik Eidus 2008-12-29 8:36 ` Avi Kivity 2 siblings, 1 reply; 5+ messages in thread From: Izik Eidus @ 2008-12-28 23:42 UTC (permalink / raw) To: kvm; +Cc: avi, Izik Eidus This commit change the name of emulator_read_std into kvm_read_guest_virt, and add new function name kvm_write_guest_virt that allow writing into a guest virtual address. Signed-off-by: Izik Eidus <ieidus@redhat.com> --- arch/x86/include/asm/kvm_host.h | 4 --- arch/x86/kvm/x86.c | 56 +++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index ab8ef1d..a129700 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -608,10 +608,6 @@ void kvm_inject_nmi(struct kvm_vcpu *vcpu); void fx_init(struct kvm_vcpu *vcpu); -int emulator_read_std(unsigned long addr, - void *val, - unsigned int bytes, - struct kvm_vcpu *vcpu); int emulator_write_emulated(unsigned long addr, const void *val, unsigned int bytes, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index aa4575c..c812209 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1973,10 +1973,8 @@ static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu, return dev; } -int emulator_read_std(unsigned long addr, - void *val, - unsigned int bytes, - struct kvm_vcpu *vcpu) +int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) { void *data = val; int r = X86EMUL_CONTINUE; @@ -1984,27 +1982,57 @@ int emulator_read_std(unsigned long addr, while (bytes) { gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); unsigned offset = addr & (PAGE_SIZE-1); - unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset); + unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset); int ret; if (gpa == UNMAPPED_GVA) { r = X86EMUL_PROPAGATE_FAULT; goto out; } - ret = kvm_read_guest(vcpu->kvm, gpa, data, tocopy); + ret = kvm_read_guest(vcpu->kvm, gpa, data, toread); if (ret < 0) { r = X86EMUL_UNHANDLEABLE; goto out; } - bytes -= tocopy; - data += tocopy; - addr += tocopy; + bytes -= toread; + data += toread; + addr += toread; } out: return r; } -EXPORT_SYMBOL_GPL(emulator_read_std); + +int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes, + struct kvm_vcpu *vcpu) +{ + void *data = val; + int r = X86EMUL_CONTINUE; + + while (bytes) { + gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr); + unsigned offset = addr & (PAGE_SIZE-1); + unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset); + int ret; + + if (gpa == UNMAPPED_GVA) { + r = X86EMUL_PROPAGATE_FAULT; + goto out; + } + ret = kvm_write_guest(vcpu->kvm, gpa, data, towrite); + if (ret < 0) { + r = X86EMUL_UNHANDLEABLE; + goto out; + } + + bytes -= towrite; + data += towrite; + addr += towrite; + } +out: + return r; +} + static int emulator_read_emulated(unsigned long addr, void *val, @@ -2026,8 +2054,8 @@ static int emulator_read_emulated(unsigned long addr, if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) goto mmio; - if (emulator_read_std(addr, val, bytes, vcpu) - == X86EMUL_CONTINUE) + if (kvm_read_guest_virt(addr, val, bytes, vcpu) + == X86EMUL_CONTINUE) return X86EMUL_CONTINUE; if (gpa == UNMAPPED_GVA) return X86EMUL_PROPAGATE_FAULT; @@ -2230,7 +2258,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS); - emulator_read_std(rip_linear, (void *)opcodes, 4, vcpu); + kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu); printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n", context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]); @@ -2238,7 +2266,7 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context) EXPORT_SYMBOL_GPL(kvm_report_emulation_failure); static struct x86_emulate_ops emulate_ops = { - .read_std = emulator_read_std, + .read_std = kvm_read_guest_virt, .read_emulated = emulator_read_emulated, .write_emulated = emulator_write_emulated, .cmpxchg_emulated = emulator_cmpxchg_emulated, -- 1.6.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] KVM: remove the vmap usage 2008-12-28 23:42 ` [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt Izik Eidus @ 2008-12-28 23:42 ` Izik Eidus 0 siblings, 0 replies; 5+ messages in thread From: Izik Eidus @ 2008-12-28 23:42 UTC (permalink / raw) To: kvm; +Cc: avi, Izik Eidus Signed-off-by: Izik Eidus <ieidus@redhat.com> --- arch/x86/kvm/x86.c | 62 +++++++++----------------------------------- include/linux/kvm_types.h | 3 +- 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c812209..29df564 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2368,40 +2368,19 @@ int emulate_instruction(struct kvm_vcpu *vcpu, } EXPORT_SYMBOL_GPL(emulate_instruction); -static void free_pio_guest_pages(struct kvm_vcpu *vcpu) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(vcpu->arch.pio.guest_pages); ++i) - if (vcpu->arch.pio.guest_pages[i]) { - kvm_release_page_dirty(vcpu->arch.pio.guest_pages[i]); - vcpu->arch.pio.guest_pages[i] = NULL; - } -} - static int pio_copy_data(struct kvm_vcpu *vcpu) { void *p = vcpu->arch.pio_data; - void *q; + gva_t q = vcpu->arch.pio.guest_gva; unsigned bytes; - int nr_pages = vcpu->arch.pio.guest_pages[1] ? 2 : 1; + int ret; - q = vmap(vcpu->arch.pio.guest_pages, nr_pages, VM_READ|VM_WRITE, - PAGE_KERNEL); - if (!q) { - free_pio_guest_pages(vcpu); - return -ENOMEM; - } - q += vcpu->arch.pio.guest_page_offset; bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count; if (vcpu->arch.pio.in) - memcpy(q, p, bytes); + ret = kvm_write_guest_virt(q, p, bytes, vcpu); else - memcpy(p, q, bytes); - q -= vcpu->arch.pio.guest_page_offset; - vunmap(q); - free_pio_guest_pages(vcpu); - return 0; + ret = kvm_read_guest_virt(q, p, bytes, vcpu); + return ret; } int complete_pio(struct kvm_vcpu *vcpu) @@ -2512,7 +2491,6 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, vcpu->arch.pio.in = in; vcpu->arch.pio.string = 0; vcpu->arch.pio.down = 0; - vcpu->arch.pio.guest_page_offset = 0; vcpu->arch.pio.rep = 0; if (vcpu->run->io.direction == KVM_EXIT_IO_IN) @@ -2540,9 +2518,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, gva_t address, int rep, unsigned port) { unsigned now, in_page; - int i, ret = 0; - int nr_pages = 1; - struct page *page; + int ret = 0; struct kvm_io_device *pio_dev; vcpu->run->exit_reason = KVM_EXIT_IO; @@ -2554,7 +2530,6 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, vcpu->arch.pio.in = in; vcpu->arch.pio.string = 1; vcpu->arch.pio.down = down; - vcpu->arch.pio.guest_page_offset = offset_in_page(address); vcpu->arch.pio.rep = rep; if (vcpu->run->io.direction == KVM_EXIT_IO_IN) @@ -2574,15 +2549,8 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, else in_page = offset_in_page(address) + size; now = min(count, (unsigned long)in_page / size); - if (!now) { - /* - * String I/O straddles page boundary. Pin two guest pages - * so that we satisfy atomicity constraints. Do just one - * transaction to avoid complexity. - */ - nr_pages = 2; + if (!now) now = 1; - } if (down) { /* * String I/O in reverse. Yuck. Kill the guest, fix later. @@ -2597,15 +2565,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, if (vcpu->arch.pio.cur_count == vcpu->arch.pio.count) kvm_x86_ops->skip_emulated_instruction(vcpu); - for (i = 0; i < nr_pages; ++i) { - page = gva_to_page(vcpu, address + i * PAGE_SIZE); - vcpu->arch.pio.guest_pages[i] = page; - if (!page) { - kvm_inject_gp(vcpu, 0); - free_pio_guest_pages(vcpu); - return 1; - } - } + vcpu->arch.pio.guest_gva = address; pio_dev = vcpu_find_pio_dev(vcpu, port, vcpu->arch.pio.cur_count, @@ -2613,7 +2573,11 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in, if (!vcpu->arch.pio.in) { /* string PIO write */ ret = pio_copy_data(vcpu); - if (ret >= 0 && pio_dev) { + if (ret == X86EMUL_PROPAGATE_FAULT) { + kvm_inject_gp(vcpu, 0); + return 1; + } + if (ret == 0 && pio_dev) { pio_string_write(pio_dev, vcpu); complete_pio(vcpu); if (vcpu->arch.pio.count == 0) diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 9b6f395..5f4a18c 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -43,8 +43,7 @@ typedef hfn_t pfn_t; struct kvm_pio_request { unsigned long count; int cur_count; - struct page *guest_pages[2]; - unsigned guest_page_offset; + gva_t guest_gva; int in; int port; int size; -- 1.6.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] remove kvm vmap usage 2008-12-28 23:42 [PATCH 0/2] remove kvm vmap usage Izik Eidus 2008-12-28 23:42 ` [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt Izik Eidus @ 2008-12-29 0:06 ` Izik Eidus 2008-12-29 8:36 ` Avi Kivity 2 siblings, 0 replies; 5+ messages in thread From: Izik Eidus @ 2008-12-29 0:06 UTC (permalink / raw) To: kvm; +Cc: avi Izik Eidus wrote: > Remove the vmap usage from kvm, this is needed both for ksm and > get_user_pages != write. > -- > To unsubscribe from this list: send the line "unsubscribe kvm" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Ok so for ksm things are now all right, actully i could live without this vmap as well, beacuse ksm check the page _count and every call to gva_to_page should increase it. anyway before i continue with the kmap removing (again ksm doesnt need it, only get_user_pages != write) does we really want to go that way? even for the get_user_pages case we can live with the write = 0, if before each kmap_atomic we will call get_user_pages (write = 1), so the page inside apic_page and time_page and what so ever would be safe (when ksm will come to merge that page it will skip it with the page count check) ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] remove kvm vmap usage 2008-12-28 23:42 [PATCH 0/2] remove kvm vmap usage Izik Eidus 2008-12-28 23:42 ` [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt Izik Eidus 2008-12-29 0:06 ` [PATCH 0/2] remove kvm " Izik Eidus @ 2008-12-29 8:36 ` Avi Kivity 2 siblings, 0 replies; 5+ messages in thread From: Avi Kivity @ 2008-12-29 8:36 UTC (permalink / raw) To: Izik Eidus; +Cc: kvm Izik Eidus wrote: > Remove the vmap usage from kvm, this is needed both for ksm and > get_user_pages != write. > applied, thanks. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-12-29 8:36 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-12-28 23:42 [PATCH 0/2] remove kvm vmap usage Izik Eidus 2008-12-28 23:42 ` [PATCH 1/2] KVM: introducing kvm_read_guest_virt, kvm_write_guest_virt Izik Eidus 2008-12-28 23:42 ` [PATCH 2/2] KVM: remove the vmap usage Izik Eidus 2008-12-29 0:06 ` [PATCH 0/2] remove kvm " Izik Eidus 2008-12-29 8:36 ` Avi Kivity
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox