kvm: switch kvm slots to use host virtual address instead of ram_addr_t
This simplifies a later switch to the memory API in slot management. Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
7664e80c84
commit
9f213ed92c
27
kvm-all.c
27
kvm-all.c
@ -50,7 +50,7 @@ typedef struct KVMSlot
|
||||
{
|
||||
target_phys_addr_t start_addr;
|
||||
ram_addr_t memory_size;
|
||||
ram_addr_t phys_offset;
|
||||
void *ram;
|
||||
int slot;
|
||||
int flags;
|
||||
} KVMSlot;
|
||||
@ -146,7 +146,7 @@ static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,
|
||||
return found;
|
||||
}
|
||||
|
||||
int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
|
||||
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
|
||||
target_phys_addr_t *phys_addr)
|
||||
{
|
||||
int i;
|
||||
@ -154,9 +154,8 @@ int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
|
||||
for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
|
||||
KVMSlot *mem = &s->slots[i];
|
||||
|
||||
if (ram_addr >= mem->phys_offset &&
|
||||
ram_addr < mem->phys_offset + mem->memory_size) {
|
||||
*phys_addr = mem->start_addr + (ram_addr - mem->phys_offset);
|
||||
if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
|
||||
*phys_addr = mem->start_addr + (ram - mem->ram);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -171,7 +170,7 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
|
||||
mem.slot = slot->slot;
|
||||
mem.guest_phys_addr = slot->start_addr;
|
||||
mem.memory_size = slot->memory_size;
|
||||
mem.userspace_addr = (unsigned long)qemu_safe_ram_ptr(slot->phys_offset);
|
||||
mem.userspace_addr = (unsigned long)slot->ram;
|
||||
mem.flags = slot->flags;
|
||||
if (s->migration_log) {
|
||||
mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
|
||||
@ -527,6 +526,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
|
||||
KVMSlot *mem, old;
|
||||
int err;
|
||||
void *ram = NULL;
|
||||
|
||||
/* kvm works in page size chunks, but the function may be called
|
||||
with sub-page size and unaligned start address. */
|
||||
@ -536,6 +536,10 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
/* KVM does not support read-only slots */
|
||||
phys_offset &= ~IO_MEM_ROM;
|
||||
|
||||
if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
|
||||
ram = qemu_safe_ram_ptr(phys_offset);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
|
||||
if (!mem) {
|
||||
@ -544,7 +548,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
|
||||
if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
|
||||
(start_addr + size <= mem->start_addr + mem->memory_size) &&
|
||||
(phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
|
||||
(ram - start_addr == mem->ram - mem->start_addr)) {
|
||||
/* The new slot fits into the existing one and comes with
|
||||
* identical parameters - update flags and done. */
|
||||
kvm_slot_dirty_pages_log_change(mem, log_dirty);
|
||||
@ -576,7 +580,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
mem = kvm_alloc_slot(s);
|
||||
mem->memory_size = old.memory_size;
|
||||
mem->start_addr = old.start_addr;
|
||||
mem->phys_offset = old.phys_offset;
|
||||
mem->ram = old.ram;
|
||||
mem->flags = kvm_mem_flags(s, log_dirty);
|
||||
|
||||
err = kvm_set_user_memory_region(s, mem);
|
||||
@ -588,6 +592,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
|
||||
start_addr += old.memory_size;
|
||||
phys_offset += old.memory_size;
|
||||
ram += old.memory_size;
|
||||
size -= old.memory_size;
|
||||
continue;
|
||||
}
|
||||
@ -597,7 +602,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
mem = kvm_alloc_slot(s);
|
||||
mem->memory_size = start_addr - old.start_addr;
|
||||
mem->start_addr = old.start_addr;
|
||||
mem->phys_offset = old.phys_offset;
|
||||
mem->ram = old.ram;
|
||||
mem->flags = kvm_mem_flags(s, log_dirty);
|
||||
|
||||
err = kvm_set_user_memory_region(s, mem);
|
||||
@ -621,7 +626,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
mem->start_addr = start_addr + size;
|
||||
size_delta = mem->start_addr - old.start_addr;
|
||||
mem->memory_size = old.memory_size - size_delta;
|
||||
mem->phys_offset = old.phys_offset + size_delta;
|
||||
mem->ram = old.ram + size_delta;
|
||||
mem->flags = kvm_mem_flags(s, log_dirty);
|
||||
|
||||
err = kvm_set_user_memory_region(s, mem);
|
||||
@ -644,7 +649,7 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
|
||||
mem = kvm_alloc_slot(s);
|
||||
mem->memory_size = size;
|
||||
mem->start_addr = start_addr;
|
||||
mem->phys_offset = phys_offset;
|
||||
mem->ram = ram;
|
||||
mem->flags = kvm_mem_flags(s, log_dirty);
|
||||
|
||||
err = kvm_set_user_memory_region(s, mem);
|
||||
|
2
kvm.h
2
kvm.h
@ -188,7 +188,7 @@ static inline void cpu_synchronize_post_init(CPUState *env)
|
||||
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
|
||||
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
|
||||
target_phys_addr_t *phys_addr);
|
||||
#endif
|
||||
|
||||
|
6
memory.c
6
memory.c
@ -769,11 +769,11 @@ static void address_space_update_topology_pass(AddressSpace *as,
|
||||
|
||||
if (adding) {
|
||||
if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
|
||||
MEMORY_LISTENER_UPDATE_REGION(frold, as, log_stop);
|
||||
MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_stop);
|
||||
as->ops->log_stop(as, frnew);
|
||||
} else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
|
||||
as->ops->log_start(as, frnew);
|
||||
MEMORY_LISTENER_UPDATE_REGION(frold, as, log_start);
|
||||
MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_start);
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,7 +784,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
|
||||
|
||||
if (adding) {
|
||||
as->ops->range_add(as, frnew);
|
||||
MEMORY_LISTENER_UPDATE_REGION(frold, as, region_add);
|
||||
MEMORY_LISTENER_UPDATE_REGION(frnew, as, region_add);
|
||||
}
|
||||
|
||||
++inew;
|
||||
|
@ -253,8 +253,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
|
||||
if ((env->mcg_cap & MCG_SER_P) && addr
|
||||
&& (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
|
||||
if (qemu_ram_addr_from_host(addr, &ram_addr) ||
|
||||
!kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr,
|
||||
&paddr)) {
|
||||
!kvm_physical_memory_addr_from_host(env->kvm_state, addr, &paddr)) {
|
||||
fprintf(stderr, "Hardware memory error for memory used by "
|
||||
"QEMU itself instead of guest system!\n");
|
||||
/* Hope we are lucky for AO MCE */
|
||||
@ -286,7 +285,7 @@ int kvm_arch_on_sigbus(int code, void *addr)
|
||||
|
||||
/* Hope we are lucky for AO MCE */
|
||||
if (qemu_ram_addr_from_host(addr, &ram_addr) ||
|
||||
!kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
|
||||
!kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr,
|
||||
&paddr)) {
|
||||
fprintf(stderr, "Hardware memory error for memory used by "
|
||||
"QEMU itself instead of guest system!: %p\n", addr);
|
||||
|
Loading…
Reference in New Issue
Block a user