Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

LoongArch: Always enumerate MADT and setup logical-physical CPU mapping

Some drivers want to use cpu_logical_map(), early_cpu_to_node() and some
other CPU mapping APIs, even if we use "nr_cpus=1" to hard limit the CPU
number. This is strongly required for the multi-bridges machines.

Currently, we stop parsing the MADT if the nr_cpus limit is reached, but
to achieve the above goal we should always enumerate the MADT table and
setup logical-physical CPU mapping whether there is a nr_cpus limit.

Rework the MADT enumeration:

1. Define a flag "cpu_enumerated" to distinguish the first enumeration
(cpu_enumerated=0) and the physical hotplug case (cpu_enumerated=1)
for set_processor_mask().

2. If cpu_enumerated=0, stop parsing only when NR_CPUS limit is reached,
so we can setup logical-physical CPU mapping; if cpu_enumerated=1,
stop parsing when nr_cpu_ids limit is reached, so we can avoid some
runtime bugs. Once logical-physical CPU mapping is setup, we will let
cpu_enumerated=1.

3. Use find_first_zero_bit() instead of cpumask_next_zero() to find the
next zero bit (free logical CPU id) in the cpu_present_mask, because
cpumask_next_zero() will stop at nr_cpu_ids.

4. Only touch cpu_possible_mask if cpu_enumerated=0, this is in order to
avoid some potential crashes, because cpu_possible_mask is marked as
__ro_after_init.

5. In prefill_possible_map(), clear cpu_present_mask bits greater than
nr_cpu_ids, in order to avoid a CPU be "present" but not "possible".

Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

+22 -11
+16 -6
arch/loongarch/kernel/acpi.c
··· 57 57 return ioremap_cache(phys, size); 58 58 } 59 59 60 + static int cpu_enumerated = 0; 61 + 60 62 #ifdef CONFIG_SMP 61 63 static int set_processor_mask(u32 id, u32 flags) 62 64 { 63 - 65 + int nr_cpus; 64 66 int cpu, cpuid = id; 65 67 66 - if (num_processors >= nr_cpu_ids) { 67 - pr_warn(PREFIX "nr_cpus/possible_cpus limit of %i reached." 68 - " processor 0x%x ignored.\n", nr_cpu_ids, cpuid); 68 + if (!cpu_enumerated) 69 + nr_cpus = NR_CPUS; 70 + else 71 + nr_cpus = nr_cpu_ids; 72 + 73 + if (num_processors >= nr_cpus) { 74 + pr_warn(PREFIX "nr_cpus limit of %i reached." 75 + " processor 0x%x ignored.\n", nr_cpus, cpuid); 69 76 70 77 return -ENODEV; 71 78 ··· 80 73 if (cpuid == loongson_sysconf.boot_cpu_id) 81 74 cpu = 0; 82 75 else 83 - cpu = cpumask_next_zero(-1, cpu_present_mask); 76 + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); 77 + 78 + if (!cpu_enumerated) 79 + set_cpu_possible(cpu, true); 84 80 85 81 if (flags & ACPI_MADT_ENABLED) { 86 82 num_processors++; 87 - set_cpu_possible(cpu, true); 88 83 set_cpu_present(cpu, true); 89 84 __cpu_number_map[cpuid] = cpu; 90 85 __cpu_logical_map[cpu] = cpuid; ··· 147 138 acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, 148 139 acpi_parse_eio_master, MAX_IO_PICS); 149 140 141 + cpu_enumerated = 1; 150 142 loongson_sysconf.nr_cpus = num_processors; 151 143 } 152 144
+3 -1
arch/loongarch/kernel/setup.c
··· 576 576 577 577 for (i = 0; i < possible; i++) 578 578 set_cpu_possible(i, true); 579 - for (; i < NR_CPUS; i++) 579 + for (; i < NR_CPUS; i++) { 580 + set_cpu_present(i, false); 580 581 set_cpu_possible(i, false); 582 + } 581 583 582 584 set_nr_cpu_ids(possible); 583 585 }
+3 -4
arch/loongarch/kernel/smp.c
··· 271 271 if (cpuid >= nr_cpu_ids) 272 272 continue; 273 273 274 - if (cpuid == loongson_sysconf.boot_cpu_id) { 274 + if (cpuid == loongson_sysconf.boot_cpu_id) 275 275 cpu = 0; 276 - } else { 277 - cpu = cpumask_next_zero(-1, cpu_present_mask); 278 - } 276 + else 277 + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); 279 278 280 279 num_processors++; 281 280 set_cpu_possible(cpu, true);