Here is the first part of cpu topology and cpu-hotplug code for RFC.
In this part of code, MADT is being parsed and the cpu possible map and cpu present map are prefilled.
CPU possible map is equal to the GIC entries in MADT no matter enabled or disabled, and cpu present map limits to the enabled cpu in MADT.
Without this patch set, CPU possible map is equal to the cpus found in FDT, and cpu possible map is the same as cpu present map with no hotplugble cpus.
Boot information with this patch (with --cores=4):
ACPI: GIC (acpi_id[0x0000] gic_id[0x0000] enabled) // MADT was parsed ACPI: GIC (acpi_id[0x0001] gic_id[0x0001] enabled) ACPI: GIC (acpi_id[0x0002] gic_id[0x0002] disabled) ACPI: GIC (acpi_id[0x0003] gic_id[0x0003] disabled) ACPI: GIC (acpi_id[0x0004] gic_id[0x0004] disabled) ACPI: GIC (acpi_id[0x0005] gic_id[0x0005] disabled) ACPI: GIC (acpi_id[0x0006] gic_id[0x0006] disabled) ACPI: GIC (acpi_id[0x0007] gic_id[0x0007] disabled) 2 CPUs available, 8 CPUs total //find 2 enabled cpus which // is the same as MADT described ACPI: GIC Distributor (id[0x0000] address[0x2c001000] gsi_base[0]) // IOAPIC(GIC distributor is also parsed) Using ACPI (MADT) for SMP configuration information SMP: limits to 4 CPUs // the foundation model supports only 4 four cpus SMP: Allowing 4 CPUs, 2 hotplug CPUs // so limits to 4 cpus, and 2 disabled in MADT can be hotpluged PERCPU: Embedded 10 pages/cpu @ffffffc03ffa7000 s11520 r8192 d21248 u40960 [....] CPU1: Booted secondary processor Brought up 2 CPUs SMP: Total of 2 processors activated (400.00 BogoMIPS).
Because only 2 cpus is enabled in MADT, so the system will up 2 cpus in despite of --cores=4.
Next step will prototype cpu topology code for ACPI driver.
This is the RFC version only, will updated and rebased on the new acpi branch.
Hanjun Guo (3): ARM / ACPI: MADT for armv8 foundation model ARM / ACPI: Core functions for MADT parse ARM / ACPI: Prefill cpu possible and present map when boot with MADT
arch/arm64/boot/asl/foundation-v8.acpi/apic.asl | 175 ++++++++------- arch/arm64/include/asm/acpi.h | 3 + arch/arm64/kernel/setup.c | 6 + arch/arm64/kernel/smp.c | 2 + drivers/acpi/plat/arm/boot.c | 261 ++++++++++++++++++++++- drivers/acpi/tables.c | 21 ++ 6 files changed, 374 insertions(+), 94 deletions(-)
Implement the MADT for armv8 foundation model, There are 8 GIC struct entries in MADT, which stands for 8 cpus in the system. since 4 cpus was supported on armv8 foundation model, so I disabled 4 cpus to test the cpu topology and cpu hot-plug.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- arch/arm64/boot/asl/foundation-v8.acpi/apic.asl | 169 +++++++++++------------ 1 file changed, 81 insertions(+), 88 deletions(-)
diff --git a/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl b/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl index b301712..60d1f56 100644 --- a/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl +++ b/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl @@ -8,126 +8,119 @@ */
[0004] Signature : "APIC" -[0004] Table Length : 000000F6 -[0001] Revision : 01 -[0001] Checksum : B0 +[0004] Table Length : 000000F6 // should be updated when table finished? +[0001] Revision : 03 +[0001] Checksum : B0 // update it too? [0006] Oem ID : "LINARO" [0008] Oem Table ID : "FOUNDATI" [0004] Oem Revision : 00000001 [0004] Asl Compiler ID : "INTL" [0004] Asl Compiler Revision : 20110623
-[0004] Local Apic Address : 00000000 +[0004] Local Apic Address : 2C002000 [0004] Flags (decoded below) : 00000001 - PC-AT Compatibility : 1 + PC-AT Compatibility : 0
-[0001] Subtable Type : 00 [Processor Local APIC] -[0001] Length : 08 -[0001] Processor ID : 00 -[0001] Local Apic ID : 00 +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 +[0002] Reserved : 0000 +[0004] Local GIC Hardware ID : 00000000 // should this value be equal to FDT provided? +[0004] Processor UID : 00000000 [0004] Flags (decoded below) : 00000001 Processor Enabled : 1 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000 // this is the foundation model's GIC address
-[0001] Subtable Type : 01 [I/O APIC] -[0001] Length : 0C -[0001] I/O Apic ID : 01 -[0001] Reserved : 00 -[0004] Address : 00000000 -[0004] Interrupt : 00000000 - -[0001] Subtable Type : 02 [Interrupt Source Override] -[0001] Length : 0A -[0001] Bus : 00 -[0001] Source : 00 -[0004] Interrupt : 00000000 -[0002] Flags (decoded below) : 0000 - Polarity : 0 - Trigger Mode : 0 - -[0001] Subtable Type : 03 [NMI Source] -[0001] Length : 08 -[0002] Flags (decoded below) : 000D - Polarity : 1 - Trigger Mode : 3 -[0004] Interrupt : 00000001 - -[0001] Subtable Type : 04 [Local APIC NMI] -[0001] Length : 06 -[0001] Processor ID : 00 -[0002] Flags (decoded below) : 0005 - Polarity : 1 - Trigger Mode : 1 -[0001] Interrupt Input LINT : 01 - -[0001] Subtable Type : 05 [Local APIC Address Override] -[0001] Length : 0C +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 [0002] Reserved : 0000 -[0008] APIC Address : 0000000000000000 - -[0001] Subtable Type : 06 [I/O SAPIC] -[0001] Length : 10 -[0001] I/O Sapic ID : 00 -[0001] Reserved : 00 -[0004] Interrupt Base : 00000000 -[0008] Address : 0000000000000000 - -[0001] Subtable Type : 07 [Local SAPIC] -[0001] Length : 16 -[0001] Processor ID : 00 -[0001] Local Sapic ID : 00 -[0001] Local Sapic EID : 00 -[0003] Reserved : 000000 +[0004] Local GIC Hardware ID : 00000001 +[0004] Processor UID : 00000001 [0004] Flags (decoded below) : 00000001 Processor Enabled : 1 -[0004] Processor UID : 00000000 -[0006] Processor UID String : "\CPU0" +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000
-[0001] Subtable Type : 08 [Platform Interrupt Sources] -[0001] Length : 10 -[0002] Flags (decoded below) : 0005 - Polarity : 1 - Trigger Mode : 1 -[0001] InterruptType : 00 -[0001] Processor ID : 00 -[0001] Processor EID : 00 -[0001] I/O Sapic Vector : 00 -[0004] Interrupt : 00000001 +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 +[0002] Reserved : 0000 +[0004] Local GIC Hardware ID : 00000002 +[0004] Processor UID : 00000002 [0004] Flags (decoded below) : 00000001 - CPEI Override : 1 + Processor Enabled : 1 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000
-[0001] Subtable Type : 09 [Processor Local x2APIC] -[0001] Length : 10 +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 [0002] Reserved : 0000 -[0004] Processor x2Apic ID : 00000000 +[0004] Local GIC Hardware ID : 00000003 +[0004] Processor UID : 00000003 [0004] Flags (decoded below) : 00000001 Processor Enabled : 1 -[0004] Processor UID : 00000000 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000
-[0001] Subtable Type : 0A [Local x2APIC NMI] -[0001] Length : 0C -[0002] Flags (decoded below) : 0005 - Polarity : 1 - Trigger Mode : 1 -[0004] Processor UID : 00000000 -[0001] Interrupt Input LINT : 00 -[0003] Reserved : 000000 +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 +[0002] Reserved : 0000 +[0004] Local GIC Hardware ID : 00000004 +[0004] Processor UID : 00000004 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000
[0001] Subtable Type : 0B [Generic Interrupt Controller] [0001] Length : 28 [0002] Reserved : 0000 -[0004] Local GIC Hardware ID : 00000000 -[0004] Processor UID : 00000000 -[0004] Flags (decoded below) : 00000001 - Processor Enabled : 1 +[0004] Local GIC Hardware ID : 00000005 +[0004] Processor UID : 00000005 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000 + +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 +[0002] Reserved : 0000 +[0004] Local GIC Hardware ID : 00000006 +[0004] Processor UID : 00000006 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 +[0004] Parking Protocol Version : 00000000 +[0004] Performance Interrupt : 00000000 +[0008] Parked Address : 0000000000000000 +[0008] Base Address : 000000002C002000 + +[0001] Subtable Type : 0B [Generic Interrupt Controller] +[0001] Length : 28 +[0002] Reserved : 0000 +[0004] Local GIC Hardware ID : 00000007 +[0004] Processor UID : 00000007 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 [0004] Parking Protocol Version : 00000000 [0004] Performance Interrupt : 00000000 [0008] Parked Address : 0000000000000000 -[0008] Base Address : 0000000000000000 +[0008] Base Address : 000000002C002000
[0001] Subtable Type : 0C [Generic Interrupt Distributor] [0001] Length : 18 [0002] Reserved : 0000 [0004] Local GIC Hardware ID : 00000000 -[0008] Base Address : 0000000000000000 +[0008] Base Address : 000000002C001000 [0004] Interrupt Base : 00000000 [0004] Reserved : 00000000
On 06/27/2013 05:18 AM, Hanjun Guo wrote:
Implement the MADT for armv8 foundation model, There are 8 GIC struct entries in MADT, which stands for 8 cpus in the system. since 4 cpus was supported on armv8 foundation model, so I disabled 4 cpus to test the cpu topology and cpu hot-plug.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org
Cool! One more table down... :)
On 2013-6-28 4:20, Al Stone wrote:
On 06/27/2013 05:18 AM, Hanjun Guo wrote:
Implement the MADT for armv8 foundation model, There are 8 GIC struct entries in MADT, which stands for 8 cpus in the system. since 4 cpus was supported on armv8 foundation model, so I disabled 4 cpus to test the cpu topology and cpu hot-plug.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org
Cool! One more table down... :)
:) Next step will be the SRAT and SLIT.
Implement core functions for GIC and GIC distributor entries in MADT, after this patch, we can parse MADT for ARM now. here is the boot information for MADT parse:
enter early_acpi_boot_init enter acpi_boot_init ACPI: GIC (acpi_id[0x0000] gic_id[0x0000] enabled) ACPI: GIC (acpi_id[0x0001] gic_id[0x0001] enabled) ACPI: GIC (acpi_id[0x0002] gic_id[0x0002] enabled) ACPI: GIC (acpi_id[0x0003] gic_id[0x0003] enabled) ACPI: GIC (acpi_id[0x0004] gic_id[0x0004] disabled) ACPI: GIC (acpi_id[0x0005] gic_id[0x0005] disabled) ACPI: GIC (acpi_id[0x0006] gic_id[0x0006] disabled) ACPI: GIC (acpi_id[0x0007] gic_id[0x0007] disabled) ACPI: GIC Distributor (id[0x0000] address[0x2c001000] gsi_base[0]) Using ACPI (MADT) for SMP configuration information PERCPU: Embedded 10 pages/cpu @ffffffc03ffa7000 s11520 r8192 d21248 u40960
NOTE: Parse GIC distributor for irq system is not implemented, should fix it in the future.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- arch/arm64/kernel/setup.c | 4 + drivers/acpi/plat/arm/boot.c | 165 +++++++++++++++++++++++++++++++++++++++++- drivers/acpi/tables.c | 21 ++++++ 3 files changed, 188 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index cb5a299..7e37ba0 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -299,6 +299,10 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif + +#ifdef CONFIG_ACPI + acpi_boot_init(); +#endif }
static int __init arm64_device_init(void) diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index e62d167..3a27232 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -51,6 +51,10 @@ u32 acpi_rsdt_forced; int acpi_disabled; EXPORT_SYMBOL(acpi_disabled);
+/* TODO: should be moved to a head file */ +#define MAX_LOCAL_APIC 256 +#define MAX_IO_APICS 64 + #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) @@ -70,6 +74,7 @@ int acpi_sci_override_gsi __initdata; int acpi_skip_timer_override __initdata; int acpi_use_timer_override __initdata; int acpi_fix_pin2_polarity __initdata; +static u64 acpi_lapic_addr __initdata;
struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP from FDT */
@@ -117,6 +122,73 @@ void __init __acpi_unmap_table(char *map, unsigned long size) return; }
+static int __init acpi_parse_madt(struct acpi_table_header *table) +{ + struct acpi_table_madt *madt = NULL; + + madt = (struct acpi_table_madt *)table; + if (!madt) { + printk(KERN_WARNING PREFIX "Unable to map MADT\n"); + return -ENODEV; + } + + if (madt->address) { + acpi_lapic_addr = (u64) madt->address; + + printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n", + madt->address); + } + + return 0; +} + +static void __cpuinit acpi_register_gic(int id, u8 enabled) +{ + return; +} + +static int __init +acpi_parse_gic(struct acpi_subtable_header * header, const unsigned long end) +{ + struct acpi_madt_generic_interrupt *processor = NULL; + + processor = (struct acpi_madt_generic_interrupt *)header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* + * We need to register disabled CPU as well to permit + * counting disabled CPUs. This allows us to size + * cpus_possible_map more accurately, to permit + * to not preallocating memory for all NR_CPUS + * when we use CPU hotplug. + */ + acpi_register_gic(processor->gic_id, /* APIC ID */ + processor->flags & ACPI_MADT_ENABLED); + + return 0; +} + +static int __init +acpi_parse_gic_distributor(struct acpi_subtable_header * header, const unsigned long end) +{ + struct acpi_madt_generic_distributor *distributor = NULL; + + distributor = (struct acpi_madt_generic_distributor *)header; + + if (BAD_MADT_ENTRY(distributor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + /* TODO: handle with the base_address and irq_base for irq system */ + + return 0; +} + /* * acpi_pic_sci_set_trigger() * @@ -227,9 +299,9 @@ void __init acpi_set_irq_model_pic(void) acpi_ioapic = 0; }
-void __init acpi_set_irq_model_ioapic(void) +void __init acpi_set_irq_model_gic(void) { - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_model = ACPI_IRQ_MODEL_GIC; __acpi_register_gsi = acpi_register_gsi_ioapic; acpi_ioapic = 1; } @@ -437,17 +509,106 @@ late_initcall(hpet_insert_resource); #define acpi_parse_hpet NULL #endif
+static int __init acpi_parse_madt_lapic_entries(void) +{ + int count; + + /* + * do a partial walk of MADT to determine how many CPUs + * we have including disabled CPUs + */ + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, + acpi_parse_gic, MAX_LOCAL_APIC); + + if (!count) { + printk(KERN_ERR PREFIX "No LAPIC entries present\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return -ENODEV; + } else if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); + /* TBD: Cleanup to allow fallback to MPS */ + return count; + } + + return 0; +} + static int __init acpi_parse_fadt(struct acpi_table_header *table) { return 0; }
+/* + * Parse IOAPIC related entries in MADT + * returns 0 on success, < 0 on error + */ +static int __init acpi_parse_madt_ioapic_entries(void) +{ + int count; + + /* + * ACPI interpreter is required to complete interrupt setup, + * so if it is off, don't enumerate the io-apics with ACPI. + * If MPS is present, it will handle them, + * otherwise the system will stay in PIC mode + */ + if (acpi_disabled || acpi_noirq) + return -ENODEV; + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, + acpi_parse_gic_distributor, MAX_IO_APICS); + + if (!count) { + printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); + return -ENODEV; + } else if (count < 0) { + printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); + return count; + } + + return 0; +} + static void __init early_acpi_process_madt(void) { + /* should I introduce CONFIG_ARM_LOCAL_APIC like x86 does? */ + acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt); }
static void __init acpi_process_madt(void) { + /* should I introduce CONFIG_ARM_LOCAL_APIC like x86 does? */ + int error; + + if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) { + + /* + * Parse MADT LAPIC entries + */ + error = acpi_parse_madt_lapic_entries(); + if (!error) { + acpi_lapic = 1; + + /* + * Parse MADT IO-APIC entries + */ + error = acpi_parse_madt_ioapic_entries(); + if (!error) + acpi_set_irq_model_gic(); + } + } + + /* + * ACPI supports both logical (e.g. Hyper-Threading) and physical + * processors, where MPS only supports physical. + */ + if (acpi_lapic && acpi_ioapic) + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration " + "information\n"); + else if (acpi_lapic) + printk(KERN_INFO "Using ACPI for processor (LAPIC) " + "configuration information\n"); + return; }
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index d67a1fe..55e5198 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -191,6 +191,27 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break;
+ case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + { + struct acpi_madt_generic_interrupt *p = + (struct acpi_madt_generic_interrupt *)header; + printk(KERN_INFO PREFIX + "GIC (acpi_id[0x%04x] gic_id[0x%04x] %s)\n", + p->uid, p->gic_id, + (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); + } + break; + + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + { + struct acpi_madt_generic_distributor *p = + (struct acpi_madt_generic_distributor *)header; + printk(KERN_INFO PREFIX + "GIC Distributor (id[0x%04x] address[0x%08x] gsi_base[%d])\n", + p->gic_id, p->base_address, p->global_irq_base); + } + break; + default: printk(KERN_WARNING PREFIX "Found unsupported MADT entry (type = 0x%x)\n",
When boot the kernel with MADT, the cpu possible and present map should be prefilled for cpu topology and cpu hot-plug.
The logic cpu id maps to GIC id is also implemented, then we can use it for ACPI driver for cpu hot-plug.
I modified the APIC.asl because only 4 cpus supported on armv8 foundation model, so limit the available cpus to 2 for test purpose.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- arch/arm64/boot/asl/foundation-v8.acpi/apic.asl | 8 +- arch/arm64/include/asm/acpi.h | 3 + arch/arm64/kernel/setup.c | 2 + arch/arm64/kernel/smp.c | 2 + drivers/acpi/plat/arm/boot.c | 98 ++++++++++++++++++++++- 5 files changed, 107 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl b/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl index 60d1f56..c674628 100644 --- a/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl +++ b/arch/arm64/boot/asl/foundation-v8.acpi/apic.asl @@ -50,8 +50,8 @@ [0002] Reserved : 0000 [0004] Local GIC Hardware ID : 00000002 [0004] Processor UID : 00000002 -[0004] Flags (decoded below) : 00000001 - Processor Enabled : 1 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 [0004] Parking Protocol Version : 00000000 [0004] Performance Interrupt : 00000000 [0008] Parked Address : 0000000000000000 @@ -62,8 +62,8 @@ [0002] Reserved : 0000 [0004] Local GIC Hardware ID : 00000003 [0004] Processor UID : 00000003 -[0004] Flags (decoded below) : 00000001 - Processor Enabled : 1 +[0004] Flags (decoded below) : 00000000 + Processor Enabled : 0 [0004] Parking Protocol Version : 00000000 [0004] Performance Interrupt : 00000000 [0008] Parked Address : 0000000000000000 diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 605478e..a72012b 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -73,6 +73,8 @@ extern int acpi_disabled; extern int acpi_noirq; extern int acpi_pci_disabled; extern int acpi_strict; +extern volatile int arm_cpu_to_gicid[NR_CPUS]; +extern int boot_cpu_gic_id;
struct acpi_arm_root { phys_addr_t phys_address; @@ -83,6 +85,7 @@ extern struct acpi_arm_root acpi_arm_rsdp_info; /* Low-level suspend routine. */ extern int acpi_suspend_lowlevel(void);
+extern void prefill_possible_map(void); /* Physical address to resume after wakeup */ /* BOZO: was... #define acpi_wakeup_address ((unsigned long)(real_mode_header->wakeup_start)) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 7e37ba0..3344c77 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -301,7 +301,9 @@ void __init setup_arch(char **cmdline_p) #endif
#ifdef CONFIG_ACPI + boot_cpu_gic_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; acpi_boot_init(); + prefill_possible_map(); #endif }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5d54e37..fe4ed77 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -418,7 +418,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (err) continue;
+#ifndef CONFIG_ACPI set_cpu_present(cpu, true); +#endif max_cpus--; } } diff --git a/drivers/acpi/plat/arm/boot.c b/drivers/acpi/plat/arm/boot.c index 3a27232..d2fa164 100644 --- a/drivers/acpi/plat/arm/boot.c +++ b/drivers/acpi/plat/arm/boot.c @@ -47,10 +47,15 @@ #include <asm/acpi.h>
static int __initdata acpi_force; +static int available_cpus __initdata; u32 acpi_rsdt_forced; int acpi_disabled; EXPORT_SYMBOL(acpi_disabled);
+/* logical CPU number maps to GIC id */ +volatile int arm_cpu_to_gicid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 }; +int boot_cpu_gic_id = -1; + /* TODO: should be moved to a head file */ #define MAX_LOCAL_APIC 256 #define MAX_IO_APICS 64 @@ -144,7 +149,30 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
static void __cpuinit acpi_register_gic(int id, u8 enabled) { - return; + int cpu; + + total_cpus++; + if (!enabled) + return; + + available_cpus++; + + /* allocate a logic cpu id for the new comer + * TODO: do sth more for the boot cpu + */ + if (boot_cpu_gic_id == id) { + /* + * boot_cpu_init() already hold bit 0 in cpu_present_mask + * for BSP. + */ + cpu = 0; + } else { + cpu = cpumask_next_zero(-1, cpu_present_mask); + } + + /* map the logic cpu id to APIC id */ + arm_cpu_to_gicid[cpu] = id; + set_cpu_present(cpu, true); }
static int __init @@ -306,6 +334,61 @@ void __init acpi_set_irq_model_gic(void) acpi_ioapic = 1; }
+static int __initdata setup_possible_cpus = -1; +static int __init _setup_possible_cpus(char *str) +{ + get_option(&str, &setup_possible_cpus); + return 0; +} +early_param("possible_cpus", _setup_possible_cpus); + +/* + * cpu_possible_mask should be static, it cannot change as cpu's + * are onlined, or offlined. The reason is per-cpu data-structures + * are allocated by some modules at init time, and dont expect to + * do this dynamically on cpu arrival/departure. + * cpu_present_mask on the other hand can change dynamically. + * In case when cpu_hotplug is not compiled, then we resort to current + * behaviour, which is cpu_possible == cpu_present. + * - Ashok Raj + * + * Three ways to find out the number of additional hotplug CPUs: + * - If the BIOS specified disabled CPUs in ACPI/mptables use that. + * - The user can overwrite it with possible_cpus=NUM + * - Otherwise don't reserve additional CPUs. + * We do this because additional CPUs waste a lot of memory. + * -AK + */ +__init void prefill_possible_map(void) +{ + int i; + int possible, disabled_cpus; + + disabled_cpus = total_cpus - available_cpus; + + if (setup_possible_cpus == -1) { + if (disabled_cpus > 0) + setup_possible_cpus = disabled_cpus; + else + setup_possible_cpus = 0; + } + + possible = available_cpus + setup_possible_cpus; + + printk(KERN_INFO "SMP: limits to %d CPUs\n", nr_cpu_ids); + /* + * --cores=4 lets nr_cpu_ids=4, so we can't get possible map correctly + */ + if (possible > nr_cpu_ids) + possible = nr_cpu_ids; + + printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n", + possible, max((possible - available_cpus), 0)); + + for (i = 0; i < possible; i++) + set_cpu_possible(i, true); +} + /* * ACPI based hotplug support for CPU */ @@ -530,6 +613,18 @@ static int __init acpi_parse_madt_lapic_entries(void) return count; }
+#ifdef CONFIG_SMP + if (available_cpus == 0) { + printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); + /* FIXME: should be the real GIC id read from hardware */ + arm_cpu_to_gicid[available_cpus] = 0; + available_cpus = 1; /* We've got at least one of these */ + } +#endif + /* Make boot-up look pretty */ + printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, + total_cpus); + return 0; }
@@ -718,7 +813,6 @@ void __init acpi_arm_blob_relocate(void) * bit of fixup work on the offsets to turn them into kernel * virtual addresses so we can pass them on for later use. */ - void __init acpi_boot_table_init(void) { /*
Hi Hanjun,
This looks like a good start for cpu support.
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
Thanks
Graeme
On 06/27/2013 12:18 PM, Hanjun Guo wrote:
Here is the first part of cpu topology and cpu-hotplug code for RFC.
In this part of code, MADT is being parsed and the cpu possible map and cpu present map are prefilled.
CPU possible map is equal to the GIC entries in MADT no matter enabled or disabled, and cpu present map limits to the enabled cpu in MADT.
Without this patch set, CPU possible map is equal to the cpus found in FDT, and cpu possible map is the same as cpu present map with no hotplugble cpus.
Boot information with this patch (with --cores=4):
ACPI: GIC (acpi_id[0x0000] gic_id[0x0000] enabled) // MADT was parsed ACPI: GIC (acpi_id[0x0001] gic_id[0x0001] enabled) ACPI: GIC (acpi_id[0x0002] gic_id[0x0002] disabled) ACPI: GIC (acpi_id[0x0003] gic_id[0x0003] disabled) ACPI: GIC (acpi_id[0x0004] gic_id[0x0004] disabled) ACPI: GIC (acpi_id[0x0005] gic_id[0x0005] disabled) ACPI: GIC (acpi_id[0x0006] gic_id[0x0006] disabled) ACPI: GIC (acpi_id[0x0007] gic_id[0x0007] disabled) 2 CPUs available, 8 CPUs total //find 2 enabled cpus which // is the same as MADT described ACPI: GIC Distributor (id[0x0000] address[0x2c001000] gsi_base[0]) // IOAPIC(GIC distributor is also parsed) Using ACPI (MADT) for SMP configuration information SMP: limits to 4 CPUs // the foundation model supports only 4 four cpus SMP: Allowing 4 CPUs, 2 hotplug CPUs // so limits to 4 cpus, and 2 disabled in MADT can be hotpluged PERCPU: Embedded 10 pages/cpu @ffffffc03ffa7000 s11520 r8192 d21248 u40960 [....] CPU1: Booted secondary processor Brought up 2 CPUs SMP: Total of 2 processors activated (400.00 BogoMIPS).
Because only 2 cpus is enabled in MADT, so the system will up 2 cpus in despite of --cores=4.
Next step will prototype cpu topology code for ACPI driver.
This is the RFC version only, will updated and rebased on the new acpi branch.
Hanjun Guo (3): ARM / ACPI: MADT for armv8 foundation model ARM / ACPI: Core functions for MADT parse ARM / ACPI: Prefill cpu possible and present map when boot with MADT
arch/arm64/boot/asl/foundation-v8.acpi/apic.asl | 175 ++++++++------- arch/arm64/include/asm/acpi.h | 3 + arch/arm64/kernel/setup.c | 6 + arch/arm64/kernel/smp.c | 2 + drivers/acpi/plat/arm/boot.c | 261 ++++++++++++++++++++++- drivers/acpi/tables.c | 21 ++ 6 files changed, 374 insertions(+), 94 deletions(-)
On 06/27/2013 02:07 PM, Graeme Gregory wrote:
Hi Hanjun,
This looks like a good start for cpu support.
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
Thanks
Graeme
Which do we want to give preference to? You're right -- ARM does not use the term "APIC." On the other hand, the ACPI spec does, even with the reduced HW profile. My gut reaction is to be consistent with the kernel source, even if it does say APIC...
On 06/27/2013 12:18 PM, Hanjun Guo wrote:
Here is the first part of cpu topology and cpu-hotplug code for RFC.
In this part of code, MADT is being parsed and the cpu possible map and cpu present map are prefilled.
CPU possible map is equal to the GIC entries in MADT no matter enabled or disabled, and cpu present map limits to the enabled cpu in MADT.
Without this patch set, CPU possible map is equal to the cpus found in FDT, and cpu possible map is the same as cpu present map with no hotplugble cpus.
Boot information with this patch (with --cores=4):
ACPI: GIC (acpi_id[0x0000] gic_id[0x0000] enabled) // MADT was parsed ACPI: GIC (acpi_id[0x0001] gic_id[0x0001] enabled) ACPI: GIC (acpi_id[0x0002] gic_id[0x0002] disabled) ACPI: GIC (acpi_id[0x0003] gic_id[0x0003] disabled) ACPI: GIC (acpi_id[0x0004] gic_id[0x0004] disabled) ACPI: GIC (acpi_id[0x0005] gic_id[0x0005] disabled) ACPI: GIC (acpi_id[0x0006] gic_id[0x0006] disabled) ACPI: GIC (acpi_id[0x0007] gic_id[0x0007] disabled) 2 CPUs available, 8 CPUs total //find 2 enabled cpus which // is the same as MADT described ACPI: GIC Distributor (id[0x0000] address[0x2c001000] gsi_base[0]) // IOAPIC(GIC distributor is also parsed) Using ACPI (MADT) for SMP configuration information SMP: limits to 4 CPUs // the foundation model supports only 4 four cpus SMP: Allowing 4 CPUs, 2 hotplug CPUs // so limits to 4 cpus, and 2 disabled in MADT can be hotpluged PERCPU: Embedded 10 pages/cpu @ffffffc03ffa7000 s11520 r8192 d21248 u40960 [....] CPU1: Booted secondary processor Brought up 2 CPUs SMP: Total of 2 processors activated (400.00 BogoMIPS).
Because only 2 cpus is enabled in MADT, so the system will up 2 cpus in despite of --cores=4.
Next step will prototype cpu topology code for ACPI driver.
This is the RFC version only, will updated and rebased on the new acpi branch.
Hanjun Guo (3): ARM / ACPI: MADT for armv8 foundation model ARM / ACPI: Core functions for MADT parse ARM / ACPI: Prefill cpu possible and present map when boot with MADT
arch/arm64/boot/asl/foundation-v8.acpi/apic.asl | 175 ++++++++------- arch/arm64/include/asm/acpi.h | 3 + arch/arm64/kernel/setup.c | 6 + arch/arm64/kernel/smp.c | 2 + drivers/acpi/plat/arm/boot.c | 261 ++++++++++++++++++++++- drivers/acpi/tables.c | 21 ++ 6 files changed, 374 insertions(+), 94 deletions(-)
Linaro-acpi mailing list Linaro-acpi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-acpi
On 2013-6-28 4:29, Al Stone wrote:
On 06/27/2013 02:07 PM, Graeme Gregory wrote:
Hi Hanjun,
This looks like a good start for cpu support.
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
Thanks
Graeme
Which do we want to give preference to? You're right -- ARM does not use the term "APIC." On the other hand, the ACPI spec does, even with the reduced HW profile. My gut reaction is to be consistent with the kernel source, even if it does say APIC...
do you mean use APIC instead of GIC?
There are acpi_madt_generic_interrupt and acpi_madt_generic_distributor struct in kernel source, and ACPI_MADT_TYPE_GENERIC_INTERRUPT macro is also defined, if use "APIC", it will also lead to confusion.
Thanks Hanjun
On 2013-6-28 4:07, Graeme Gregory wrote:
Hi Hanjun,
This looks like a good start for cpu support.
yes, this is also is a start for APICs (LEG-465 card).
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
When I hack the code, I also have this question in my mind. APIC is not the correct terminology on arm, It is GIC and GIC distributor on arm, something like local APIC and IOAPIC on x86.
I think we should keep things consistent in the code, either GIC or APIC, I would prefer GIC, what's your opinion, Al, Graeme?
Thanks Hanjun
On 28 June 2013 06:41, Hanjun Guo hanjun.guo@linaro.org wrote:
On 2013-6-28 4:07, Graeme Gregory wrote:
Hi Hanjun,
This looks like a good start for cpu support.
yes, this is also is a start for APICs (LEG-465 card).
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
When I hack the code, I also have this question in my mind. APIC is not the correct terminology on arm, It is GIC and GIC distributor on arm, something like local APIC and IOAPIC on x86.
I think we should keep things consistent in the code, either GIC or APIC, I would prefer GIC, what's your opinion, Al, Graeme?
I would stay consistent to ACPI in the ACPI code, to avoid confusion and bad reaction from the upstream maintainers... they are 99.999999% from x86 so they will reject any terminology change. And it would cause confusion.
I would anyway add comments here and there as "// APIC = GIC on ARM"
that's just my 2c :-)
/Andrea
Thanks Hanjun
On 2013-6-28 17:35, Andrea Gallo wrote:
On 28 June 2013 06:41, Hanjun Guo hanjun.guo@linaro.org wrote:
On 2013-6-28 4:07, Graeme Gregory wrote:
Hi Hanjun,
This looks like a good start for cpu support.
yes, this is also is a start for APICs (LEG-465 card).
I have a query about the terminology, a lot of your comments still refer to APIC is this correct terminology on arm?
When I hack the code, I also have this question in my mind. APIC is not the correct terminology on arm, It is GIC and GIC distributor on arm, something like local APIC and IOAPIC on x86.
I think we should keep things consistent in the code, either GIC or APIC, I would prefer GIC, what's your opinion, Al, Graeme?
I would stay consistent to ACPI in the ACPI code, to avoid confusion and bad reaction from the upstream maintainers... they are 99.999999% from x86 so they will reject any terminology change. And it would cause confusion.
I would anyway add comments here and there as "// APIC = GIC on ARM"
Hi Andrea,
Good point, Thanks for the wonderful advice! I think Al also have the same opinion, I will update my patch set.
Thanks Hanjun
that's just my 2c :-)
/Andrea
Thanks Hanjun