From: Sergio Lopez <slp@redhat.com>
To: mst@redhat.com, marcel.apfelbaum@gmail.com, pbonzini@redhat.com,
rth@twiddle.net, ehabkost@redhat.com
Cc: qemu-devel@nongnu.org, Sergio Lopez <slp@redhat.com>
Subject: [Qemu-devel] [PATCH 1/4] hw/i386: Factorize CPU routine
Date: Fri, 28 Jun 2019 13:53:46 +0200 [thread overview]
Message-ID: <20190628115349.60293-2-slp@redhat.com> (raw)
In-Reply-To: <20190628115349.60293-1-slp@redhat.com>
This is a combination of the following commits from
NEMU (https://github.com/intel/nemu):
===============================================
commit b6472ce5ce5108c7aacb0dfa3d74b3eb8f98ae85
Author: Samuel Ortiz <sameo@linux.intel.com>
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 <sameo@linux.intel.com>
commit f29f3c294a889ad659dc8808728e8441e23a675c
Author: Samuel Ortiz <sameo@linux.intel.com>
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 <sameo@linux.intel.com>
===============================================
Signed-off-by: Sergio Lopez <slp@redhat.com>
---
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
next prev parent reply other threads:[~2019-06-28 12:43 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-28 11:53 [Qemu-devel] [PATCH 0/4] Introduce the microvm machine type Sergio Lopez
2019-06-28 11:53 ` Sergio Lopez [this message]
2019-06-28 20:03 ` [Qemu-devel] [PATCH 1/4] hw/i386: Factorize CPU routine Eduardo Habkost
2019-06-28 21:44 ` Sergio Lopez
2019-07-01 9:25 ` Michael S. Tsirkin
2019-06-28 11:53 ` [Qemu-devel] [PATCH 2/4] hw/virtio: Factorize virtio-mmio headers Sergio Lopez
2019-06-28 14:03 ` Michael S. Tsirkin
2019-06-28 20:50 ` Sergio Lopez
2019-06-30 21:36 ` Michael S. Tsirkin
2019-07-02 8:19 ` Gerd Hoffmann
2019-07-02 13:22 ` Michael S. Tsirkin
2019-06-28 11:53 ` [Qemu-devel] [PATCH 3/4] hw/i386: Add an Intel MPTable generator Sergio Lopez
2019-06-28 11:53 ` [Qemu-devel] [PATCH 4/4] hw/i386: Introduce the microvm machine type Sergio Lopez
2019-06-28 14:06 ` Michael S. Tsirkin
2019-06-28 20:56 ` Sergio Lopez
2019-06-28 22:17 ` Paolo Bonzini
2019-06-30 21:37 ` Michael S. Tsirkin
2019-06-28 19:15 ` Maran Wilson
2019-06-28 21:05 ` Sergio Lopez
2019-06-28 21:54 ` Maran Wilson
2019-06-28 22:23 ` Sergio Lopez
2019-06-28 21:56 ` Paolo Bonzini
2019-06-28 19:47 ` Eduardo Habkost
2019-06-28 21:42 ` Sergio Lopez
2019-06-28 21:57 ` Paolo Bonzini
2019-06-28 13:21 ` [Qemu-devel] [PATCH 0/4] " Paolo Bonzini
2019-06-28 20:49 ` Sergio Lopez
2019-06-28 16:32 ` no-reply
2019-06-28 18:16 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190628115349.60293-2-slp@redhat.com \
--to=slp@redhat.com \
--cc=ehabkost@redhat.com \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.