[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration
|
From: |
Claudio Fontana |
|
Subject: |
Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration |
|
Date: |
Tue, 10 Nov 2020 10:49:05 +0100 |
|
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.12.0 |
Hello Eduardo,
thank you for your answer,
On 11/9/20 8:04 PM, Eduardo Habkost wrote:
> On Mon, Nov 09, 2020 at 06:27:54PM +0100, Claudio Fontana wrote:
>> split cpu.c into:
>>
>> cpu.c cpuid and common x86 cpu functionality
>> host-cpu.c host x86 cpu functions and "host" cpu type
>> kvm-cpu-type.c KVM x86 cpu type
>> hvf-cpu-type.c HVF x86 cpu type
>> tcg-cpu-type.c TCG x86 cpu type
>>
>> Defer the x86 models registration to MODULE_INIT_ACCEL_CPU,
>> so that accel-specific types can be used as parent types for all
>> cpu models. Use the generic TYPE_X86_CPU only if no
>> accel-specific specialization is enabled.
>
> This is very unfriendly to introspection, I don't think this is
> the direction we want to go with the QOM type hierarchy.
>
> Why do you need inheritance here? accel-specific behavior can be
> delegated to a separate object, instead of requiring the CPU
> object to inherit from a accel-specific class.
Looking in detail at QOM CPU I got the impression that really it's inheritance
that makes sense here,
it just flows correctly I think from an OOP perspective.
I'd note that it's not really the specialized cpu types that are the problem.
TYPE_TCG_CPU , TYPE_KVM_CPU are defined statically as usual during
MODULE_INIT_QOM time.
That part actually works surprisingly well and seems just the right thing to do
to me.
It's the second step that is the contentious one I think, ie the CPU models
registration.
>
> In case inheritance is really the best mechanism for this, I'd
> prefer to register accel-specific subclasses unconditionally, and
Indeed, accel-specific sub types are already registered unconditionally.
> make cpu_class_by_name() resolve to the right accel-specific
> class name.
Ah! I'll look at this!
This might point into a new direction.
Thanks!
Claudio
>
>>
>> Signed-off-by: Claudio Fontana <cfontana@suse.de>
>> ---
>> bsd-user/main.c | 4 +
>> hw/i386/pc_piix.c | 1 +
>> linux-user/main.c | 10 +-
>> softmmu/vl.c | 2 +-
>> target/i386/accel/hvf/hvf-cpu-type.c | 78 +++++
>> target/i386/accel/hvf/meson.build | 1 +
>> target/i386/accel/kvm/kvm-cpu-type.c | 161 ++++++++++
>> target/i386/accel/kvm/kvm-cpu-type.h | 41 +++
>> target/i386/accel/kvm/kvm.c | 3 +-
>> target/i386/accel/kvm/meson.build | 7 +-
>> target/i386/accel/tcg/meson.build | 3 +-
>> target/i386/accel/tcg/tcg-cpu-type.c | 176 +++++++++++
>> target/i386/accel/tcg/tcg-cpu-type.h | 25 ++
>> target/i386/cpu.c | 454 +++++----------------------
>> target/i386/cpu.h | 26 +-
>> target/i386/host-cpu.c | 201 ++++++++++++
>> target/i386/host-cpu.h | 21 ++
>> target/i386/meson.build | 8 +-
>> target/i386/tcg-cpu.c | 71 -----
>> target/i386/tcg-cpu.h | 15 -
>> 20 files changed, 834 insertions(+), 474 deletions(-)
>> create mode 100644 target/i386/accel/hvf/hvf-cpu-type.c
>> create mode 100644 target/i386/accel/kvm/kvm-cpu-type.c
>> create mode 100644 target/i386/accel/kvm/kvm-cpu-type.h
>> create mode 100644 target/i386/accel/tcg/tcg-cpu-type.c
>> create mode 100644 target/i386/accel/tcg/tcg-cpu-type.h
>> create mode 100644 target/i386/host-cpu.c
>> create mode 100644 target/i386/host-cpu.h
>> delete mode 100644 target/i386/tcg-cpu.c
>> delete mode 100644 target/i386/tcg-cpu.h
>>
>> diff --git a/bsd-user/main.c b/bsd-user/main.c
>> index ac40d79bfa..48dd4b8ba5 100644
>> --- a/bsd-user/main.c
>> +++ b/bsd-user/main.c
>> @@ -911,6 +911,10 @@ int main(int argc, char **argv)
>>
>> /* init tcg before creating CPUs and to get qemu_host_page_size */
>> tcg_exec_init(0);
>> + /*
>> + * TCG has been initialized, now it is time to register the cpu models.
>> + */
>> + module_call_init(MODULE_INIT_ACCEL_CPU);
>>
>> cpu_type = parse_cpu_option(cpu_model);
>> cpu = cpu_create(cpu_type);
>> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
>> index 13d1628f13..a59c3e1457 100644
>> --- a/hw/i386/pc_piix.c
>> +++ b/hw/i386/pc_piix.c
>> @@ -64,6 +64,7 @@
>> #include "hw/hyperv/vmbus-bridge.h"
>> #include "hw/mem/nvdimm.h"
>> #include "hw/i386/acpi-build.h"
>> +#include "accel/kvm/kvm-cpu-type.h"
>>
>> #define MAX_IDE_BUS 2
>>
>> diff --git a/linux-user/main.c b/linux-user/main.c
>> index 75c9785157..86ebd5db5e 100644
>> --- a/linux-user/main.c
>> +++ b/linux-user/main.c
>> @@ -699,14 +699,18 @@ int main(int argc, char **argv, char **envp)
>> }
>> }
>>
>> + /* init tcg before creating CPUs and to get qemu_host_page_size */
>> + tcg_exec_init(0);
>> + /*
>> + * TCG has been initialized, now it is time to register the cpu models.
>> + */
>> + module_call_init(MODULE_INIT_ACCEL_CPU);
>> +
>> if (cpu_model == NULL) {
>> cpu_model = cpu_get_model(get_elf_eflags(execfd));
>> }
>> cpu_type = parse_cpu_option(cpu_model);
>>
>> - /* init tcg before creating CPUs and to get qemu_host_page_size */
>> - tcg_exec_init(0);
>> -
>> cpu = cpu_create(cpu_type);
>> env = cpu->env_ptr;
>> cpu_reset(cpu);
>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>> index 6a6363902d..47cc938cef 100644
>> --- a/softmmu/vl.c
>> +++ b/softmmu/vl.c
>> @@ -4176,7 +4176,7 @@ void qemu_init(int argc, char **argv, char **envp)
>>
>> /*
>> * accelerator has been chosen and initialized, now it is time to
>> - * register the cpu accel interface.
>> + * register the cpu models, and the cpu accel interface.
>> */
>> module_call_init(MODULE_INIT_ACCEL_CPU);
>>
>> diff --git a/target/i386/accel/hvf/hvf-cpu-type.c
>> b/target/i386/accel/hvf/hvf-cpu-type.c
>> new file mode 100644
>> index 0000000000..dfe4ec4e9e
>> --- /dev/null
>> +++ b/target/i386/accel/hvf/hvf-cpu-type.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * x86 HVF CPU type initialization
>> + *
>> + * Copyright 2020 SUSE LLC
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "cpu.h"
>> +#include "host-cpu.h"
>> +#include "hvf-cpu-type.h"
>> +#include "qapi/error.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/boards.h"
>> +#include "sysemu/hvf.h"
>> +
>> +
>> +static void hvf_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> + dc->realize = host_cpu_realizefn;
>> +}
>> +
>> +static void hvf_cpu_max_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> + CPUX86State *env = &cpu->env;
>> +
>> + host_cpu_max_initfn(cpu);
>> +
>> + env->cpuid_min_level =
>> + hvf_get_supported_cpuid(0x0, 0, R_EAX);
>> + env->cpuid_min_xlevel =
>> + hvf_get_supported_cpuid(0x80000000, 0, R_EAX);
>> + env->cpuid_min_xlevel2 =
>> + hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
>> +}
>> +
>> +static void hvf_cpu_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> +
>> + host_cpu_initfn(obj);
>> +
>> + /* Special cases not set in the X86CPUDefinition structs: */
>> + /* TODO: in-kernel irqchip for hvf */
>> +
>> + if (cpu->max_features) {
>> + hvf_cpu_max_initfn(obj);
>> + }
>> +}
>> +
>> +static const TypeInfo hvf_cpu_type_info = {
>> + .name = X86_CPU_TYPE_NAME("hvf"),
>> + .parent = TYPE_X86_CPU,
>> +
>> + .instance_init = hvf_cpu_initfn,
>> + .class_init = hvf_cpu_common_class_init,
>> +};
>> +
>> +static void hvf_cpu_register_base_type(void)
>> +{
>> + type_register_static(&hvf_cpu_type_info);
>> +}
>> +
>> +type_init(hvf_cpu_register_base_type);
>> +
>> +void hvf_cpu_type_init(void)
>> +{
>> + if (hvf_enabled()) {
>> + x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("hvf"));
>> + }
>> +}
>> +
>> +accel_cpu_init(hvf_cpu_type_init);
>> diff --git a/target/i386/accel/hvf/meson.build
>> b/target/i386/accel/hvf/meson.build
>> index 409c9a3f14..785dee72fc 100644
>> --- a/target/i386/accel/hvf/meson.build
>> +++ b/target/i386/accel/hvf/meson.build
>> @@ -10,4 +10,5 @@ i386_softmmu_ss.add(when: [hvf, 'CONFIG_HVF'], if_true:
>> files(
>> 'x86_mmu.c',
>> 'x86_task.c',
>> 'x86hvf.c',
>> + 'hvf-cpu-type.c',
>> ))
>> diff --git a/target/i386/accel/kvm/kvm-cpu-type.c
>> b/target/i386/accel/kvm/kvm-cpu-type.c
>> new file mode 100644
>> index 0000000000..f696f21e2b
>> --- /dev/null
>> +++ b/target/i386/accel/kvm/kvm-cpu-type.c
>> @@ -0,0 +1,161 @@
>> +/*
>> + * x86 KVM CPU type initialization
>> + *
>> + * Copyright 2020 SUSE LLC
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "cpu.h"
>> +#include "host-cpu.h"
>> +#include "kvm-cpu-type.h"
>> +#include "qapi/error.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/boards.h"
>> +
>> +#include "kvm_i386.h"
>> +
>> +/* this information overloads the TYPE_X86_CPU type in x86-cpu.c */
>> +
>> +static void kvm_cpu_realizefn(DeviceState *dev, Error **errp)
>> +{
>> + X86CPU *cpu = X86_CPU(dev);
>> + CPUX86State *env = &cpu->env;
>> +
>> + /*
>> + * also for KVM the realize order is important, since
>> + * x86_cpu_realize() checks if nothing else has been set by the user,
>> + * or by the specialized x86 cpus (KVM, HVF) in
>> + * cpu->ucode_rev and cpu->phys_bits.
>> + *
>> + * So it's kvm_cpu -> host_cpu -> x86_cpu
>> + */
>> + if (cpu->max_features) {
>> + if (enable_cpu_pm && kvm_has_waitpkg()) {
>> + env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG;
>> + }
>> + if (cpu->ucode_rev == 0) {
>> + cpu->ucode_rev =
>> + kvm_arch_get_supported_msr_feature(kvm_state,
>> + MSR_IA32_UCODE_REV);
>> + }
>> + }
>> + host_cpu_realizefn(dev, errp);
>> +}
>> +
>> +static void kvm_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(oc);
>> + dc->realize = kvm_cpu_realizefn;
>> +}
>> +
>> +/*
>> + * KVM-specific features that are automatically added/removed
>> + * from all CPU models when KVM is enabled.
>> + */
>> +static PropValue kvm_default_props[] = {
>> + { "kvmclock", "on" },
>> + { "kvm-nopiodelay", "on" },
>> + { "kvm-asyncpf", "on" },
>> + { "kvm-steal-time", "on" },
>> + { "kvm-pv-eoi", "on" },
>> + { "kvmclock-stable-bit", "on" },
>> + { "x2apic", "on" },
>> + { "acpi", "off" },
>> + { "monitor", "off" },
>> + { "svm", "off" },
>> + { NULL, NULL },
>> +};
>> +
>> +void x86_cpu_change_kvm_default(const char *prop, const char *value)
>> +{
>> + PropValue *pv;
>> + for (pv = kvm_default_props; pv->prop; pv++) {
>> + if (!strcmp(pv->prop, prop)) {
>> + pv->value = value;
>> + break;
>> + }
>> + }
>> +
>> + /*
>> + * It is valid to call this function only for properties that
>> + * are already present in the kvm_default_props table.
>> + */
>> + assert(pv->prop);
>> +}
>> +
>> +static bool lmce_supported(void)
>> +{
>> + uint64_t mce_cap = 0;
>> +
>> + if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
>> + return false;
>> + }
>> + return !!(mce_cap & MCG_LMCE_P);
>> +}
>> +
>> +static void kvm_cpu_max_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> + CPUX86State *env = &cpu->env;
>> + KVMState *s = kvm_state;
>> +
>> + host_cpu_max_initfn(cpu);
>> +
>> + if (lmce_supported()) {
>> + object_property_set_bool(OBJECT(cpu), "lmce", true, &error_abort);
>> + }
>> +
>> + env->cpuid_min_level =
>> + kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
>> + env->cpuid_min_xlevel =
>> + kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
>> + env->cpuid_min_xlevel2 =
>> + kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
>> +}
>> +
>> +static void kvm_cpu_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> +
>> + host_cpu_initfn(obj);
>> +
>> + if (!kvm_irqchip_in_kernel()) {
>> + x86_cpu_change_kvm_default("x2apic", "off");
>> + }
>> +
>> + /* Special cases not set in the X86CPUDefinition structs: */
>> +
>> + x86_cpu_apply_props(cpu, kvm_default_props);
>> +
>> + if (cpu->max_features) {
>> + kvm_cpu_max_initfn(obj);
>> + }
>> +}
>> +
>> +static const TypeInfo kvm_cpu_type_info = {
>> + .name = X86_CPU_TYPE_NAME("kvm"),
>> + .parent = TYPE_X86_CPU,
>> +
>> + .instance_init = kvm_cpu_initfn,
>> + .class_init = kvm_cpu_common_class_init,
>> +};
>> +
>> +static void kvm_cpu_register_base_type(void)
>> +{
>> + type_register_static(&kvm_cpu_type_info);
>> +}
>> +
>> +type_init(kvm_cpu_register_base_type);
>> +
>> +void kvm_cpu_type_init(void)
>> +{
>> + if (kvm_enabled()) {
>> + x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("kvm"));
>> + host_cpu_type_init();
>> + }
>> +}
>> +
>> +accel_cpu_init(kvm_cpu_type_init);
>> diff --git a/target/i386/accel/kvm/kvm-cpu-type.h
>> b/target/i386/accel/kvm/kvm-cpu-type.h
>> new file mode 100644
>> index 0000000000..2448f49222
>> --- /dev/null
>> +++ b/target/i386/accel/kvm/kvm-cpu-type.h
>> @@ -0,0 +1,41 @@
>> +/*
>> + * i386 KVM CPU type initialization
>> + *
>> + * Copyright (c) 2003 Fabrice Bellard
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef KVM_CPU_TYPE_H
>> +#define KVM_CPU_TYPE_H
>> +
>> +#ifdef CONFIG_KVM
>> +void kvm_cpu_type_init(void);
>> +
>> +/*
>> + * Change the value of a KVM-specific default
>> + *
>> + * If value is NULL, no default will be set and the original
>> + * value from the CPU model table will be kept.
>> + *
>> + * It is valid to call this function only for properties that
>> + * are already present in the kvm_default_props table.
>> + */
>> +void x86_cpu_change_kvm_default(const char *prop, const char *value);
>> +
>> +#else /* CONFIG_KVM */
>> +#define x86_cpu_change_kvm_default(a, b)
>> +#endif /* CONFIG_KVM */
>> +
>> +#endif /* KVM_CPU_TYPE_H */
>> diff --git a/target/i386/accel/kvm/kvm.c b/target/i386/accel/kvm/kvm.c
>> index cf46259534..829730d3c2 100644
>> --- a/target/i386/accel/kvm/kvm.c
>> +++ b/target/i386/accel/kvm/kvm.c
>> @@ -22,6 +22,7 @@
>> #include "standard-headers/asm-x86/kvm_para.h"
>>
>> #include "cpu.h"
>> +#include "host-cpu.h"
>> #include "sysemu/sysemu.h"
>> #include "sysemu/hw_accel.h"
>> #include "sysemu/kvm_int.h"
>> @@ -285,7 +286,7 @@ static bool host_tsx_broken(void)
>> int family, model, stepping;\
>> char vendor[CPUID_VENDOR_SZ + 1];
>>
>> - host_vendor_fms(vendor, &family, &model, &stepping);
>> + host_cpu_vendor_fms(vendor, &family, &model, &stepping);
>>
>> /* Check if we are running on a Haswell host known to have broken TSX */
>> return !strcmp(vendor, CPUID_VENDOR_INTEL) &&
>> diff --git a/target/i386/accel/kvm/meson.build
>> b/target/i386/accel/kvm/meson.build
>> index 1d66559187..b6b32166b4 100644
>> --- a/target/i386/accel/kvm/meson.build
>> +++ b/target/i386/accel/kvm/meson.build
>> @@ -1,3 +1,8 @@
>> i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
>> -i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
>> +
>> +i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files(
>> + 'kvm.c',
>> + 'kvm-cpu-type.c',
>> +))
>> +
>> i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'),
>> if_false: files('hyperv-stub.c'))
>> diff --git a/target/i386/accel/tcg/meson.build
>> b/target/i386/accel/tcg/meson.build
>> index 02794226c2..211ecef5f9 100644
>> --- a/target/i386/accel/tcg/meson.build
>> +++ b/target/i386/accel/tcg/meson.build
>> @@ -10,4 +10,5 @@ i386_ss.add(when: 'CONFIG_TCG', if_true: files(
>> 'seg_helper.c',
>> 'smm_helper.c',
>> 'svm_helper.c',
>> - 'translate.c'), if_false: files('tcg-stub.c'))
>> + 'translate.c',
>> + 'tcg-cpu-type.c'), if_false: files('tcg-stub.c'))
>> diff --git a/target/i386/accel/tcg/tcg-cpu-type.c
>> b/target/i386/accel/tcg/tcg-cpu-type.c
>> new file mode 100644
>> index 0000000000..f0ee4ef5f7
>> --- /dev/null
>> +++ b/target/i386/accel/tcg/tcg-cpu-type.c
>> @@ -0,0 +1,176 @@
>> +/*
>> + * i386 TCG cpu class initialization
>> + *
>> + * Copyright (c) 2003 Fabrice Bellard
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/units.h"
>> +#include "cpu.h"
>> +#include "tcg-cpu-type.h"
>> +
>> +#include "helper-tcg.h"
>> +#include "sysemu/sysemu.h"
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +#include "exec/address-spaces.h"
>> +#endif
>> +
>> +/* Frob eflags into and out of the CPU temporary format. */
>> +
>> +static void x86_cpu_exec_enter(CPUState *cs)
>> +{
>> + X86CPU *cpu = X86_CPU(cs);
>> + CPUX86State *env = &cpu->env;
>> +
>> + CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
>> + env->df = 1 - (2 * ((env->eflags >> 10) & 1));
>> + CC_OP = CC_OP_EFLAGS;
>> + env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
>> +}
>> +
>> +static void x86_cpu_exec_exit(CPUState *cs)
>> +{
>> + X86CPU *cpu = X86_CPU(cs);
>> + CPUX86State *env = &cpu->env;
>> +
>> + env->eflags = cpu_compute_eflags(env);
>> +}
>> +
>> +static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>> +{
>> + X86CPU *cpu = X86_CPU(cs);
>> +
>> + cpu->env.eip = tb->pc - tb->cs_base;
>> +}
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +
>> +static void x86_cpu_machine_done(Notifier *n, void *unused)
>> +{
>> + X86CPU *cpu = container_of(n, X86CPU, machine_done);
>> + MemoryRegion *smram =
>> + (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
>> +
>> + if (smram) {
>> + cpu->smram = g_new(MemoryRegion, 1);
>> + memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
>> + smram, 0, 4 * GiB);
>> + memory_region_set_enabled(cpu->smram, true);
>> + memory_region_add_subregion_overlap(cpu->cpu_as_root, 0,
>> + cpu->smram, 1);
>> + }
>> +}
>> +
>> +static void tcg_cpu_realizefn(DeviceState *dev, Error **errp)
>> +{
>> + X86CPU *cpu = X86_CPU(dev);
>> + CPUState *cs = CPU(dev);
>> +
>> + /*
>> + * also for TCG the realize order is important,
>> + * as the memory regions initialized here are needed
>> + * in x86_cpu_realizefn()
>> + */
>> + cpu->cpu_as_mem = g_new(MemoryRegion, 1);
>> + cpu->cpu_as_root = g_new(MemoryRegion, 1);
>> +
>> + /* Outer container... */
>> + memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
>> + memory_region_set_enabled(cpu->cpu_as_root, true);
>> +
>> + /*
>> + * ... with two regions inside: normal system memory with low
>> + * priority, and...
>> + */
>> + memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
>> + get_system_memory(), 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);
>> +
>> + cs->num_ases = 2;
>> + cpu_address_space_init(cs, 0, "cpu-memory", cs->memory);
>> + cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root);
>> +
>> + /* ... SMRAM with higher priority, linked from /machine/smram. */
>> + cpu->machine_done.notify = x86_cpu_machine_done;
>> + qemu_add_machine_init_done_notifier(&cpu->machine_done);
>> +
>> + /* call the generic x86_cpu_realizefn() after regions initialized */
>> + x86_cpu_realizefn(dev, errp);
>> +}
>> +#endif /* !CONFIG_USER_ONLY */
>> +
>> +static void tcg_cpu_common_class_init(ObjectClass *oc, void *data)
>> +{
>> + CPUClass *cc = CPU_CLASS(oc);
>> +#ifndef CONFIG_USER_ONLY
>> + DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> + dc->realize = tcg_cpu_realizefn;
>> +#endif /* !CONFIG_USER_ONLY */
>> +
>> + cc->do_interrupt = x86_cpu_do_interrupt;
>> + cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
>> + cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
>> + cc->cpu_exec_enter = x86_cpu_exec_enter;
>> + cc->cpu_exec_exit = x86_cpu_exec_exit;
>> + cc->tcg_initialize = tcg_x86_init;
>> + cc->tlb_fill = x86_cpu_tlb_fill;
>> +#ifndef CONFIG_USER_ONLY
>> + cc->debug_excp_handler = breakpoint_handler;
>> +#endif /* !CONFIG_USER_ONLY */
>> +}
>> +
>> +/*
>> + * TCG-specific defaults that override all CPU models when using TCG
>> + */
>> +static PropValue tcg_default_props[] = {
>> + { "vme", "off" },
>> + { NULL, NULL },
>> +};
>> +
>> +static void tcg_cpu_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> +
>> + /* Special cases not set in the X86CPUDefinition structs: */
>> + x86_cpu_apply_props(cpu, tcg_default_props);
>> +}
>> +
>> +static const TypeInfo tcg_cpu_type_info = {
>> + .name = X86_CPU_TYPE_NAME("tcg"),
>> + .parent = TYPE_X86_CPU,
>> +
>> + .instance_init = tcg_cpu_initfn,
>> + .class_init = tcg_cpu_common_class_init,
>> +};
>> +
>> +static void tcg_cpu_register_base_type(void)
>> +{
>> + type_register_static(&tcg_cpu_type_info);
>> +}
>> +
>> +type_init(tcg_cpu_register_base_type);
>> +
>> +void tcg_cpu_type_init(void)
>> +{
>> + if (tcg_enabled()) {
>> + x86_cpu_register_cpu_models(X86_CPU_TYPE_NAME("tcg"));
>> + }
>> +}
>> +
>> +accel_cpu_init(tcg_cpu_type_init);
>> diff --git a/target/i386/accel/tcg/tcg-cpu-type.h
>> b/target/i386/accel/tcg/tcg-cpu-type.h
>> new file mode 100644
>> index 0000000000..d741a8f6be
>> --- /dev/null
>> +++ b/target/i386/accel/tcg/tcg-cpu-type.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + * i386 TCG CPU type initialization
>> + *
>> + * Copyright (c) 2003 Fabrice Bellard
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef TCG_CPU_TYPE_H
>> +#define TCG_CPU_TYPE_H
>> +
>> +void tcg_cpu_type_init(void);
>> +
>> +#endif /* TCG_CPU_TYPE_H */
>> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
>> index b185789d88..b547c9d39d 100644
>> --- a/target/i386/cpu.c
>> +++ b/target/i386/cpu.c
>> @@ -22,9 +22,7 @@
>> #include "qemu/cutils.h"
>> #include "qemu/bitops.h"
>> #include "qemu/qemu-print.h"
>> -
>> #include "cpu.h"
>> -#include "tcg-cpu.h"
>> #include "helper-tcg.h"
>> #include "exec/exec-all.h"
>> #include "sysemu/kvm.h"
>> @@ -34,27 +32,17 @@
>> #include "sysemu/xen.h"
>> #include "accel/kvm/kvm_i386.h"
>> #include "sev_i386.h"
>> -
>> -#include "qemu/error-report.h"
>> #include "qemu/module.h"
>> -#include "qemu/option.h"
>> -#include "qemu/config-file.h"
>> -#include "qapi/error.h"
>> #include "qapi/qapi-visit-machine.h"
>> #include "qapi/qapi-visit-run-state.h"
>> #include "qapi/qmp/qdict.h"
>> #include "qapi/qmp/qerror.h"
>> -#include "qapi/visitor.h"
>> #include "qom/qom-qobject.h"
>> -#include "sysemu/arch_init.h"
>> #include "qapi/qapi-commands-machine-target.h"
>> -
>> #include "standard-headers/asm-x86/kvm_para.h"
>> -
>> -#include "sysemu/sysemu.h"
>> -#include "sysemu/tcg.h"
>> #include "hw/qdev-properties.h"
>> #include "hw/i386/topology.h"
>> +
>> #ifndef CONFIG_USER_ONLY
>> #include "exec/address-spaces.h"
>> #include "hw/i386/apic_internal.h"
>> @@ -594,8 +582,8 @@ static CPUCacheInfo legacy_l3_cache = {
>> #define INTEL_PT_CYCLE_BITMAP 0x1fff /* Support 0,2^(0~11) */
>> #define INTEL_PT_PSB_BITMAP (0x003f << 16) /* Support
>> 2K,4K,8K,16K,32K,64K */
>>
>> -static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
>> - uint32_t vendor2, uint32_t vendor3)
>> +void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
>> + uint32_t vendor2, uint32_t vendor3)
>> {
>> int i;
>> for (i = 0; i < 4; i++) {
>> @@ -1563,25 +1551,6 @@ void host_cpuid(uint32_t function, uint32_t count,
>> *edx = vec[3];
>> }
>>
>> -void host_vendor_fms(char *vendor, int *family, int *model, int *stepping)
>> -{
>> - uint32_t eax, ebx, ecx, edx;
>> -
>> - host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
>> - x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
>> -
>> - host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
>> - if (family) {
>> - *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
>> - }
>> - if (model) {
>> - *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
>> - }
>> - if (stepping) {
>> - *stepping = eax & 0x0F;
>> - }
>> -}
>> -
>> /* CPU class name definitions: */
>>
>> /* Return type name for a given CPU model name
>> @@ -1606,10 +1575,6 @@ static char *x86_cpu_class_get_model_name(X86CPUClass
>> *cc)
>> strlen(class_name) - strlen(X86_CPU_TYPE_SUFFIX));
>> }
>>
>> -typedef struct PropValue {
>> - const char *prop, *value;
>> -} PropValue;
>> -
>> typedef struct X86CPUVersionDefinition {
>> X86CPUVersion version;
>> const char *alias;
>> @@ -4106,31 +4071,6 @@ static X86CPUDefinition builtin_x86_defs[] = {
>> },
>> };
>>
>> -/* KVM-specific features that are automatically added/removed
>> - * from all CPU models when KVM is enabled.
>> - */
>> -static PropValue kvm_default_props[] = {
>> - { "kvmclock", "on" },
>> - { "kvm-nopiodelay", "on" },
>> - { "kvm-asyncpf", "on" },
>> - { "kvm-steal-time", "on" },
>> - { "kvm-pv-eoi", "on" },
>> - { "kvmclock-stable-bit", "on" },
>> - { "x2apic", "on" },
>> - { "acpi", "off" },
>> - { "monitor", "off" },
>> - { "svm", "off" },
>> - { NULL, NULL },
>> -};
>> -
>> -/* TCG-specific defaults that override all CPU models when using TCG
>> - */
>> -static PropValue tcg_default_props[] = {
>> - { "vme", "off" },
>> - { NULL, NULL },
>> -};
>> -
>> -
>> /*
>> * We resolve CPU model aliases using -v1 when using "-machine
>> * none", but this is just for compatibility while libvirt isn't
>> @@ -4172,61 +4112,6 @@ static X86CPUVersion
>> x86_cpu_model_resolve_version(const X86CPUModel *model)
>> return v;
>> }
>>
>> -void x86_cpu_change_kvm_default(const char *prop, const char *value)
>> -{
>> - PropValue *pv;
>> - for (pv = kvm_default_props; pv->prop; pv++) {
>> - if (!strcmp(pv->prop, prop)) {
>> - pv->value = value;
>> - break;
>> - }
>> - }
>> -
>> - /* It is valid to call this function only for properties that
>> - * are already present in the kvm_default_props table.
>> - */
>> - assert(pv->prop);
>> -}
>> -
>> -static bool lmce_supported(void)
>> -{
>> - uint64_t mce_cap = 0;
>> -
>> -#ifdef CONFIG_KVM
>> - if (kvm_ioctl(kvm_state, KVM_X86_GET_MCE_CAP_SUPPORTED, &mce_cap) < 0) {
>> - return false;
>> - }
>> -#endif
>> -
>> - return !!(mce_cap & MCG_LMCE_P);
>> -}
>> -
>> -#define CPUID_MODEL_ID_SZ 48
>> -
>> -/**
>> - * cpu_x86_fill_model_id:
>> - * Get CPUID model ID string from host CPU.
>> - *
>> - * @str should have at least CPUID_MODEL_ID_SZ bytes
>> - *
>> - * The function does NOT add a null terminator to the string
>> - * automatically.
>> - */
>> -static int cpu_x86_fill_model_id(char *str)
>> -{
>> - uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
>> - int i;
>> -
>> - for (i = 0; i < 3; i++) {
>> - host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
>> - memcpy(str + i * 16 + 0, &eax, 4);
>> - memcpy(str + i * 16 + 4, &ebx, 4);
>> - memcpy(str + i * 16 + 8, &ecx, 4);
>> - memcpy(str + i * 16 + 12, &edx, 4);
>> - }
>> - return 0;
>> -}
>> -
>> static Property max_x86_cpu_properties[] = {
>> DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
>> DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough,
>> false),
>> @@ -4246,98 +4131,38 @@ static void max_x86_cpu_class_init(ObjectClass *oc,
>> void *data)
>> device_class_set_props(dc, max_x86_cpu_properties);
>> }
>>
>> -static void max_x86_cpu_initfn(Object *obj)
>> +void max_x86_cpu_initfn(Object *obj)
>> {
>> X86CPU *cpu = X86_CPU(obj);
>> - CPUX86State *env = &cpu->env;
>> - KVMState *s = kvm_state;
>>
>> /* We can't fill the features array here because we don't know yet if
>> * "migratable" is true or false.
>> */
>> cpu->max_features = true;
>> -
>> - if (accel_uses_host_cpuid()) {
>> - char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
>> - char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
>> - int family, model, stepping;
>> -
>> - host_vendor_fms(vendor, &family, &model, &stepping);
>> - cpu_x86_fill_model_id(model_id);
>> -
>> - object_property_set_str(OBJECT(cpu), "vendor", vendor,
>> &error_abort);
>> - object_property_set_int(OBJECT(cpu), "family", family,
>> &error_abort);
>> - object_property_set_int(OBJECT(cpu), "model", model, &error_abort);
>> - object_property_set_int(OBJECT(cpu), "stepping", stepping,
>> - &error_abort);
>> - object_property_set_str(OBJECT(cpu), "model-id", model_id,
>> - &error_abort);
>> -
>> - if (kvm_enabled()) {
>> - env->cpuid_min_level =
>> - kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
>> - env->cpuid_min_xlevel =
>> - kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
>> - env->cpuid_min_xlevel2 =
>> - kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
>> - } else {
>> - env->cpuid_min_level =
>> - hvf_get_supported_cpuid(0x0, 0, R_EAX);
>> - env->cpuid_min_xlevel =
>> - hvf_get_supported_cpuid(0x80000000, 0, R_EAX);
>> - env->cpuid_min_xlevel2 =
>> - hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
>> - }
>> -
>> - if (lmce_supported()) {
>> - object_property_set_bool(OBJECT(cpu), "lmce", true,
>> &error_abort);
>> - }
>> - } else {
>> - object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
>> - &error_abort);
>> - object_property_set_int(OBJECT(cpu), "family", 6, &error_abort);
>> - object_property_set_int(OBJECT(cpu), "model", 6, &error_abort);
>> - object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort);
>> - object_property_set_str(OBJECT(cpu), "model-id",
>> - "QEMU TCG CPU version " QEMU_HW_VERSION,
>> - &error_abort);
>> - }
>> -
>> object_property_set_bool(OBJECT(cpu), "pmu", true, &error_abort);
>> +
>> + /*
>> + * these defaults are used for TCG and all other accelerators
>> + * besides KVM and HVF, which overwrite these values
>> + */
>> + object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
>> + &error_abort);
>> + object_property_set_int(OBJECT(cpu), "family", 6, &error_abort);
>> + object_property_set_int(OBJECT(cpu), "model", 6, &error_abort);
>> + object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort);
>> + object_property_set_str(OBJECT(cpu), "model-id",
>> + "QEMU TCG CPU version " QEMU_HW_VERSION,
>> + &error_abort);
>> }
>>
>> -static const TypeInfo max_x86_cpu_type_info = {
>> +static TypeInfo max_x86_cpu_type_info = {
>> .name = X86_CPU_TYPE_NAME("max"),
>> - .parent = TYPE_X86_CPU,
>> - .instance_init = max_x86_cpu_initfn,
>> + .parent = NULL, /* set by x86_cpu_register_cpu_models */
>> +
>> .class_init = max_x86_cpu_class_init,
>> + .instance_init = max_x86_cpu_initfn,
>> };
>>
>> -#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
>> -static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
>> -{
>> - X86CPUClass *xcc = X86_CPU_CLASS(oc);
>> -
>> - xcc->host_cpuid_required = true;
>> - xcc->ordering = 8;
>> -
>> -#if defined(CONFIG_KVM)
>> - xcc->model_description =
>> - "KVM processor with all supported host features ";
>> -#elif defined(CONFIG_HVF)
>> - xcc->model_description =
>> - "HVF processor with all supported host features ";
>> -#endif
>> -}
>> -
>> -static const TypeInfo host_x86_cpu_type_info = {
>> - .name = X86_CPU_TYPE_NAME("host"),
>> - .parent = X86_CPU_TYPE_NAME("max"),
>> - .class_init = host_x86_cpu_class_init,
>> -};
>> -
>> -#endif
>> -
>> static char *feature_word_description(FeatureWordInfo *f, uint32_t bit)
>> {
>> assert(f->type == CPUID_FEATURE_WORD || f->type == MSR_FEATURE_WORD);
>> @@ -5063,7 +4888,7 @@ static uint64_t
>> x86_cpu_get_supported_feature_word(FeatureWord w,
>> return r;
>> }
>>
>> -static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
>> +void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
>> {
>> PropValue *pv;
>> for (pv = props; pv->prop; pv++) {
>> @@ -5110,8 +4935,6 @@ static void x86_cpu_load_model(X86CPU *cpu,
>> X86CPUModel *model)
>> {
>> X86CPUDefinition *def = model->cpudef;
>> CPUX86State *env = &cpu->env;
>> - const char *vendor;
>> - char host_vendor[CPUID_VENDOR_SZ + 1];
>> FeatureWord w;
>>
>> /*NOTE: any property set by this function should be returned by
>> @@ -5138,18 +4961,6 @@ static void x86_cpu_load_model(X86CPU *cpu,
>> X86CPUModel *model)
>> /* legacy-cache defaults to 'off' if CPU model provides cache info */
>> cpu->legacy_cache = !def->cache_info;
>>
>> - /* Special cases not set in the X86CPUDefinition structs: */
>> - /* TODO: in-kernel irqchip for hvf */
>> - if (kvm_enabled()) {
>> - if (!kvm_irqchip_in_kernel()) {
>> - x86_cpu_change_kvm_default("x2apic", "off");
>> - }
>> -
>> - x86_cpu_apply_props(cpu, kvm_default_props);
>> - } else if (tcg_enabled()) {
>> - x86_cpu_apply_props(cpu, tcg_default_props);
>> - }
>> -
>> env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
>>
>> /* sysenter isn't supported in compatibility mode on AMD,
>> @@ -5159,15 +4970,12 @@ static void x86_cpu_load_model(X86CPU *cpu,
>> X86CPUModel *model)
>> * KVM's sysenter/syscall emulation in compatibility mode and
>> * when doing cross vendor migration
>> */
>> - vendor = def->vendor;
>> - if (accel_uses_host_cpuid()) {
>> - uint32_t ebx = 0, ecx = 0, edx = 0;
>> - host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
>> - x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx);
>> - vendor = host_vendor;
>> - }
>>
>> - object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
>> + /*
>> + * vendor property is set here but then overloaded with the
>> + * host cpu vendor for KVM and HVF.
>> + */
>> + object_property_set_str(OBJECT(cpu), "vendor", def->vendor,
>> &error_abort);
>>
>> x86_cpu_apply_version_props(cpu, model);
>>
>> @@ -5400,12 +5208,13 @@ static void x86_cpu_cpudef_class_init(ObjectClass
>> *oc, void *data)
>> cc->deprecation_note = model->cpudef->deprecation_note;
>> }
>>
>> -static void x86_register_cpu_model_type(const char *name, X86CPUModel
>> *model)
>> +static void x86_register_cpu_model_type(const char *name, X86CPUModel
>> *model,
>> + const char *parent_type)
>> {
>> g_autofree char *typename = x86_cpu_type_name(name);
>> TypeInfo ti = {
>> .name = typename,
>> - .parent = TYPE_X86_CPU,
>> + .parent = parent_type,
>> .class_init = x86_cpu_cpudef_class_init,
>> .class_data = model,
>> };
>> @@ -5413,7 +5222,8 @@ static void x86_register_cpu_model_type(const char
>> *name, X86CPUModel *model)
>> type_register(&ti);
>> }
>>
>> -static void x86_register_cpudef_types(X86CPUDefinition *def)
>> +static void x86_register_cpudef(X86CPUDefinition *def,
>> + const char *parent_type)
>> {
>> X86CPUModel *m;
>> const X86CPUVersionDefinition *vdef;
>> @@ -5430,7 +5240,7 @@ static void x86_register_cpudef_types(X86CPUDefinition
>> *def)
>> m->cpudef = def;
>> m->version = CPU_VERSION_AUTO;
>> m->is_alias = true;
>> - x86_register_cpu_model_type(def->name, m);
>> + x86_register_cpu_model_type(def->name, m, parent_type);
>>
>> /* Versioned models: */
>>
>> @@ -5441,14 +5251,14 @@ static void
>> x86_register_cpudef_types(X86CPUDefinition *def)
>> m->cpudef = def;
>> m->version = vdef->version;
>> m->note = vdef->note;
>> - x86_register_cpu_model_type(name, m);
>> + x86_register_cpu_model_type(name, m, parent_type);
>>
>> if (vdef->alias) {
>> X86CPUModel *am = g_new0(X86CPUModel, 1);
>> am->cpudef = def;
>> am->version = vdef->version;
>> am->is_alias = true;
>> - x86_register_cpu_model_type(vdef->alias, am);
>> + x86_register_cpu_model_type(vdef->alias, am, parent_type);
>> }
>> }
>>
>> @@ -6192,53 +6002,12 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error
>> **errp)
>> apic_mmio_map_once = true;
>> }
>> }
>> -
>> -static void x86_cpu_machine_done(Notifier *n, void *unused)
>> -{
>> - X86CPU *cpu = container_of(n, X86CPU, machine_done);
>> - MemoryRegion *smram =
>> - (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
>> -
>> - if (smram) {
>> - cpu->smram = g_new(MemoryRegion, 1);
>> - memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
>> - smram, 0, 4 * GiB);
>> - memory_region_set_enabled(cpu->smram, true);
>> - memory_region_add_subregion_overlap(cpu->cpu_as_root, 0,
>> cpu->smram, 1);
>> - }
>> -}
>> #else
>> static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
>> {
>> }
>> #endif
>>
>> -/* Note: Only safe for use on x86(-64) hosts */
>> -static uint32_t x86_host_phys_bits(void)
>> -{
>> - uint32_t eax;
>> - uint32_t host_phys_bits;
>> -
>> - host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL);
>> - if (eax >= 0x80000008) {
>> - host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL);
>> - /* Note: According to AMD doc 25481 rev 2.34 they have a field
>> - * at 23:16 that can specify a maximum physical address bits for
>> - * the guest that can override this value; but I've not seen
>> - * anything with that set.
>> - */
>> - host_phys_bits = eax & 0xff;
>> - } else {
>> - /* It's an odd 64 bit machine that doesn't have the leaf for
>> - * physical address bits; fall back to 36 that's most older
>> - * Intel.
>> - */
>> - host_phys_bits = 36;
>> - }
>> -
>> - return host_phys_bits;
>> -}
>> -
>> static void x86_cpu_adjust_level(X86CPU *cpu, uint32_t *min, uint32_t value)
>> {
>> if (*min < value) {
>> @@ -6512,7 +6281,7 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool
>> verbose)
>> }
>> }
>>
>> -static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>> +void x86_cpu_realizefn(DeviceState *dev, Error **errp)
>> {
>> CPUState *cs = CPU(dev);
>> X86CPU *cpu = X86_CPU(dev);
>> @@ -6521,27 +6290,15 @@ static void x86_cpu_realizefn(DeviceState *dev,
>> Error **errp)
>> Error *local_err = NULL;
>> static bool ht_warned;
>>
>> - if (xcc->host_cpuid_required) {
>> - if (!accel_uses_host_cpuid()) {
>> - g_autofree char *name = x86_cpu_class_get_model_name(xcc);
>> - error_setg(&local_err, "CPU model '%s' requires KVM", name);
>> - goto out;
>> - }
>> - }
>> + /*
>> + * For accelerators that specialize the x86 cpu,
>> + * this common code must be called after the accelerator-specific
>> realizefn.
>> + */
>>
>> - if (cpu->max_features && accel_uses_host_cpuid()) {
>> - if (enable_cpu_pm) {
>> - host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
>> - &cpu->mwait.ecx, &cpu->mwait.edx);
>> - env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
>> - if (kvm_enabled() && kvm_has_waitpkg()) {
>> - env->features[FEAT_7_0_ECX] |= CPUID_7_0_ECX_WAITPKG;
>> - }
>> - }
>> - if (kvm_enabled() && cpu->ucode_rev == 0) {
>> - cpu->ucode_rev = kvm_arch_get_supported_msr_feature(kvm_state,
>> -
>> MSR_IA32_UCODE_REV);
>> - }
>> + if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
>> + g_autofree char *name = x86_cpu_class_get_model_name(xcc);
>> + error_setg(&local_err, "CPU model '%s' requires KVM or HVF", name);
>> + goto out;
>> }
>>
>> if (cpu->ucode_rev == 0) {
>> @@ -6593,39 +6350,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error
>> **errp)
>> * consumer AMD devices but nothing else.
>> */
>> if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
>> - if (accel_uses_host_cpuid()) {
>> - uint32_t host_phys_bits = x86_host_phys_bits();
>> - static bool warned;
>> -
>> - /* Print a warning if the user set it to a value that's not the
>> - * host value.
>> - */
>> - if (cpu->phys_bits != host_phys_bits && cpu->phys_bits != 0 &&
>> - !warned) {
>> - warn_report("Host physical bits (%u)"
>> - " does not match phys-bits property (%u)",
>> - host_phys_bits, cpu->phys_bits);
>> - warned = true;
>> - }
>> -
>> - if (cpu->host_phys_bits) {
>> - /* The user asked for us to use the host physical bits */
>> - cpu->phys_bits = host_phys_bits;
>> - if (cpu->host_phys_bits_limit &&
>> - cpu->phys_bits > cpu->host_phys_bits_limit) {
>> - cpu->phys_bits = cpu->host_phys_bits_limit;
>> - }
>> - }
>> -
>> - if (cpu->phys_bits &&
>> - (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS ||
>> - cpu->phys_bits < 32)) {
>> - error_setg(errp, "phys-bits should be between 32 and %u "
>> - " (but is %u)",
>> - TARGET_PHYS_ADDR_SPACE_BITS,
>> cpu->phys_bits);
>> - return;
>> - }
>> - } else {
>> + if (!accel_uses_host_cpuid()) {
>> if (cpu->phys_bits && cpu->phys_bits != TCG_PHYS_ADDR_BITS) {
>> error_setg(errp, "TCG only supports phys-bits=%u",
>> TCG_PHYS_ADDR_BITS);
>> @@ -6633,8 +6358,8 @@ static void x86_cpu_realizefn(DeviceState *dev, Error
>> **errp)
>> }
>> }
>> /* 0 means it was not explicitly set by the user (or by machine
>> - * compat_props or by the host code above). In this case, the
>> default
>> - * is the value used by TCG (40).
>> + * compat_props or by the host code in host-cpu.c).
>> + * In this case, the default is the value used by TCG (40).
>> */
>> if (cpu->phys_bits == 0) {
>> cpu->phys_bits = TCG_PHYS_ADDR_BITS;
>> @@ -6704,32 +6429,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error
>> **errp)
>>
>> mce_init(cpu);
>>
>> -#ifndef CONFIG_USER_ONLY
>> - if (tcg_enabled()) {
>> - cpu->cpu_as_mem = g_new(MemoryRegion, 1);
>> - cpu->cpu_as_root = g_new(MemoryRegion, 1);
>> -
>> - /* Outer container... */
>> - memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
>> - memory_region_set_enabled(cpu->cpu_as_root, true);
>> -
>> - /* ... with two regions inside: normal system memory with low
>> - * priority, and...
>> - */
>> - memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
>> - get_system_memory(), 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);
>> -
>> - cs->num_ases = 2;
>> - cpu_address_space_init(cs, 0, "cpu-memory", cs->memory);
>> - cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root);
>> -
>> - /* ... SMRAM with higher priority, linked from /machine/smram. */
>> - cpu->machine_done.notify = x86_cpu_machine_done;
>> - qemu_add_machine_init_done_notifier(&cpu->machine_done);
>> - }
>> -#endif
>> + /* XXX this is the place for tcg region initialization XXX */
>>
>> qemu_init_vcpu(cs);
>>
>> @@ -6932,7 +6632,7 @@ static void x86_cpu_get_crash_info_qom(Object *obj,
>> Visitor *v,
>> }
>> #endif /* !CONFIG_USER_ONLY */
>>
>> -static void x86_cpu_initfn(Object *obj)
>> +void x86_cpu_initfn(Object *obj)
>> {
>> X86CPU *cpu = X86_CPU(obj);
>> X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
>> @@ -7230,7 +6930,7 @@ static Property x86_cpu_properties[] = {
>> DEFINE_PROP_END_OF_LIST()
>> };
>>
>> -static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>> +void x86_cpu_common_class_init(ObjectClass *oc, void *data)
>> {
>> X86CPUClass *xcc = X86_CPU_CLASS(oc);
>> CPUClass *cc = CPU_CLASS(oc);
>> @@ -7249,10 +6949,6 @@ static void x86_cpu_common_class_init(ObjectClass
>> *oc, void *data)
>> cc->parse_features = x86_cpu_parse_featurestr;
>> cc->has_work = x86_cpu_has_work;
>>
>> -#ifdef CONFIG_TCG
>> - tcg_cpu_common_class_init(cc);
>> -#endif /* CONFIG_TCG */
>> -
>> cc->dump_state = x86_cpu_dump_state;
>> cc->set_pc = x86_cpu_set_pc;
>> cc->gdb_read_register = x86_cpu_gdb_read_register;
>> @@ -7341,25 +7037,49 @@ static void x86_cpu_base_class_init(ObjectClass *oc,
>> void *data)
>> xcc->ordering = 8;
>> }
>>
>> -static const TypeInfo x86_base_cpu_type_info = {
>> - .name = X86_CPU_TYPE_NAME("base"),
>> - .parent = TYPE_X86_CPU,
>> - .class_init = x86_cpu_base_class_init,
>> +static TypeInfo x86_base_cpu_type_info = {
>> + .name = X86_CPU_TYPE_NAME("base"),
>> + .parent = NULL, /* set by x86_cpu_register_cpu_models */
>> +
>> + .class_init = x86_cpu_base_class_init,
>> };
>>
>> -static void x86_cpu_register_types(void)
>> +/*
>> + * x86 cpu types are only registered once accelerator is determined,
>> + * passing the parent cpu type as an argument here.
>> + */
>> +void x86_cpu_register_cpu_models(const char *parent_type)
>> {
>> int i;
>>
>> - type_register_static(&x86_cpu_type_info);
>> for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
>> - x86_register_cpudef_types(&builtin_x86_defs[i]);
>> + x86_register_cpudef(&builtin_x86_defs[i], parent_type);
>> + }
>> + max_x86_cpu_type_info.parent = parent_type;
>> + type_register(&max_x86_cpu_type_info);
>> +
>> + x86_base_cpu_type_info.parent = parent_type;
>> + type_register(&x86_base_cpu_type_info);
>> +}
>> +
>> +static void x86_cpu_register_base_type(void)
>> +{
>> + type_register_static(&x86_cpu_type_info);
>> +}
>> +
>> +type_init(x86_cpu_register_base_type);
>> +
>> +/*
>> + * generic initializer if no other specialization.
>> + */
>> +static void x86_cpu_type_init(void)
>> +{
>> + /*
>> + * I would like something better than this check.
>> + */
>> + if (!tcg_enabled() && !kvm_enabled() && !hvf_enabled()) {
>> + x86_cpu_register_cpu_models(TYPE_X86_CPU);
>> }
>> - type_register_static(&max_x86_cpu_type_info);
>> - type_register_static(&x86_base_cpu_type_info);
>> -#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
>> - type_register_static(&host_x86_cpu_type_info);
>> -#endif
>> }
>>
>> -type_init(x86_cpu_register_types)
>> +accel_cpu_init(x86_cpu_type_init);
>> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
>> index f1bce16b53..9232672eb2 100644
>> --- a/target/i386/cpu.h
>> +++ b/target/i386/cpu.h
>> @@ -1905,13 +1905,26 @@ int cpu_x86_signal_handler(int host_signum, void
>> *pinfo,
>> void *puc);
>>
>> /* cpu.c */
>> +void x86_cpu_register_cpu_models(const char *parent_type);
>> +
>> +void x86_cpu_initfn(Object *obj);
>> +void max_x86_cpu_initfn(Object *obj);
>> +void x86_cpu_realizefn(DeviceState *dev, Error **errp);
>> +void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
>> + uint32_t vendor2, uint32_t vendor3);
>> +void x86_cpu_common_class_init(ObjectClass *oc, void *data);
>> +typedef struct PropValue {
>> + const char *prop, *value;
>> +} PropValue;
>> +void x86_cpu_apply_props(X86CPU *cpu, PropValue *props);
>> +
>> +/* cpu.c other functions (cpuid) */
>> void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>> uint32_t *eax, uint32_t *ebx,
>> uint32_t *ecx, uint32_t *edx);
>> void cpu_clear_apic_feature(CPUX86State *env);
>> void host_cpuid(uint32_t function, uint32_t count,
>> uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
>> -void host_vendor_fms(char *vendor, int *family, int *model, int *stepping);
>>
>> /* helper.c */
>> void x86_cpu_set_a20(X86CPU *cpu, int a20_state);
>> @@ -2111,17 +2124,6 @@ void cpu_report_tpr_access(CPUX86State *env,
>> TPRAccess access);
>> void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
>> TPRAccess access);
>>
>> -
>> -/* Change the value of a KVM-specific default
>> - *
>> - * If value is NULL, no default will be set and the original
>> - * value from the CPU model table will be kept.
>> - *
>> - * It is valid to call this function only for properties that
>> - * are already present in the kvm_default_props table.
>> - */
>> -void x86_cpu_change_kvm_default(const char *prop, const char *value);
>> -
>> /* Special values for X86CPUVersion: */
>>
>> /* Resolve to latest CPU version */
>> diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c
>> new file mode 100644
>> index 0000000000..65a0119f4b
>> --- /dev/null
>> +++ b/target/i386/host-cpu.c
>> @@ -0,0 +1,201 @@
>> +/*
>> + * x86 host CPU functions, and "host" cpu type initialization
>> + *
>> + * Copyright 2020 SUSE LLC
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "cpu.h"
>> +#include "host-cpu.h"
>> +#include "qapi/error.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/boards.h"
>> +
>> +/* Note: Only safe for use on x86(-64) hosts */
>> +static uint32_t host_cpu_phys_bits(void)
>> +{
>> + uint32_t eax;
>> + uint32_t host_phys_bits;
>> +
>> + host_cpuid(0x80000000, 0, &eax, NULL, NULL, NULL);
>> + if (eax >= 0x80000008) {
>> + host_cpuid(0x80000008, 0, &eax, NULL, NULL, NULL);
>> + /*
>> + * Note: According to AMD doc 25481 rev 2.34 they have a field
>> + * at 23:16 that can specify a maximum physical address bits for
>> + * the guest that can override this value; but I've not seen
>> + * anything with that set.
>> + */
>> + host_phys_bits = eax & 0xff;
>> + } else {
>> + /*
>> + * It's an odd 64 bit machine that doesn't have the leaf for
>> + * physical address bits; fall back to 36 that's most older
>> + * Intel.
>> + */
>> + host_phys_bits = 36;
>> + }
>> +
>> + return host_phys_bits;
>> +}
>> +
>> +static void host_cpu_enable_cpu_pm(X86CPU *cpu)
>> +{
>> + CPUX86State *env = &cpu->env;
>> +
>> + host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
>> + &cpu->mwait.ecx, &cpu->mwait.edx);
>> + env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR;
>> +}
>> +
>> +static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu, Error **errp)
>> +{
>> + uint32_t host_phys_bits = host_cpu_phys_bits();
>> + uint32_t phys_bits = cpu->phys_bits;
>> + static bool warned;
>> +
>> + /*
>> + * Print a warning if the user set it to a value that's not the
>> + * host value.
>> + */
>> + if (phys_bits != host_phys_bits && phys_bits != 0 &&
>> + !warned) {
>> + warn_report("Host physical bits (%u)"
>> + " does not match phys-bits property (%u)",
>> + host_phys_bits, phys_bits);
>> + warned = true;
>> + }
>> +
>> + if (cpu->host_phys_bits) {
>> + /* The user asked for us to use the host physical bits */
>> + phys_bits = host_phys_bits;
>> + if (cpu->host_phys_bits_limit &&
>> + phys_bits > cpu->host_phys_bits_limit) {
>> + phys_bits = cpu->host_phys_bits_limit;
>> + }
>> + }
>> +
>> + if (phys_bits &&
>> + (phys_bits > TARGET_PHYS_ADDR_SPACE_BITS ||
>> + phys_bits < 32)) {
>> + error_setg(errp, "phys-bits should be between 32 and %u "
>> + " (but is %u)",
>> + TARGET_PHYS_ADDR_SPACE_BITS, phys_bits);
>> + }
>> +
>> + return phys_bits;
>> +}
>> +
>> +void host_cpu_realizefn(DeviceState *dev, Error **errp)
>> +{
>> + X86CPU *cpu = X86_CPU(dev);
>> + CPUX86State *env = &cpu->env;
>> +
>> + if (cpu->max_features && enable_cpu_pm) {
>> + host_cpu_enable_cpu_pm(cpu);
>> + }
>> + if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
>> + cpu->phys_bits = host_cpu_adjust_phys_bits(cpu, errp);
>> + }
>> + x86_cpu_realizefn(dev, errp);
>> +}
>> +
>> +#define CPUID_MODEL_ID_SZ 48
>> +/**
>> + * cpu_x86_fill_model_id:
>> + * Get CPUID model ID string from host CPU.
>> + *
>> + * @str should have at least CPUID_MODEL_ID_SZ bytes
>> + *
>> + * The function does NOT add a null terminator to the string
>> + * automatically.
>> + */
>> +static int host_cpu_fill_model_id(char *str)
>> +{
>> + uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
>> + int i;
>> +
>> + for (i = 0; i < 3; i++) {
>> + host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
>> + memcpy(str + i * 16 + 0, &eax, 4);
>> + memcpy(str + i * 16 + 4, &ebx, 4);
>> + memcpy(str + i * 16 + 8, &ecx, 4);
>> + memcpy(str + i * 16 + 12, &edx, 4);
>> + }
>> + return 0;
>> +}
>> +
>> +void host_cpu_vendor_fms(char *vendor, int *family, int *model, int
>> *stepping)
>> +{
>> + uint32_t eax, ebx, ecx, edx;
>> +
>> + host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
>> + x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
>> +
>> + host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
>> + if (family) {
>> + *family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
>> + }
>> + if (model) {
>> + *model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
>> + }
>> + if (stepping) {
>> + *stepping = eax & 0x0F;
>> + }
>> +}
>> +
>> +void host_cpu_initfn(Object *obj)
>> +{
>> + X86CPU *cpu = X86_CPU(obj);
>> + uint32_t ebx = 0, ecx = 0, edx = 0;
>> + char vendor[CPUID_VENDOR_SZ + 1];
>> +
>> + host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
>> + x86_cpu_vendor_words2str(vendor, ebx, edx, ecx);
>> +
>> + object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
>> +}
>> +
>> +void host_cpu_max_initfn(X86CPU *cpu)
>> +{
>> + char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
>> + char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
>> + int family, model, stepping;
>> +
>> + host_cpu_vendor_fms(vendor, &family, &model, &stepping);
>> + host_cpu_fill_model_id(model_id);
>> +
>> + object_property_set_str(OBJECT(cpu), "vendor", vendor, &error_abort);
>> + object_property_set_int(OBJECT(cpu), "family", family, &error_abort);
>> + object_property_set_int(OBJECT(cpu), "model", model, &error_abort);
>> + object_property_set_int(OBJECT(cpu), "stepping", stepping,
>> + &error_abort);
>> + object_property_set_str(OBJECT(cpu), "model-id", model_id,
>> + &error_abort);
>> +}
>> +
>> +static void host_cpu_class_init(ObjectClass *oc, void *data)
>> +{
>> + X86CPUClass *xcc = X86_CPU_CLASS(oc);
>> +
>> + xcc->host_cpuid_required = true;
>> + xcc->ordering = 8;
>> + xcc->model_description =
>> + g_strdup_printf("%s processor with all supported host features ",
>> + ACCEL_GET_CLASS(current_accel())->name);
>> +}
>> +
>> +static const TypeInfo host_cpu_type_info = {
>> + .name = X86_CPU_TYPE_NAME("host"),
>> + .parent = X86_CPU_TYPE_NAME("max"),
>> +
>> + .class_init = host_cpu_class_init,
>> +};
>> +
>> +void host_cpu_type_init(void)
>> +{
>> + type_register(&host_cpu_type_info);
>> +}
>> diff --git a/target/i386/host-cpu.h b/target/i386/host-cpu.h
>> new file mode 100644
>> index 0000000000..e9d4726833
>> --- /dev/null
>> +++ b/target/i386/host-cpu.h
>> @@ -0,0 +1,21 @@
>> +/*
>> + * x86 host CPU type initialization
>> + *
>> + * Copyright 2020 SUSE LLC
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#ifndef HOST_CPU_TYPE_H
>> +#define HOST_CPU_TYPE_H
>> +
>> +void host_cpu_type_init(void);
>> +
>> +void host_cpu_initfn(Object *obj);
>> +void host_cpu_realizefn(DeviceState *dev, Error **errp);
>> +void host_cpu_max_initfn(X86CPU *cpu);
>> +
>> +void host_cpu_vendor_fms(char *vendor, int *family, int *model, int
>> *stepping);
>> +
>> +#endif /* HOST_CPU_TYPE_H */
>> diff --git a/target/i386/meson.build b/target/i386/meson.build
>> index 50c8fba6cb..c84b0d6965 100644
>> --- a/target/i386/meson.build
>> +++ b/target/i386/meson.build
>> @@ -6,8 +6,12 @@ i386_ss.add(files(
>> 'xsave_helper.c',
>> 'cpu-dump.c',
>> ))
>> -i386_ss.add(when: 'CONFIG_TCG', if_true: files('tcg-cpu.c'))
>> -i386_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false:
>> files('sev-stub.c'))
>> +
>> +i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c', 'sev.c'),
>> if_false: files('sev-stub.c'))
>> +
>> +# x86 cpu type
>> +i386_ss.add(when: 'CONFIG_KVM', if_true: files('host-cpu.c'))
>> +i386_ss.add(when: 'CONFIG_HVF', if_true: files('host-cpu.c'))
>>
>> i386_softmmu_ss = ss.source_set()
>> i386_softmmu_ss.add(files(
>> diff --git a/target/i386/tcg-cpu.c b/target/i386/tcg-cpu.c
>> deleted file mode 100644
>> index 628dd29fe7..0000000000
>> --- a/target/i386/tcg-cpu.c
>> +++ /dev/null
>> @@ -1,71 +0,0 @@
>> -/*
>> - * i386 TCG cpu class initialization
>> - *
>> - * Copyright (c) 2003 Fabrice Bellard
>> - *
>> - * This library is free software; you can redistribute it and/or
>> - * modify it under the terms of the GNU Lesser General Public
>> - * License as published by the Free Software Foundation; either
>> - * version 2 of the License, or (at your option) any later version.
>> - *
>> - * This library is distributed in the hope that it will be useful,
>> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> - * Lesser General Public License for more details.
>> - *
>> - * You should have received a copy of the GNU Lesser General Public
>> - * License along with this library; if not, see
>> <http://www.gnu.org/licenses/>.
>> - */
>> -
>> -#include "qemu/osdep.h"
>> -#include "cpu.h"
>> -#include "tcg-cpu.h"
>> -#include "exec/exec-all.h"
>> -#include "sysemu/runstate.h"
>> -#include "helper-tcg.h"
>> -
>> -#if !defined(CONFIG_USER_ONLY)
>> -#include "hw/i386/apic.h"
>> -#endif
>> -
>> -/* Frob eflags into and out of the CPU temporary format. */
>> -
>> -static void x86_cpu_exec_enter(CPUState *cs)
>> -{
>> - X86CPU *cpu = X86_CPU(cs);
>> - CPUX86State *env = &cpu->env;
>> -
>> - CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
>> - env->df = 1 - (2 * ((env->eflags >> 10) & 1));
>> - CC_OP = CC_OP_EFLAGS;
>> - env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
>> -}
>> -
>> -static void x86_cpu_exec_exit(CPUState *cs)
>> -{
>> - X86CPU *cpu = X86_CPU(cs);
>> - CPUX86State *env = &cpu->env;
>> -
>> - env->eflags = cpu_compute_eflags(env);
>> -}
>> -
>> -static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
>> -{
>> - X86CPU *cpu = X86_CPU(cs);
>> -
>> - cpu->env.eip = tb->pc - tb->cs_base;
>> -}
>> -
>> -void tcg_cpu_common_class_init(CPUClass *cc)
>> -{
>> - cc->do_interrupt = x86_cpu_do_interrupt;
>> - cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
>> - cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
>> - cc->cpu_exec_enter = x86_cpu_exec_enter;
>> - cc->cpu_exec_exit = x86_cpu_exec_exit;
>> - cc->tcg_initialize = tcg_x86_init;
>> - cc->tlb_fill = x86_cpu_tlb_fill;
>> -#ifndef CONFIG_USER_ONLY
>> - cc->debug_excp_handler = breakpoint_handler;
>> -#endif
>> -}
>> diff --git a/target/i386/tcg-cpu.h b/target/i386/tcg-cpu.h
>> deleted file mode 100644
>> index 81f02e562e..0000000000
>> --- a/target/i386/tcg-cpu.h
>> +++ /dev/null
>> @@ -1,15 +0,0 @@
>> -/*
>> - * i386 TCG CPU class initialization
>> - *
>> - * Copyright 2020 SUSE LLC
>> - *
>> - * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> - * See the COPYING file in the top-level directory.
>> - */
>> -
>> -#ifndef TCG_CPU_H
>> -#define TCG_CPU_H
>> -
>> -void tcg_cpu_common_class_init(CPUClass *cc);
>> -
>> -#endif /* TCG_CPU_H */
>> --
>> 2.26.2
>>
>
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, (continued)
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Eduardo Habkost, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Paolo Bonzini, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Eduardo Habkost, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Paolo Bonzini, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Eduardo Habkost, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Claudio Fontana, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Eduardo Habkost, 2020/11/10
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Claudio Fontana, 2020/11/11
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Claudio Fontana, 2020/11/16
Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration, Eduardo Habkost, 2020/11/09
- Re: [RFC v1 09/10] i386: split cpu.c and defer x86 models registration,
Claudio Fontana <=
[RFC v1 10/10] module: add priority to module_init, Claudio Fontana, 2020/11/09
Re: [RFC v1 00/10] i386 cleanup, no-reply, 2020/11/09