mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
i386: split cpu accelerators from cpu.c, using AccelCPUClass
i386 is the first user of AccelCPUClass, allowing to split
cpu.c into:
cpu.c cpuid and common x86 cpu functionality
host-cpu.c host x86 cpu functions and "host" cpu type
kvm/kvm-cpu.c KVM x86 AccelCPUClass
hvf/hvf-cpu.c HVF x86 AccelCPUClass
tcg/tcg-cpu.c TCG x86 AccelCPUClass
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
[claudio]:
Rebased on commit b8184135 ("target/i386: allow modifying TCG phys-addr-bits")
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Message-Id: <20210322132800.7470-5-cfontana@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
committed by
Paolo Bonzini
parent
0ac2b19743
commit
f5cc5a5c16
+1
-1
@@ -351,7 +351,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Richard Henderson <richard.henderson@linaro.org>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Maintained
|
||||
F: target/i386/
|
||||
F: target/i386/tcg/
|
||||
F: tests/tcg/i386/
|
||||
F: tests/tcg/x86_64/
|
||||
F: hw/i386/
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "hw/hyperv/vmbus-bridge.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "hw/i386/acpi-build.h"
|
||||
#include "kvm/kvm-cpu.h"
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
|
||||
+41
-342
File diff suppressed because it is too large
Load Diff
+8
-12
@@ -1926,13 +1926,20 @@ int cpu_x86_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc);
|
||||
|
||||
/* cpu.c */
|
||||
void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
||||
uint32_t vendor2, uint32_t vendor3);
|
||||
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);
|
||||
@@ -2137,17 +2144,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 */
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* x86 host CPU functions, and "host" cpu type initialization
|
||||
*
|
||||
* Copyright 2021 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"
|
||||
|
||||
/* 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(CPUState *cs, Error **errp)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#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_instance_init(X86CPU *cpu)
|
||||
{
|
||||
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_instance_init(X86CPU *cpu)
|
||||
{
|
||||
char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
|
||||
char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
|
||||
int family, model, stepping;
|
||||
|
||||
/* Use max host physical address bits if -cpu max option is applied */
|
||||
object_property_set_bool(OBJECT(cpu), "host-phys-bits", true, &error_abort);
|
||||
|
||||
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("processor with all supported host features ");
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static void host_cpu_type_init(void)
|
||||
{
|
||||
type_register_static(&host_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(host_cpu_type_init);
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* x86 host CPU type initialization and host CPU functions
|
||||
*
|
||||
* Copyright 2021 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_H
|
||||
#define HOST_CPU_H
|
||||
|
||||
void host_cpu_instance_init(X86CPU *cpu);
|
||||
void host_cpu_max_instance_init(X86CPU *cpu);
|
||||
void host_cpu_realizefn(CPUState *cs, Error **errp);
|
||||
|
||||
void host_cpu_vendor_fms(char *vendor, int *family, int *model, int *stepping);
|
||||
|
||||
#endif /* HOST_CPU_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* x86 HVF CPU type initialization
|
||||
*
|
||||
* Copyright 2021 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"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "hw/core/accel-cpu.h"
|
||||
|
||||
static void hvf_cpu_max_instance_init(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
host_cpu_max_instance_init(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_instance_init(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
|
||||
host_cpu_instance_init(cpu);
|
||||
|
||||
/* Special cases not set in the X86CPUDefinition structs: */
|
||||
/* TODO: in-kernel irqchip for hvf */
|
||||
|
||||
if (cpu->max_features) {
|
||||
hvf_cpu_max_instance_init(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
|
||||
|
||||
acc->cpu_realizefn = host_cpu_realizefn;
|
||||
acc->cpu_instance_init = hvf_cpu_instance_init;
|
||||
}
|
||||
|
||||
static const TypeInfo hvf_cpu_accel_type_info = {
|
||||
.name = ACCEL_CPU_NAME("hvf"),
|
||||
|
||||
.parent = TYPE_ACCEL_CPU,
|
||||
.class_init = hvf_cpu_accel_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void hvf_cpu_accel_register_types(void)
|
||||
{
|
||||
type_register_static(&hvf_cpu_accel_type_info);
|
||||
}
|
||||
|
||||
type_init(hvf_cpu_accel_register_types);
|
||||
@@ -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.c',
|
||||
))
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* x86 KVM CPU type initialization
|
||||
*
|
||||
* Copyright 2021 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.h"
|
||||
#include "qapi/error.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "kvm_i386.h"
|
||||
#include "hw/core/accel-cpu.h"
|
||||
|
||||
static void kvm_cpu_realizefn(CPUState *cs, Error **errp)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
/*
|
||||
* The realize order is important, since x86_cpu_realize() checks if
|
||||
* nothing else has been set by the user (or by accelerators) in
|
||||
* cpu->ucode_rev and cpu->phys_bits.
|
||||
*
|
||||
* realize order:
|
||||
* 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(cs, errp);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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" },
|
||||
{ "kvm-msi-ext-dest-id", "off" },
|
||||
{ "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_instance_init(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
KVMState *s = kvm_state;
|
||||
|
||||
host_cpu_max_instance_init(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_instance_init(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
|
||||
host_cpu_instance_init(cpu);
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
x86_cpu_change_kvm_default("x2apic", "off");
|
||||
} else if (kvm_irqchip_is_split() && kvm_enable_x2apic()) {
|
||||
x86_cpu_change_kvm_default("kvm-msi-ext-dest-id", "on");
|
||||
}
|
||||
|
||||
/* Special cases not set in the X86CPUDefinition structs: */
|
||||
|
||||
x86_cpu_apply_props(cpu, kvm_default_props);
|
||||
|
||||
if (cpu->max_features) {
|
||||
kvm_cpu_max_instance_init(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
|
||||
|
||||
acc->cpu_realizefn = kvm_cpu_realizefn;
|
||||
acc->cpu_instance_init = kvm_cpu_instance_init;
|
||||
}
|
||||
static const TypeInfo kvm_cpu_accel_type_info = {
|
||||
.name = ACCEL_CPU_NAME("kvm"),
|
||||
|
||||
.parent = TYPE_ACCEL_CPU,
|
||||
.class_init = kvm_cpu_accel_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
static void kvm_cpu_accel_register_types(void)
|
||||
{
|
||||
type_register_static(&kvm_cpu_accel_type_info);
|
||||
}
|
||||
type_init(kvm_cpu_accel_register_types);
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* i386 KVM CPU type and functions
|
||||
*
|
||||
* 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_H
|
||||
#define KVM_CPU_H
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
/*
|
||||
* 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_H */
|
||||
@@ -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"
|
||||
@@ -288,7 +289,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) &&
|
||||
|
||||
@@ -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.c',
|
||||
))
|
||||
|
||||
i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
|
||||
|
||||
@@ -6,7 +6,11 @@ i386_ss.add(files(
|
||||
'xsave_helper.c',
|
||||
'cpu-dump.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(
|
||||
|
||||
+107
-6
@@ -19,13 +19,14 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "tcg-cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "helper-tcg.h"
|
||||
#include "qemu/accel.h"
|
||||
#include "hw/core/accel-cpu.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/i386/apic.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/units.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#endif
|
||||
|
||||
/* Frob eflags into and out of the CPU temporary format. */
|
||||
@@ -72,7 +73,107 @@ static struct TCGCPUOps x86_tcg_ops = {
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
void tcg_cpu_common_class_init(CPUClass *cc)
|
||||
static void tcg_cpu_class_init(CPUClass *cc)
|
||||
{
|
||||
cc->tcg_ops = &x86_tcg_ops;
|
||||
}
|
||||
|
||||
#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(CPUState *cs, Error **errp)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
|
||||
/*
|
||||
* The realize order is important, since x86_cpu_realize() checks if
|
||||
* nothing else has been set by the user (or by accelerators) in
|
||||
* cpu->ucode_rev and cpu->phys_bits, and the memory regions
|
||||
* initialized here are needed for the vcpu initialization.
|
||||
*
|
||||
* realize order:
|
||||
* tcg_cpu -> host_cpu -> x86_cpu
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
#else /* CONFIG_USER_ONLY */
|
||||
|
||||
static void tcg_cpu_realizefn(CPUState *cs, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
#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_instance_init(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
/* Special cases not set in the X86CPUDefinition structs: */
|
||||
x86_cpu_apply_props(cpu, tcg_default_props);
|
||||
}
|
||||
|
||||
static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelCPUClass *acc = ACCEL_CPU_CLASS(oc);
|
||||
|
||||
acc->cpu_realizefn = tcg_cpu_realizefn;
|
||||
acc->cpu_class_init = tcg_cpu_class_init;
|
||||
acc->cpu_instance_init = tcg_cpu_instance_init;
|
||||
}
|
||||
static const TypeInfo tcg_cpu_accel_type_info = {
|
||||
.name = ACCEL_CPU_NAME("tcg"),
|
||||
|
||||
.parent = TYPE_ACCEL_CPU,
|
||||
.class_init = tcg_cpu_accel_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
static void tcg_cpu_accel_register_types(void)
|
||||
{
|
||||
type_register_static(&tcg_cpu_accel_type_info);
|
||||
}
|
||||
type_init(tcg_cpu_accel_register_types);
|
||||
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user