target/i386: use multiple CPU AddressSpaces

This speeds up SMM switches. Later on it may remove the need to take
the BQL, and it may also allow to reuse code between TCG and KVM.

Backports commit f8c45c6550b9ff1e1f0b92709ff3213a79870879 from qemu
This commit is contained in:
Paolo Bonzini 2018-03-03 14:44:30 -05:00 committed by Lioncash
parent 710f393c13
commit 741ff79e23
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 59 additions and 34 deletions

View file

@ -3313,15 +3313,29 @@ static int x86_cpu_realizefn(struct uc_struct *uc, DeviceState *dev, Error **err
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
if (tcg_enabled(uc)) { if (tcg_enabled(uc)) {
AddressSpace *newas = g_new(AddressSpace, 1); AddressSpace *as_normal = address_space_init_shareable(uc, cs->memory,
"cpu-memory");
AddressSpace *as_smm = g_new(AddressSpace, 1);
cpu->cpu_as_mem = g_new(MemoryRegion, 1);
cpu->cpu_as_root = g_new(MemoryRegion, 1); cpu->cpu_as_root = g_new(MemoryRegion, 1);
memory_region_init_alias(uc, cpu->cpu_as_root, OBJECT(cpu), "memory",
get_system_memory(uc), 0, ~0ull); /* Outer container... */
memory_region_init(uc, cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
memory_region_set_enabled(cpu->cpu_as_root, true); memory_region_set_enabled(cpu->cpu_as_root, true);
cs->num_ases = 1;
address_space_init(uc, newas, cpu->cpu_as_root, "CPU"); /* ... with two regions inside: normal system memory with low
cpu_address_space_init(cs, newas, 0); * priority, and...
*/
memory_region_init_alias(uc, cpu->cpu_as_mem, OBJECT(cpu), "memory",
get_system_memory(uc), 0, ~0ull);
memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
memory_region_set_enabled(cpu->cpu_as_mem, true);
address_space_init(uc, as_smm, cpu->cpu_as_root, "CPU");
cs->num_ases = 2;
cpu_address_space_init(cs, as_normal, 0);
cpu_address_space_init(cs, as_smm, 1);
} }
#endif #endif
@ -3485,6 +3499,7 @@ static void x86_cpu_common_class_init(struct uc_struct *uc, ObjectClass *oc, voi
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
cc->handle_mmu_fault = x86_cpu_handle_mmu_fault; cc->handle_mmu_fault = x86_cpu_handle_mmu_fault;
#else #else
cc->asidx_from_attrs = x86_asidx_from_attrs;
cc->get_memory_mapping = x86_cpu_get_memory_mapping; cc->get_memory_mapping = x86_cpu_get_memory_mapping;
cc->get_phys_page_debug = x86_cpu_get_phys_page_debug; cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
#endif #endif

View file

@ -1244,7 +1244,7 @@ typedef struct X86CPU {
/* in order to simplify APIC support, we leave this pointer to the /* in order to simplify APIC support, we leave this pointer to the
user */ user */
struct DeviceState *apic_state; struct DeviceState *apic_state;
struct MemoryRegion *cpu_as_root; struct MemoryRegion *cpu_as_root, *cpu_as_mem, *smram;
int32_t socket_id; int32_t socket_id;
int32_t core_id; int32_t core_id;
@ -1424,6 +1424,16 @@ int x86_cpu_handle_mmu_fault(CPUState *cpu, vaddr addr,
void x86_cpu_set_a20(X86CPU *cpu, int a20_state); void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static inline int x86_asidx_from_attrs(CPUState *cs, MemTxAttrs attrs)
{
return !!attrs.secure;
}
static inline AddressSpace *cpu_addressspace(CPUState *cs, MemTxAttrs attrs)
{
return cpu_get_address_space(cs, cpu_asidx_from_attrs(cs, attrs));
}
uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr); uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr);
uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr); uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr);
uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr); uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr);

View file

@ -1082,89 +1082,89 @@ uint8_t x86_ldub_phys(CPUState *cs, hwaddr addr)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
return address_space_ldub(cs->as, addr, return address_space_ldub(as, addr, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr) uint32_t x86_lduw_phys(CPUState *cs, hwaddr addr)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
return address_space_lduw(cs->as, addr, return address_space_lduw(as, addr, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr) uint32_t x86_ldl_phys(CPUState *cs, hwaddr addr)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
return address_space_ldl(cs->as, addr, return address_space_ldl(as, addr, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr) uint64_t x86_ldq_phys(CPUState *cs, hwaddr addr)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
return address_space_ldq(cs->as, addr, return address_space_ldq(as, addr, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val) void x86_stb_phys(CPUState *cs, hwaddr addr, uint8_t val)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
address_space_stb(cs->as, addr, val, address_space_stb(as, addr, val, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val) void x86_stl_phys_notdirty(CPUState *cs, hwaddr addr, uint32_t val)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
address_space_stl_notdirty(cs->as, addr, val, address_space_stl_notdirty(as, addr, val, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val) void x86_stw_phys(CPUState *cs, hwaddr addr, uint32_t val)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
address_space_stw(cs->as, addr, val, address_space_stw(as, addr, val, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val) void x86_stl_phys(CPUState *cs, hwaddr addr, uint32_t val)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
address_space_stl(cs->as, addr, val, address_space_stl(as, addr, val, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val) void x86_stq_phys(CPUState *cs, hwaddr addr, uint64_t val)
{ {
X86CPU *cpu = X86_CPU(NULL, cs); X86CPU *cpu = X86_CPU(NULL, cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
MemTxAttrs attrs = cpu_get_mem_attrs(env);
AddressSpace *as = cpu_addressspace(cs, attrs);
address_space_stq(cs->as, addr, val, address_space_stq(as, addr, val, attrs, NULL);
cpu_get_mem_attrs(env),
NULL);
} }
#endif #endif