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); }