kvm: move kvm_set_phys_mem around

move kvm_set_phys_mem so that it will
be later available earlier in the file.
needed for next patch using memory notifiers.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Michael S. Tsirkin 2010-01-27 22:07:08 +02:00 committed by Anthony Liguori
parent f6f3fbcab0
commit 46dbef6ade

276
kvm-all.c
View File

@ -402,6 +402,144 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
void kvm_set_phys_mem(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
KVMSlot *mem, old;
int err;
if (start_addr & ~TARGET_PAGE_MASK) {
if (flags >= IO_MEM_UNASSIGNED) {
if (!kvm_lookup_overlapping_slot(s, start_addr,
start_addr + size)) {
return;
}
fprintf(stderr, "Unaligned split of a KVM memory slot\n");
} else {
fprintf(stderr, "Only page-aligned memory slots supported\n");
}
abort();
}
/* KVM does not support read-only slots */
phys_offset &= ~IO_MEM_ROM;
while (1) {
mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
if (!mem) {
break;
}
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)) {
/* The new slot fits into the existing one and comes with
* identical parameters - nothing to be done. */
return;
}
old = *mem;
/* unregister the overlapping slot */
mem->memory_size = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
__func__, strerror(-err));
abort();
}
/* Workaround for older KVM versions: we can't join slots, even not by
* unregistering the previous ones and then registering the larger
* slot. We have to maintain the existing fragmentation. Sigh.
*
* This workaround assumes that the new slot starts at the same
* address as the first existing one. If not or if some overlapping
* slot comes around later, we will fail (not seen in practice so far)
* - and actually require a recent KVM version. */
if (s->broken_set_mem_region &&
old.start_addr == start_addr && old.memory_size < size &&
flags < IO_MEM_UNASSIGNED) {
mem = kvm_alloc_slot(s);
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
mem->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error updating slot: %s\n", __func__,
strerror(-err));
abort();
}
start_addr += old.memory_size;
phys_offset += old.memory_size;
size -= old.memory_size;
continue;
}
/* register prefix slot */
if (old.start_addr < start_addr) {
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->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering prefix slot: %s\n",
__func__, strerror(-err));
abort();
}
}
/* register suffix slot */
if (old.start_addr + old.memory_size > start_addr + size) {
ram_addr_t size_delta;
mem = kvm_alloc_slot(s);
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->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering suffix slot: %s\n",
__func__, strerror(-err));
abort();
}
}
}
/* in case the KVM bug workaround already "consumed" the new slot */
if (!size)
return;
/* KVM does not need to know about this memory */
if (flags >= IO_MEM_UNASSIGNED)
return;
mem = kvm_alloc_slot(s);
mem->memory_size = size;
mem->start_addr = start_addr;
mem->phys_offset = phys_offset;
mem->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering slot: %s\n", __func__,
strerror(-err));
abort();
}
}
int kvm_init(int smp_cpus)
{
static const char upgrade_note[] =
@ -680,144 +818,6 @@ int kvm_cpu_exec(CPUState *env)
return ret;
}
void kvm_set_phys_mem(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
KVMSlot *mem, old;
int err;
if (start_addr & ~TARGET_PAGE_MASK) {
if (flags >= IO_MEM_UNASSIGNED) {
if (!kvm_lookup_overlapping_slot(s, start_addr,
start_addr + size)) {
return;
}
fprintf(stderr, "Unaligned split of a KVM memory slot\n");
} else {
fprintf(stderr, "Only page-aligned memory slots supported\n");
}
abort();
}
/* KVM does not support read-only slots */
phys_offset &= ~IO_MEM_ROM;
while (1) {
mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
if (!mem) {
break;
}
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)) {
/* The new slot fits into the existing one and comes with
* identical parameters - nothing to be done. */
return;
}
old = *mem;
/* unregister the overlapping slot */
mem->memory_size = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
__func__, strerror(-err));
abort();
}
/* Workaround for older KVM versions: we can't join slots, even not by
* unregistering the previous ones and then registering the larger
* slot. We have to maintain the existing fragmentation. Sigh.
*
* This workaround assumes that the new slot starts at the same
* address as the first existing one. If not or if some overlapping
* slot comes around later, we will fail (not seen in practice so far)
* - and actually require a recent KVM version. */
if (s->broken_set_mem_region &&
old.start_addr == start_addr && old.memory_size < size &&
flags < IO_MEM_UNASSIGNED) {
mem = kvm_alloc_slot(s);
mem->memory_size = old.memory_size;
mem->start_addr = old.start_addr;
mem->phys_offset = old.phys_offset;
mem->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error updating slot: %s\n", __func__,
strerror(-err));
abort();
}
start_addr += old.memory_size;
phys_offset += old.memory_size;
size -= old.memory_size;
continue;
}
/* register prefix slot */
if (old.start_addr < start_addr) {
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->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering prefix slot: %s\n",
__func__, strerror(-err));
abort();
}
}
/* register suffix slot */
if (old.start_addr + old.memory_size > start_addr + size) {
ram_addr_t size_delta;
mem = kvm_alloc_slot(s);
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->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering suffix slot: %s\n",
__func__, strerror(-err));
abort();
}
}
}
/* in case the KVM bug workaround already "consumed" the new slot */
if (!size)
return;
/* KVM does not need to know about this memory */
if (flags >= IO_MEM_UNASSIGNED)
return;
mem = kvm_alloc_slot(s);
mem->memory_size = size;
mem->start_addr = start_addr;
mem->phys_offset = phys_offset;
mem->flags = 0;
err = kvm_set_user_memory_region(s, mem);
if (err) {
fprintf(stderr, "%s: error registering slot: %s\n", __func__,
strerror(-err));
abort();
}
}
int kvm_ioctl(KVMState *s, int type, ...)
{
int ret;