mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 13:30:52 +00:00
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:
parent
f6f3fbcab0
commit
46dbef6ade
276
kvm-all.c
276
kvm-all.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user