[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH for-1.4 qom-cpu 6/9] pc: Set fw_cfg data based o
From: |
Andreas Färber |
Subject: |
Re: [Qemu-devel] [PATCH for-1.4 qom-cpu 6/9] pc: Set fw_cfg data based on APIC ID calculation |
Date: |
Wed, 23 Jan 2013 17:33:25 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130105 Thunderbird/17.0.2 |
Am 22.01.2013 21:25, schrieb Eduardo Habkost:
> This changes FW_CFG_MAX_CPUS and FW_CFG_NUMA to use apic_id_for_cpu(),
> so the NUMA table can be based on the APIC IDs, instead of CPU index
> (SeaBIOS knows nothing about CPU indexes, just APIC IDs).
>
> Signed-off-by: Eduardo Habkost <address@hidden>
> ---
> Changes v2:
> - Get PC object as argument
> - Add more detailed comments explaining the reason for FW_CFG_MAX_CPUS
> not being simply 'max_cpus'
>
> Changes v3:
> - Use PCInitArgs instead of PC object
>
> Changes v4:
> - Don't use PCInitArgs, just add the necessary data for apic_id_limit()
> as argument
> - Rename function to pc_apic_id_limit()
> - Rename max_apic_id to apic_id_limit
>
> Changes v5:
> - Refresh after apic_id_for_cpu() -> x86_cpu_apic_id_from_index()
> rename
> - Refresh after original code changes to use g_new0()
> ---
> hw/pc.c | 45 ++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 38 insertions(+), 7 deletions(-)
>
> diff --git a/hw/pc.c b/hw/pc.c
> index 44bb1dc..9029a55 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -551,6 +551,18 @@ int e820_add_entry(uint64_t address, uint64_t length,
> uint32_t type)
> return index;
> }
>
> +/* Calculates the limit to CPU APIC ID values
> + *
> + * This function returns the limit for the APIC ID value, so that all
> + * CPU APIC IDs are < pc_apic_id_limit().
> + *
> + * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
> + */
> +static unsigned int pc_apic_id_limit(unsigned int max_cpus)
> +{
> + return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
> +}
> +
> static void *bochs_bios_init(void)
> {
> void *fw_cfg;
> @@ -558,9 +570,24 @@ static void *bochs_bios_init(void)
> size_t smbios_len;
> uint64_t *numa_fw_cfg;
> int i, j;
> + unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
>
> fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
> - fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
> + /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
> + *
> + * SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
> + * QEMU<->SeaBIOS interface is not based on the "CPU index", but on the
> APIC
> + * ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
> + * "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
> + * may see".
> + *
> + * So, this means we must not use max_cpus, here, but the maximum
> possible
> + * APIC ID value, plus one.
> + *
> + * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
> + * the APIC ID, not the "CPU index"
> + */
> + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
> fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
> fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
> fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
> @@ -579,21 +606,25 @@ static void *bochs_bios_init(void)
> * of nodes, one word for each VCPU->node and one word for each node to
> * hold the amount of memory.
> */
> - numa_fw_cfg = g_new0(uint64_t, 1 + max_cpus + nb_numa_nodes);
> + numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
> numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
> - for (i = 0; i < max_cpus; i++) {
> + unsigned int cpu_idx;
Beep.
> + for (cpu_idx = 0; cpu_idx < max_cpus; cpu_idx++) {
> + unsigned int apic_id = x86_cpu_apic_id_from_index(cpu_idx);
> + assert(apic_id < apic_id_limit);
> for (j = 0; j < nb_numa_nodes; j++) {
> - if (test_bit(i, node_cpumask[j])) {
> - numa_fw_cfg[i + 1] = cpu_to_le64(j);
> + if (test_bit(cpu_idx, node_cpumask[j])) {
> + numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
> break;
> }
> }
> }
Why can't we keep using i here? That would leave the "for (..." and
"test_bit" lines unchanged and let us spot the actual changes of i vs.
apic_id more easily.
Andreas
> for (i = 0; i < nb_numa_nodes; i++) {
> - numa_fw_cfg[max_cpus + 1 + i] = cpu_to_le64(node_mem[i]);
> + numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]);
> }
> fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
> - (1 + max_cpus + nb_numa_nodes) * sizeof(*numa_fw_cfg));
> + (1 + apic_id_limit + nb_numa_nodes) *
> + sizeof(*numa_fw_cfg));
>
> return fw_cfg;
> }
>
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
[Qemu-devel] [PATCH for-1.4 qom-cpu 7/9] tests: Support target-specific unit tests, Eduardo Habkost, 2013/01/22
[Qemu-devel] [PATCH for-1.4 qom-cpu 3/9] fw_cfg: Remove FW_CFG_MAX_CPUS from fw_cfg_init(), Eduardo Habkost, 2013/01/22
[Qemu-devel] [PATCH for-1.4 qom-cpu 5/9] cpus.h: Make constant smp_cores/smp_threads available on *-user, Eduardo Habkost, 2013/01/22
[Qemu-devel] [PATCH for-1.4 qom-cpu 8/9] target-i386: Topology & APIC ID utility functions, Eduardo Habkost, 2013/01/22