[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/6] kvm: memory aliasing support for kvm
From: |
Glauber Costa |
Subject: |
[Qemu-devel] [PATCH 1/6] kvm: memory aliasing support for kvm |
Date: |
Wed, 19 Nov 2008 13:26:12 -0200 |
We use information encoded in phys_offset to support memory
alias for kvm-all.c. Recall that for any given memory slot,
userspace_addr = phys_ram_base + phys_offset (without any flags).
This way, we can detect whether or not the registered slot is
effectively pointing to the same area, regardless of the fact
that it has a different guest_phys_addr.
Signed-off-by: Glauber Costa <address@hidden>
---
kvm-all.c | 36 +++++++++++++++++++++++++-
kvm.h | 6 ++++
target-i386/kvm.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 1 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index d3fcf8b..b5bbdcb 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -75,6 +75,28 @@ static KVMSlot *kvm_lookup_slot(KVMState *s,
target_phys_addr_t start_addr)
return NULL;
}
+/*
+ * If we are trying to register a slot that points to the same address
+ * (phys_offset) of an already existing slot, data should go to the same
+ * place regardless of to which guest_phys_addr we write to. When we are
+ * using the kvm_alias API, it means it should be an alias.
+ */
+static KVMSlot *kvm_should_alias(KVMState *s, ram_addr_t phys_offset)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ KVMSlot *mem = &s->slots[i];
+
+ ram_addr_t addr = mem->userspace_addr - (ram_addr_t)phys_ram_base;
+
+ if (phys_offset >= addr &&
+ phys_offset < (addr + mem->memory_size))
+ return mem;
+ }
+ return NULL;
+}
+
int kvm_init_vcpu(CPUState *env)
{
KVMState *s = kvm_state;
@@ -315,7 +337,7 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
- KVMSlot *mem;
+ KVMSlot *mem, *as;
/* KVM does not support read-only slots */
phys_offset &= ~IO_MEM_ROM;
@@ -369,10 +391,22 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
abort();
}
}
+
+ if (((flags == IO_MEM_UNASSIGNED) || (flags >= TLB_MMIO))
+ && (kvm_arch_destroy_alias_slot(s, start_addr)))
+ return;
+
/* KVM does not need to know about this memory */
if (flags >= IO_MEM_UNASSIGNED)
return;
+ if ((as = kvm_should_alias(s, phys_offset))) {
+ target_phys_addr_t target_addr = as->guest_phys_addr;
+ target_addr += phys_offset - (as->userspace_addr -
(ram_addr_t)phys_ram_base);
+ kvm_arch_set_alias_slot(s, start_addr, size, target_addr);
+ return;
+ }
+
mem = kvm_alloc_slot(s);
mem->memory_size = size;
mem->guest_phys_addr = start_addr;
diff --git a/kvm.h b/kvm.h
index 304de27..7588601 100644
--- a/kvm.h
+++ b/kvm.h
@@ -51,6 +51,12 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...);
/* Arch specific hooks */
+int kvm_arch_is_alias_slot(target_phys_addr_t start_addr);
+int kvm_arch_destroy_alias_slot(KVMState *s, target_phys_addr_t start_addr);
+void kvm_arch_set_alias_slot(KVMState *s, target_phys_addr_t start_addr,
+ ram_addr_t size,
+ target_phys_addr_t target_addr);
+
int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 3f60654..4ede68a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -33,6 +33,74 @@
do { } while (0)
#endif
+typedef struct kvm_memory_alias KVMAliasSlot;
+
+static KVMAliasSlot alias_slots[8];
+
+static KVMAliasSlot *kvm_lookup_alias_slot(target_phys_addr_t start_addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(alias_slots); i++) {
+ KVMAliasSlot *as = &alias_slots[i];
+
+ if (start_addr >= as->guest_phys_addr &&
+ start_addr < (as->guest_phys_addr + as->memory_size))
+ return as;
+ }
+
+ return NULL;
+}
+
+int kvm_arch_is_alias_slot(target_phys_addr_t start_addr)
+{
+ return !!kvm_lookup_alias_slot(start_addr);
+}
+
+static KVMAliasSlot *kvm_alloc_alias_slot(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(alias_slots); i++) {
+ if (alias_slots[i].memory_size == 0)
+ return &alias_slots[i];
+ }
+
+ return NULL;
+}
+
+int kvm_arch_destroy_alias_slot(KVMState *s, target_phys_addr_t start_addr)
+{
+
+ KVMAliasSlot *as = kvm_lookup_alias_slot(start_addr);
+ if (!as)
+ return 0;
+ as->memory_size = 0;
+ as->target_phys_addr = 0;
+
+ kvm_vm_ioctl(s, KVM_SET_MEMORY_ALIAS, as);
+ return 1;
+}
+
+void kvm_arch_set_alias_slot(KVMState *s, target_phys_addr_t start_addr,
+ ram_addr_t size,
+ target_phys_addr_t target_addr)
+{
+
+ int r;
+ KVMAliasSlot *as = kvm_lookup_alias_slot(start_addr);
+
+ if (!as)
+ as = kvm_alloc_alias_slot();
+
+ as->guest_phys_addr = (uint64_t)start_addr;
+ as->memory_size = (uint64_t)size;
+ as->target_phys_addr = (uint64_t)target_addr;
+ as->flags = 0;
+
+ r = kvm_vm_ioctl(s, KVM_SET_MEMORY_ALIAS, as);
+}
+
int kvm_arch_init_vcpu(CPUState *env)
{
struct {
@@ -42,6 +110,10 @@ int kvm_arch_init_vcpu(CPUState *env)
int limit, i, cpuid_i;
uint32_t eax, ebx, ecx, edx;
+
+ for (i = 0; i < ARRAY_SIZE(alias_slots); i++)
+ alias_slots[i].slot = i;
+
cpuid_i = 0;
cpu_x86_cpuid(env, 0, &eax, &ebx, &ecx, &edx);
--
1.5.6.5
- [Qemu-devel] [PATCH 0/6] New shot at VGA optimization, Glauber Costa, 2008/11/19
- [Qemu-devel] [PATCH 1/6] kvm: memory aliasing support for kvm,
Glauber Costa <=
- [Qemu-devel] [PATCH 2/6] better type checking for vga, Glauber Costa, 2008/11/19
- [Qemu-devel] [PATCH 3/6] move vga_io_address to VGA State, Glauber Costa, 2008/11/19
- [Qemu-devel] [PATCH 4/6] kvm: de-register mem region for MMIO., Glauber Costa, 2008/11/19
- [Qemu-devel] [PATCH 5/6] Introduce kvm logging interface., Glauber Costa, 2008/11/19
- [Qemu-devel] [PATCH 6/6] kvm: vga optimization., Glauber Costa, 2008/11/19
- Re: [Qemu-devel] [PATCH 6/6] kvm: vga optimization., Anthony Liguori, 2008/11/19
- Re: [Qemu-devel] [PATCH 6/6] kvm: vga optimization., Glauber Costa, 2008/11/19
- Re: [Qemu-devel] [PATCH 6/6] kvm: vga optimization., Anthony Liguori, 2008/11/19
- Re: [Qemu-devel] [PATCH 5/6] Introduce kvm logging interface., Anthony Liguori, 2008/11/19
- Re: [Qemu-devel] [PATCH 5/6] Introduce kvm logging interface., Glauber Costa, 2008/11/19