[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/4] hw/i386: Factorize CPU routine
From: |
Sergio Lopez |
Subject: |
[Qemu-devel] [PATCH 1/4] hw/i386: Factorize CPU routine |
Date: |
Fri, 28 Jun 2019 13:53:46 +0200 |
This is a combination of the following commits from
NEMU (https://github.com/intel/nemu):
===============================================
commit b6472ce5ce5108c7aacb0dfa3d74b3eb8f98ae85
Author: Samuel Ortiz <address@hidden>
Date: Fri Mar 22 10:28:31 2019 +0800
hw: i386: Factorize CPU routines
A few routines are now shared between pc_* and virt, including the CPU
init one.
We factorize those routines into an i386 specific file that is now used
by all x86 machines.
Signed-off-by: Samuel Ortiz <address@hidden>
commit f29f3c294a889ad659dc8808728e8441e23a675c
Author: Samuel Ortiz <address@hidden>
Date: Mon Oct 8 15:37:17 2018 +0200
hw: i386: Remove the pc header dependency from the cpu code
It's only a matter of moving the compat APIC boolean to the correct
header file (apic.h).
Signed-off-by: Samuel Ortiz <address@hidden>
===============================================
Signed-off-by: Sergio Lopez <address@hidden>
---
hw/i386/Makefile.objs | 1 +
hw/i386/cpu.c | 174 +++++++++++++++++++++++++++++++++
hw/i386/pc.c | 151 ++--------------------------
hw/i386/pc_piix.c | 3 +-
hw/i386/pc_q35.c | 3 +-
include/hw/i386/apic.h | 1 +
include/hw/i386/cpu-internal.h | 32 ++++++
7 files changed, 218 insertions(+), 147 deletions(-)
create mode 100644 hw/i386/cpu.c
create mode 100644 include/hw/i386/cpu-internal.h
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 5d9c9efd5f..102f2b35fc 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -1,5 +1,6 @@
obj-$(CONFIG_KVM) += kvm/
obj-y += multiboot.o
+obj-y += cpu.o
obj-y += pc.o
obj-$(CONFIG_I440FX) += pc_piix.o
obj-$(CONFIG_Q35) += pc_q35.o
diff --git a/hw/i386/cpu.c b/hw/i386/cpu.c
new file mode 100644
index 0000000000..e13ae61535
--- /dev/null
+++ b/hw/i386/cpu.c
@@ -0,0 +1,174 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corportation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+#include "sysemu/cpus.h"
+#include "sysemu/qtest.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+
+#include "hw/i386/cpu-internal.h"
+#include "hw/i386/apic.h"
+#include "hw/i386/topology.h"
+
+#include "hw/acpi/pc-hotplug.h"
+
+static void cpu_new(const char *typename, int64_t apic_id, Error **errp)
+{
+ Object *cpu = NULL;
+ Error *local_err = NULL;
+
+ cpu = object_new(typename);
+
+ object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
+ object_property_set_bool(cpu, true, "realized", &local_err);
+
+ object_unref(cpu);
+ error_propagate(errp, local_err);
+}
+
+/* Calculates initial APIC ID for a specific CPU index
+ *
+ * Currently we need to be able to calculate the APIC ID from the CPU index
+ * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces
have
+ * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
+ * all CPUs up to max_cpus.
+ */
+uint32_t cpu_apicid_from_index(unsigned int cpu_index, bool compat)
+{
+ uint32_t correct_id;
+ static bool warned;
+
+ correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
+ if (compat) {
+ if (cpu_index != correct_id && !warned && !qtest_enabled()) {
+ error_report("APIC IDs set in compatibility mode, "
+ "CPU topology won't match the configuration");
+ warned = true;
+ }
+ return cpu_index;
+ } else {
+ return correct_id;
+ }
+}
+
+CpuInstanceProperties cpu_index_to_props(MachineState *ms, unsigned cpu_index)
+{
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
+
+ assert(cpu_index < possible_cpus->len);
+ return possible_cpus->cpus[cpu_index].props;
+}
+
+
+int64_t cpu_get_default_cpu_node_id(const MachineState *ms, int idx)
+{
+ X86CPUTopoInfo topo;
+
+ assert(idx < ms->possible_cpus->len);
+ x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
+ smp_cores, smp_threads, &topo);
+ return topo.pkg_id % nb_numa_nodes;
+}
+
+const CPUArchIdList *cpu_possible_cpu_arch_ids(MachineState *ms)
+{
+ int i;
+
+ if (ms->possible_cpus) {
+ /*
+ * make sure that max_cpus hasn't changed since the first use, i.e.
+ * -smp hasn't been parsed after it
+ */
+ assert(ms->possible_cpus->len == max_cpus);
+ return ms->possible_cpus;
+ }
+
+ ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
+ sizeof(CPUArchId) * max_cpus);
+ ms->possible_cpus->len = max_cpus;
+ for (i = 0; i < ms->possible_cpus->len; i++) {
+ X86CPUTopoInfo topo;
+
+ ms->possible_cpus->cpus[i].type = ms->cpu_type;
+ ms->possible_cpus->cpus[i].vcpus_count = 1;
+ ms->possible_cpus->cpus[i].arch_id = cpu_apicid_from_index(i,
compat_apic_id_mode);
+ x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
+ smp_cores, smp_threads, &topo);
+ ms->possible_cpus->cpus[i].props.has_socket_id = true;
+ ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id;
+ ms->possible_cpus->cpus[i].props.has_core_id = true;
+ ms->possible_cpus->cpus[i].props.core_id = topo.core_id;
+ ms->possible_cpus->cpus[i].props.has_thread_id = true;
+ ms->possible_cpus->cpus[i].props.thread_id = topo.smt_id;
+ }
+ return ms->possible_cpus;
+}
+
+
+void cpu_hot_add(const int64_t id, Error **errp)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ int64_t apic_id = cpu_apicid_from_index(id, compat_apic_id_mode);
+ Error *local_err = NULL;
+
+ if (id < 0) {
+ error_setg(errp, "Invalid CPU id: %" PRIi64, id);
+ return;
+ }
+
+ if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) {
+ error_setg(errp, "Unable to add CPU: %" PRIi64
+ ", resulting APIC ID (%" PRIi64 ") is too large",
+ id, apic_id);
+ return;
+ }
+
+ cpu_new(ms->cpu_type, apic_id, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+}
+
+uint32_t cpus_init(MachineState *ms, bool compat)
+{
+ int i;
+ uint32_t apic_id_limit;
+ const CPUArchIdList *possible_cpus;
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+ /* Calculates the limit to CPU APIC ID values
+ *
+ * Limit for the APIC ID value, so that all
+ * CPU APIC IDs are < ms->apic_id_limit.
+ *
+ * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
+ */
+ apic_id_limit = cpu_apicid_from_index(max_cpus - 1, compat) + 1;
+ possible_cpus = mc->possible_cpu_arch_ids(ms);
+ for (i = 0; i < smp_cpus; i++) {
+ cpu_new(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
+ &error_fatal);
+ }
+
+ return apic_id_limit;
+}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e96360b47a..07d67a5031 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -26,6 +26,7 @@
#include "qemu/units.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
+#include "hw/i386/cpu-internal.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
#include "hw/i386/apic.h"
@@ -914,38 +915,13 @@ bool e820_get_entry(int idx, uint32_t type, uint64_t
*address, uint64_t *length)
}
/* Enables contiguous-apic-ID mode, for compatibility */
-static bool compat_apic_id_mode;
+bool compat_apic_id_mode;
void enable_compat_apic_id_mode(void)
{
compat_apic_id_mode = true;
}
-/* Calculates initial APIC ID for a specific CPU index
- *
- * Currently we need to be able to calculate the APIC ID from the CPU index
- * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces
have
- * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
- * all CPUs up to max_cpus.
- */
-static uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index)
-{
- uint32_t correct_id;
- static bool warned;
-
- correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
- if (compat_apic_id_mode) {
- if (cpu_index != correct_id && !warned && !qtest_enabled()) {
- error_report("APIC IDs set in compatibility mode, "
- "CPU topology won't match the configuration");
- warned = true;
- }
- return cpu_index;
- } else {
- return correct_id;
- }
-}
-
static void pc_build_smbios(PCMachineState *pcms)
{
uint8_t *smbios_tables, *smbios_anchor;
@@ -1516,67 +1492,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int
level)
}
}
-static void pc_new_cpu(const char *typename, int64_t apic_id, Error **errp)
-{
- Object *cpu = NULL;
- Error *local_err = NULL;
-
- cpu = object_new(typename);
-
- object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
- object_property_set_bool(cpu, true, "realized", &local_err);
-
- object_unref(cpu);
- error_propagate(errp, local_err);
-}
-
-void pc_hot_add_cpu(const int64_t id, Error **errp)
-{
- MachineState *ms = MACHINE(qdev_get_machine());
- int64_t apic_id = x86_cpu_apic_id_from_index(id);
- Error *local_err = NULL;
-
- if (id < 0) {
- error_setg(errp, "Invalid CPU id: %" PRIi64, id);
- return;
- }
-
- if (apic_id >= ACPI_CPU_HOTPLUG_ID_LIMIT) {
- error_setg(errp, "Unable to add CPU: %" PRIi64
- ", resulting APIC ID (%" PRIi64 ") is too large",
- id, apic_id);
- return;
- }
-
- pc_new_cpu(ms->cpu_type, apic_id, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-void pc_cpus_init(PCMachineState *pcms)
-{
- int i;
- const CPUArchIdList *possible_cpus;
- MachineState *ms = MACHINE(pcms);
- MachineClass *mc = MACHINE_GET_CLASS(pcms);
-
- /* Calculates the limit to CPU APIC ID values
- *
- * Limit for the APIC ID value, so that all
- * CPU APIC IDs are < pcms->apic_id_limit.
- *
- * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
- */
- pcms->apic_id_limit = x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
- possible_cpus = mc->possible_cpu_arch_ids(ms);
- for (i = 0; i < smp_cpus; i++) {
- pc_new_cpu(possible_cpus->cpus[i].type, possible_cpus->cpus[i].arch_id,
- &error_fatal);
- }
-}
-
static void pc_build_feature_control_file(PCMachineState *pcms)
{
MachineState *ms = MACHINE(pcms);
@@ -2638,60 +2553,6 @@ static void pc_machine_reset(void)
}
}
-static CpuInstanceProperties
-pc_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
-{
- MachineClass *mc = MACHINE_GET_CLASS(ms);
- const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
-
- assert(cpu_index < possible_cpus->len);
- return possible_cpus->cpus[cpu_index].props;
-}
-
-static int64_t pc_get_default_cpu_node_id(const MachineState *ms, int idx)
-{
- X86CPUTopoInfo topo;
-
- assert(idx < ms->possible_cpus->len);
- x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
- smp_cores, smp_threads, &topo);
- return topo.pkg_id % nb_numa_nodes;
-}
-
-static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms)
-{
- int i;
-
- if (ms->possible_cpus) {
- /*
- * make sure that max_cpus hasn't changed since the first use, i.e.
- * -smp hasn't been parsed after it
- */
- assert(ms->possible_cpus->len == max_cpus);
- return ms->possible_cpus;
- }
-
- ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
- sizeof(CPUArchId) * max_cpus);
- ms->possible_cpus->len = max_cpus;
- for (i = 0; i < ms->possible_cpus->len; i++) {
- X86CPUTopoInfo topo;
-
- ms->possible_cpus->cpus[i].type = ms->cpu_type;
- ms->possible_cpus->cpus[i].vcpus_count = 1;
- ms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(i);
- x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
- smp_cores, smp_threads, &topo);
- ms->possible_cpus->cpus[i].props.has_socket_id = true;
- ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id;
- ms->possible_cpus->cpus[i].props.has_core_id = true;
- ms->possible_cpus->cpus[i].props.core_id = topo.core_id;
- ms->possible_cpus->cpus[i].props.has_thread_id = true;
- ms->possible_cpus->cpus[i].props.thread_id = topo.smt_id;
- }
- return ms->possible_cpus;
-}
-
static void x86_nmi(NMIState *n, int cpu_index, Error **errp)
{
/* cpu index isn't used */
@@ -2732,13 +2593,13 @@ static void pc_machine_class_init(ObjectClass *oc, void
*data)
pcmc->pvh_enabled = true;
assert(!mc->get_hotplug_handler);
mc->get_hotplug_handler = pc_get_hotplug_handler;
- mc->cpu_index_to_instance_props = pc_cpu_index_to_props;
- mc->get_default_cpu_node_id = pc_get_default_cpu_node_id;
- mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids;
+ mc->cpu_index_to_instance_props = cpu_index_to_props;
+ mc->get_default_cpu_node_id = cpu_get_default_cpu_node_id;
+ mc->possible_cpu_arch_ids = cpu_possible_cpu_arch_ids;
mc->auto_enable_numa_with_memhp = true;
mc->has_hotpluggable_cpus = true;
mc->default_boot_order = "cad";
- mc->hot_add_cpu = pc_hot_add_cpu;
+ mc->hot_add_cpu = cpu_hot_add;
mc->block_default_type = IF_IDE;
mc->max_cpus = 255;
mc->reset = pc_machine_reset;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c07c4a5b38..1e240004dd 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -28,6 +28,7 @@
#include "hw/hw.h"
#include "hw/loader.h"
#include "hw/i386/pc.h"
+#include "hw/i386/cpu-internal.h"
#include "hw/i386/apic.h"
#include "hw/display/ramfb.h"
#include "hw/firmware/smbios.h"
@@ -150,7 +151,7 @@ static void pc_init1(MachineState *machine,
}
}
- pc_cpus_init(pcms);
+ pcms->apic_id_limit = cpus_init(machine, compat_apic_id_mode);
if (kvm_enabled() && pcmc->kvmclock_enabled) {
kvmclock_create();
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 57232aed6b..308cd04a13 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -43,6 +43,7 @@
#include "hw/pci-host/q35.h"
#include "exec/address-spaces.h"
#include "hw/i386/pc.h"
+#include "hw/i386/cpu-internal.h"
#include "hw/i386/ich9.h"
#include "hw/i386/amd_iommu.h"
#include "hw/i386/intel_iommu.h"
@@ -180,7 +181,7 @@ static void pc_q35_init(MachineState *machine)
xen_hvm_init(pcms, &ram_memory);
}
- pc_cpus_init(pcms);
+ pcms->apic_id_limit = cpus_init(machine, compat_apic_id_mode);
kvmclock_create();
diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h
index da1d2fe155..f72be753b8 100644
--- a/include/hw/i386/apic.h
+++ b/include/hw/i386/apic.h
@@ -23,5 +23,6 @@ int apic_get_highest_priority_irr(DeviceState *dev);
/* pc.c */
DeviceState *cpu_get_current_apic(void);
+extern bool compat_apic_id_mode;
#endif
diff --git a/include/hw/i386/cpu-internal.h b/include/hw/i386/cpu-internal.h
new file mode 100644
index 0000000000..48a5253aa9
--- /dev/null
+++ b/include/hw/i386/cpu-internal.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright (c) 2018 Intel Corportation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_I386_CPU_H
+#define QEMU_I386_CPU_H
+
+#include "hw/boards.h"
+
+uint32_t cpu_apicid_from_index(unsigned int cpu_index, bool compat);
+
+CpuInstanceProperties cpu_index_to_props(MachineState *ms, unsigned cpu_index);
+int64_t cpu_get_default_cpu_node_id(const MachineState *ms, int idx);
+const CPUArchIdList *cpu_possible_cpu_arch_ids(MachineState *ms);
+
+void cpu_hot_add(const int64_t id, Error **errp);
+uint32_t cpus_init(MachineState *ms, bool compat);
+
+#endif
--
2.21.0