From 51369b67cd567ab4df084a2dfea9bf97a0cf8a18 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 17 Feb 2018 22:33:49 -0500 Subject: [PATCH] exec.c: Allow target CPUs to define multiple AddressSpaces Allow multiple calls to cpu_address_space_init(); each call adds an entry to the cpu->ases array at the specified index. It is up to the target-specific CPU code to actually use these extra address spaces. Since this multiple AddressSpace support won't work with KVM, add an assertion to avoid confusing failures. Backports commit 12ebc9a76dd7702aef0a3618717a826c19c34ef4 from qemu --- qemu/cpus.c | 1 + qemu/exec.c | 28 +++++++++++++++++----------- qemu/include/exec/exec-all.h | 4 ++++ qemu/include/qom/cpu.h | 5 +++++ qemu/target-i386/cpu.c | 1 + 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/qemu/cpus.c b/qemu/cpus.c index 8f5835c2..76bfd07a 100644 --- a/qemu/cpus.c +++ b/qemu/cpus.c @@ -114,6 +114,7 @@ static int qemu_tcg_init_vcpu(CPUState *cpu) /* If the target cpu hasn't set up any address spaces itself, * give it the default one. */ + cpu->num_ases = 1; cpu_address_space_init(cpu, &cpu->uc->as, 0); } diff --git a/qemu/exec.c b/qemu/exec.c index e92ec6a4..f8603e6f 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -385,25 +385,30 @@ CPUState *qemu_get_cpu(struct uc_struct *uc, int index) #if !defined(CONFIG_USER_ONLY) void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx) { + CPUAddressSpace *newas; + + /* Target code should have set num_ases before calling us */ + assert(asidx < cpu->num_ases); + if (asidx == 0) { /* address space 0 gets the convenience alias */ cpu->as = as; } - /* We only support one address space per cpu at the moment. */ - assert(cpu->as == as); + /* KVM cannot currently support multiple address spaces. */ + // Unicorn: commented out + //assert(asidx == 0 || !kvm_enabled()); - if (cpu->cpu_ases) { - /* We've already registered the listener for our only AS */ - return; + if (!cpu->cpu_ases) { + cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases); } - cpu->cpu_ases = g_new0(CPUAddressSpace, 1); - cpu->cpu_ases[0].cpu = cpu; - cpu->cpu_ases[0].as = as; + newas = &cpu->cpu_ases[asidx]; + newas->cpu = cpu; + newas->as = as; if (tcg_enabled(as->uc)) { - cpu->cpu_ases[0].tcg_as_listener.commit = tcg_commit; - memory_listener_register(as->uc, &cpu->cpu_ases[0].tcg_as_listener, as); + newas->tcg_as_listener.commit = tcg_commit; + memory_listener_register(as->uc, &newas->tcg_as_listener, as); } } #endif @@ -413,8 +418,9 @@ void cpu_exec_init(CPUState *cpu, void *opaque) struct uc_struct *uc = opaque; CPUArchState *env = cpu->env_ptr; - cpu->cpu_index = 0; cpu->as = NULL; + cpu->cpu_index = 0; + cpu->num_ases = 0; cpu->uc = uc; env->uc = uc; diff --git a/qemu/include/exec/exec-all.h b/qemu/include/exec/exec-all.h index ae9770ec..baccb4d8 100644 --- a/qemu/include/exec/exec-all.h +++ b/qemu/include/exec/exec-all.h @@ -95,6 +95,10 @@ void cpu_reload_memory_map(CPUState *cpu); * The target-specific code which registers ASes is responsible * for defining what semantics address space 0, 1, 2, etc have. * + * Before the first call to this function, the caller must set + * cpu->num_ases to the total number of address spaces it needs + * to support. + * * Note that with KVM only one address space is supported. */ void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx); diff --git a/qemu/include/qom/cpu.h b/qemu/include/qom/cpu.h index 3b27dad3..9fdfebde 100644 --- a/qemu/include/qom/cpu.h +++ b/qemu/include/qom/cpu.h @@ -209,6 +209,11 @@ struct CPUAddressSpace { * This allows a single read-compare-cbranch-write sequence to test * for both decrementer underflow and exceptions. * @can_do_io: Nonzero if memory-mapped IO is safe. + * @cpu_ases: Pointer to array of CPUAddressSpaces (which define the + * AddressSpaces this CPU has) + * @num_ases: number of CPUAddressSpaces in @cpu_ases + * @as: Pointer to the first AddressSpace, for the convenience of targets which + * only have a single AddressSpace * @env_ptr: Pointer to subclass-specific CPUArchState field. * @current_tb: Currently executing TB. * @next_cpu: Next CPU sharing TB cache. diff --git a/qemu/target-i386/cpu.c b/qemu/target-i386/cpu.c index ffd3c8cc..023d989a 100644 --- a/qemu/target-i386/cpu.c +++ b/qemu/target-i386/cpu.c @@ -2607,6 +2607,7 @@ static int x86_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err memory_region_init_alias(uc, cpu->cpu_as_root, OBJECT(cpu), "memory", get_system_memory(uc), 0, ~0ull); memory_region_set_enabled(cpu->cpu_as_root, true); + cs->num_ases = 1; address_space_init(uc, newas, cpu->cpu_as_root, "CPU"); cpu_address_space_init(cs, newas, 0); }