Skip to content

Commit 74df87d

Browse files
Salil Mehtajongwu
authored andcommitted
arm64: kernel: Handle disabled[(+)present] cpus in MADT/GICC during init
With ACPI enabled, cpus get identified by the presence of the GICC entry in the MADT Table. Each GICC entry part of MADT presents cpu as enabled or disabled. As of now, the disabled cpus are skipped as physical cpu hotplug is not supported. These remain disabled even after the kernel has booted. To support virtual cpu hotplug(in which case disabled vcpus could be hotplugged even after kernel has booted), QEMU will populate MADT Table with appropriate details of GICC entry for each possible(present+disabled) vcpu. Now, during the init time vcpus will be identified as present or disabled. To achieve this, below changes have been made with respect to the present/possible vcpu handling along with the mentioned reasoning: 1. Identify all possible(present+disabled) vcpus at boot/init time and set their present mask and possible mask. In the existing code, cpus are being marked present quite late within smp_prepare_cpus() function, which gets called in context to the kernel thread. Since the cpu hotplug is not supported, present cpus are always equal to the possible cpus. But with cpu hotplug enabled, this assumption is not true. Hence, present cpus should be marked while MADT GICC entries are bring parsed for each vcpu. 2. Set possible cpus to include disabled. This needs to be done now while parsing MADT GICC entries corresponding to each vcpu as the disabled vcpu info is available only at this point as for hotplug case possible vcpus is not equal to present vcpus. 3. We will store the parsed madt/gicc entry even for the disabled vcpus during init time. This is needed as some modules like PMU registers IRQs for each possible vcpus during init time. Therefore, a valid entry of the MADT GICC should be present for all possible vcpus. 4. Refactoring related to DT/OF is also done to align it with the init changes to support vcpu hotplug. Signed-off-by: Salil Mehta <[email protected]> Signed-off-by: Xiongfeng Wang <[email protected]>
1 parent 7d768fa commit 74df87d

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

arch/arm64/kernel/smp.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -524,13 +524,14 @@ static int __init smp_cpu_setup(int cpu)
524524
if (ops->cpu_init(cpu))
525525
return -ENODEV;
526526

527-
set_cpu_possible(cpu, true);
527+
// set_cpu_possible(cpu, true);
528528

529529
return 0;
530530
}
531531

532532
static bool bootcpu_valid __initdata;
533533
static unsigned int cpu_count = 1;
534+
static unsigned int disabled_cpu_count;
534535

535536
#ifdef CONFIG_ACPI
536537
static struct acpi_madt_generic_interrupt cpu_madt_gicc[NR_CPUS];
@@ -549,10 +550,17 @@ struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu)
549550
static void __init
550551
acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
551552
{
553+
unsigned int total_cpu_count = disabled_cpu_count + cpu_count;
552554
u64 hwid = processor->arm_mpidr;
553555

554556
if (!(processor->flags & ACPI_MADT_ENABLED)) {
557+
#ifndef CONFIG_ACPI_HOTPLUG_CPU
555558
pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid);
559+
#else
560+
cpu_madt_gicc[total_cpu_count] = *processor;
561+
set_cpu_possible(total_cpu_count, true);
562+
disabled_cpu_count++;
563+
#endif
556564
return;
557565
}
558566

@@ -561,7 +569,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
561569
return;
562570
}
563571

564-
if (is_mpidr_duplicate(cpu_count, hwid)) {
572+
if (is_mpidr_duplicate(total_cpu_count, hwid)) {
565573
pr_err("duplicate CPU MPIDR 0x%llx in MADT\n", hwid);
566574
return;
567575
}
@@ -582,9 +590,9 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
582590
return;
583591

584592
/* map the logical cpu id to cpu MPIDR */
585-
set_cpu_logical_map(cpu_count, hwid);
593+
set_cpu_logical_map(total_cpu_count, hwid);
586594

587-
cpu_madt_gicc[cpu_count] = *processor;
595+
cpu_madt_gicc[total_cpu_count] = *processor;
588596

589597
/*
590598
* Set-up the ACPI parking protocol cpu entries
@@ -595,7 +603,10 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
595603
* initialize the cpu if the parking protocol is
596604
* the only available enable method).
597605
*/
598-
acpi_set_mailbox_entry(cpu_count, processor);
606+
acpi_set_mailbox_entry(total_cpu_count, processor);
607+
608+
set_cpu_possible(total_cpu_count, true);
609+
set_cpu_present(total_cpu_count, true);
599610

600611
cpu_count++;
601612
}
@@ -629,6 +640,9 @@ static void __init acpi_parse_and_init_cpus(void)
629640
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
630641
acpi_parse_gic_cpu_interface, 0);
631642

643+
pr_debug("possible cpus(%u) present cpus(%u) disabled cpus(%u)\n",
644+
cpu_count+disabled_cpu_count, cpu_count, disabled_cpu_count);
645+
632646
/*
633647
* In ACPI, SMP and CPU NUMA information is provided in separate
634648
* static tables, namely the MADT and the SRAT.
@@ -699,6 +713,9 @@ static void __init of_parse_and_init_cpus(void)
699713
set_cpu_logical_map(cpu_count, hwid);
700714

701715
early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
716+
717+
set_cpu_possible(cpu_count, true);
718+
set_cpu_present(cpu_count, true);
702719
next:
703720
cpu_count++;
704721
}
@@ -783,7 +800,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
783800
if (err)
784801
continue;
785802

786-
set_cpu_present(cpu, true);
803+
// set_cpu_present(cpu, true);
787804
numa_store_cpu_info(cpu);
788805
}
789806
}

0 commit comments

Comments
 (0)