* [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