Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1220702 > unrolled thread
| Started by | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| First post | 2015-09-08 13:10 +0200 |
| Last post | 2015-09-09 11:40 +0200 |
| Articles | 19 — 6 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH] x86, arm64, acpi: Handle lapic/x2apic entries in MADT Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-08 13:10 +0200
[PATCH 1/4] acpi: rename acpi_table_parse_entries Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-08 13:10 +0200
[PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-08 13:10 +0200
Re: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs Marc Zyngier <marc.zyngier@arm.com> - 2015-09-08 18:30 +0200
Re: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs Al Stone <ahs3@redhat.com> - 2015-09-09 00:50 +0200
RE: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs "Anaczkowski, Lukasz" <lukasz.anaczkowski@intel.com> - 2015-09-09 09:10 +0200
[PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 11:40 +0200
[PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 11:40 +0200
Re: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2015-09-09 16:00 +0200
RE: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order "Anaczkowski, Lukasz" <lukasz.anaczkowski@intel.com> - 2015-09-09 16:40 +0200
Re: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - 2015-09-09 17:50 +0200
Re: [PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers Marc Zyngier <marc.zyngier@arm.com> - 2015-09-09 12:50 +0200
[PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 15:50 +0200
[PATCH v4 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 15:50 +0200
[PATCH v4 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 15:50 +0200
Re: [PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs "Rafael J. Wysocki" <rjw@rjwysocki.net> - 2015-09-09 22:20 +0200
Re: [PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs "Rafael J. Wysocki" <rjw@rjwysocki.net> - 2015-09-19 00:20 +0200
Re: [PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 15:50 +0200
[PATCH 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> - 2015-09-09 11:40 +0200
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-08 13:10 +0200 |
| Subject | Re: [PATCH] x86, arm64, acpi: Handle lapic/x2apic entries in MADT |
| Message-ID | <q6oWK-2qG-7@gated-at.bofh.it> |
Hi Lorenzo, Ingo and Tomasz, I'm sending revisited set of patches with all your comments addressed (I hope), thus I'll skip replying to single each of them. Thanks in advance for comments. Cheers, Lukasz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-08 13:10 +0200 |
| Subject | [PATCH 1/4] acpi: rename acpi_table_parse_entries |
| Message-ID | <q6oWK-2qG-11@gated-at.bofh.it> |
| In reply to | #1220702 |
ACPI subtable parsing needs to be extended to allow two or more
handlers to be run in the same ACPI table walk.
This is needed to fix CPU enumeration when APIC/X2APIC entries
are interleaved.
Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
---
drivers/acpi/tables.c | 13 ++++++++++++-
include/linux/acpi.h | 4 ++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 2e19189..aa8bcc6 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -277,7 +277,7 @@ acpi_parse_entries(char *id, unsigned long table_size,
}
int __init
-acpi_table_parse_entries(char *id,
+acpi_table_parse_entries_array(char *id,
unsigned long table_size,
int entry_id,
acpi_tbl_entry_handler handler,
@@ -311,6 +311,17 @@ acpi_table_parse_entries(char *id,
}
int __init
+acpi_table_parse_entries(char *id,
+ unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries)
+{
+ return acpi_table_parse_entries_array(id, table_size, entry_id,
+ handler, max_entries);
+}
+
+int __init
acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler, unsigned int max_entries)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d2445fa..07fd1d1 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -153,6 +153,10 @@ int __init acpi_table_parse_entries(char *id, unsigned long table_size,
int entry_id,
acpi_tbl_entry_handler handler,
unsigned int max_entries);
+int __init acpi_table_parse_entries_array(char *id, unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries);
int acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler,
unsigned int max_entries);
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-08 13:10 +0200 |
| Subject | [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6oWK-2qG-9@gated-at.bofh.it> |
| In reply to | #1220702 |
This series of patches attempts to fix how CPUs are enumerated by kernel when there's more than 255 of them on single processor. In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements specified in ACPI spec. Without this patches, kernel then would first enumerate BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence of that could be performance penalties due to wrong L2 cache sharing. More details in patch 4/4. Also, simpler approach has been considered, which did not required ACPI parsing interface changes, however it failed to meet requirements. More details can be found here: https://lkml.org/lkml/2015/9/7/285 I've compiled this code successfully for x86/arm64 and verified it on x86. I'd really appreciate if someone could give it a try on arm64. Although interface has changed, semantics stayed the same, thus runtime issues should not appear. Please verify, thanks! Lukasz Anaczkowski (4): acpi: rename acpi_table_parse_entries x86, arm64, acpi: Added acpi_subtable_proc acpi: multi proc support x86, acpi: Handle apic/x2apic entries in MADT in correct order arch/x86/kernel/acpi/boot.c | 39 +++++++++++++++++------- drivers/acpi/numa.c | 13 ++++++-- drivers/acpi/tables.c | 73 +++++++++++++++++++++++++++++++++++---------- drivers/irqchip/irq-gic.c | 15 +++++++--- include/linux/acpi.h | 13 ++++++-- 5 files changed, 119 insertions(+), 34 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2015-09-08 18:30 +0200 |
| Subject | Re: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6tWq-16N-11@gated-at.bofh.it> |
| In reply to | #1220705 |
On 08/09/15 12:07, Lukasz Anaczkowski wrote:
> This series of patches attempts to fix how CPUs are enumerated by kernel when
> there's more than 255 of them on single processor.
> In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements
> specified in ACPI spec. Without this patches, kernel then would first enumerate
> BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high
> logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence
> of that could be performance penalties due to wrong L2 cache sharing.
> More details in patch 4/4.
>
> Also, simpler approach has been considered, which did not required ACPI parsing
> interface changes, however it failed to meet requirements. More details can be
> found here: https://lkml.org/lkml/2015/9/7/285
>
> I've compiled this code successfully for x86/arm64 and verified it on x86. I'd
> really appreciate if someone could give it a try on arm64.
> Although interface has changed, semantics stayed the same, thus runtime issues
> should not appear. Please verify, thanks!
I really don't see why you cannot provide simple helpers that avoids
the churn on code that doesn't require this new feature. It just makes
the code hard(er) to read, and unnecessarily convoluted. ACPI doesn't
need more of that, really.
I've come up with this (on top of your series):
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index f3ccc68..acaa3b4 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -314,15 +314,9 @@ static int __init
acpi_table_parse_srat(enum acpi_srat_type id,
acpi_tbl_entry_handler handler, unsigned int max_entries)
{
- struct acpi_subtable_proc srat_proc;
-
- memset(&srat_proc, 0, sizeof(srat_proc));
- srat_proc.id = id;
- srat_proc.handler = handler;
-
- return acpi_table_parse_entries_array(ACPI_SIG_SRAT,
- sizeof(struct acpi_table_srat),
- &srat_proc, 1, max_entries);
+ return acpi_table_parse_entries(ACPI_SIG_SRAT,
+ sizeof(struct acpi_table_srat), id,
+ handler, max_entries);
}
int __init acpi_numa_init(void)
@@ -341,7 +335,6 @@ int __init acpi_numa_init(void)
acpi_parse_x2apic_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, 0);
-
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity,
NR_NODE_MEMBLKS);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index bc23220..758b334 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -215,7 +215,7 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
/**
- * acpi_parse_entries - for each proc_num find a subtable with proc->id
+ * acpi_parse_entries_array - for each proc_num find a subtable with proc->id
* and run proc->handler on it. Assumption is that there's only
* single handler for particular entry id.
*
@@ -230,8 +230,8 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
* On success returns sum of all matching entries for all proc handlers.
* Oterwise, -ENODEV or -EINVAL is returned.
*/
-int __init
-acpi_parse_entries(char *id, unsigned long table_size,
+static int __init
+acpi_parse_entries_array(char *id, unsigned long table_size,
struct acpi_table_header *table_header,
struct acpi_subtable_proc *proc, int proc_num,
unsigned int max_entries)
@@ -300,6 +300,20 @@ acpi_parse_entries(char *id, unsigned long table_size,
return count;
}
+int __init acpi_parse_entries(char *id, unsigned long table_size,
+ acpi_tbl_entry_handler handler,
+ struct acpi_table_header *table_header,
+ int entry_id, unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
+
+ return acpi_parse_entries_array(id, table_size, table_header,
+ &proc, 1, max_entries);
+}
+
int __init
acpi_table_parse_entries_array(char *id,
unsigned long table_size,
@@ -326,8 +340,8 @@ acpi_table_parse_entries_array(char *id,
return -ENODEV;
}
- count = acpi_parse_entries(id, table_size, table_header,
- proc, proc_num, max_entries);
+ count = acpi_parse_entries_array(id, table_size, table_header,
+ proc, proc_num, max_entries);
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
@@ -340,17 +354,13 @@ acpi_table_parse_entries(char *id,
acpi_tbl_entry_handler handler,
unsigned int max_entries)
{
- struct acpi_subtable_proc proc[1];
-
- if (!handler)
- return -EINVAL;
-
- memset(proc, 0, sizeof(proc));
- proc[0].id = entry_id;
- proc[0].handler = handler;
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
- return acpi_table_parse_entries_array(id, table_size, proc, 1,
- max_entries);
+ return acpi_table_parse_entries_array(id, table_size, &proc, 1,
+ max_entries);
}
int __init
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 581336c..4dd8826 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1091,16 +1091,12 @@ gic_v2_acpi_init(struct acpi_table_header *table)
{
void __iomem *cpu_base, *dist_base;
int count;
- struct acpi_subtable_proc gic_proc[1];
-
- memset(gic_proc, 0, sizeof(gic_proc));
- gic_proc[0].id = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
- gic_proc[0].handler = gic_acpi_parse_madt_cpu;
/* Collect CPU base addresses */
count = acpi_parse_entries(ACPI_SIG_MADT,
sizeof(struct acpi_table_madt),
- table, gic_proc, 1, 0);
+ gic_acpi_parse_madt_cpu, table,
+ ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
if (count <= 0) {
pr_err("No valid GICC entries exist\n");
return -EINVAL;
@@ -1110,13 +1106,10 @@ gic_v2_acpi_init(struct acpi_table_header *table)
* Find distributor base address. We expect one distributor entry since
* ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
*/
- memset(gic_proc, 0, sizeof(gic_proc));
- gic_proc[0].id = ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR;
- gic_proc[0].handler = gic_acpi_parse_madt_distributor;
-
count = acpi_parse_entries(ACPI_SIG_MADT,
sizeof(struct acpi_table_madt),
- table, gic_proc, 1, 0);
+ gic_acpi_parse_madt_distributor, table,
+ ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
if (count <= 0) {
pr_err("No valid GICD entries exist\n");
return -EINVAL;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 52c8d20..0f6381d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -152,9 +152,9 @@ int acpi_numa_init (void);
int acpi_table_init (void);
int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
int __init acpi_parse_entries(char *id, unsigned long table_size,
- struct acpi_table_header *table_header,
- struct acpi_subtable_proc *proc, int proc_num,
- unsigned int max_entries);
+ acpi_tbl_entry_handler handler,
+ struct acpi_table_header *table_header,
+ int entry_id, unsigned int max_entries);
int __init acpi_table_parse_entries(char *id, unsigned long table_size,
int entry_id,
acpi_tbl_entry_handler handler,
In my view, this makes the change a lot more palatable, and it
can fit in exactly two patches:
1) add the acpi_subtable_proc stuff with the compatibility helpers
2) change arch/x86/kernel/acpi/boot.c to do whatever you want it
to do
It will be a lot easier to review and to verify.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Al Stone <ahs3@redhat.com> |
|---|---|
| Date | 2015-09-09 00:50 +0200 |
| Subject | Re: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6zSa-1bn-13@gated-at.bofh.it> |
| In reply to | #1220959 |
On 09/08/2015 10:27 AM, Marc Zyngier wrote:
> On 08/09/15 12:07, Lukasz Anaczkowski wrote:
>> This series of patches attempts to fix how CPUs are enumerated by kernel when
>> there's more than 255 of them on single processor.
>> In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements
>> specified in ACPI spec. Without this patches, kernel then would first enumerate
>> BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high
>> logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence
>> of that could be performance penalties due to wrong L2 cache sharing.
>> More details in patch 4/4.
>>
>> Also, simpler approach has been considered, which did not required ACPI parsing
>> interface changes, however it failed to meet requirements. More details can be
>> found here: https://lkml.org/lkml/2015/9/7/285
>>
>> I've compiled this code successfully for x86/arm64 and verified it on x86. I'd
>> really appreciate if someone could give it a try on arm64.
>> Although interface has changed, semantics stayed the same, thus runtime issues
>> should not appear. Please verify, thanks!
>
> I really don't see why you cannot provide simple helpers that avoids
> the churn on code that doesn't require this new feature. It just makes
> the code hard(er) to read, and unnecessarily convoluted. ACPI doesn't
> need more of that, really.
>
> I've come up with this (on top of your series):
>
> diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
> index f3ccc68..acaa3b4 100644
> --- a/drivers/acpi/numa.c
> +++ b/drivers/acpi/numa.c
> @@ -314,15 +314,9 @@ static int __init
> acpi_table_parse_srat(enum acpi_srat_type id,
> acpi_tbl_entry_handler handler, unsigned int max_entries)
> {
> - struct acpi_subtable_proc srat_proc;
> -
> - memset(&srat_proc, 0, sizeof(srat_proc));
> - srat_proc.id = id;
> - srat_proc.handler = handler;
> -
> - return acpi_table_parse_entries_array(ACPI_SIG_SRAT,
> - sizeof(struct acpi_table_srat),
> - &srat_proc, 1, max_entries);
> + return acpi_table_parse_entries(ACPI_SIG_SRAT,
> + sizeof(struct acpi_table_srat), id,
> + handler, max_entries);
> }
>
> int __init acpi_numa_init(void)
> @@ -341,7 +335,6 @@ int __init acpi_numa_init(void)
> acpi_parse_x2apic_affinity, 0);
> acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
> acpi_parse_processor_affinity, 0);
> -
> cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
> acpi_parse_memory_affinity,
> NR_NODE_MEMBLKS);
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index bc23220..758b334 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -215,7 +215,7 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
> }
>
> /**
> - * acpi_parse_entries - for each proc_num find a subtable with proc->id
> + * acpi_parse_entries_array - for each proc_num find a subtable with proc->id
> * and run proc->handler on it. Assumption is that there's only
> * single handler for particular entry id.
> *
> @@ -230,8 +230,8 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
> * On success returns sum of all matching entries for all proc handlers.
> * Oterwise, -ENODEV or -EINVAL is returned.
> */
> -int __init
> -acpi_parse_entries(char *id, unsigned long table_size,
> +static int __init
> +acpi_parse_entries_array(char *id, unsigned long table_size,
> struct acpi_table_header *table_header,
> struct acpi_subtable_proc *proc, int proc_num,
> unsigned int max_entries)
> @@ -300,6 +300,20 @@ acpi_parse_entries(char *id, unsigned long table_size,
> return count;
> }
>
> +int __init acpi_parse_entries(char *id, unsigned long table_size,
> + acpi_tbl_entry_handler handler,
> + struct acpi_table_header *table_header,
> + int entry_id, unsigned int max_entries)
> +{
> + struct acpi_subtable_proc proc = {
> + .id = entry_id,
> + .handler = handler,
> + };
> +
> + return acpi_parse_entries_array(id, table_size, table_header,
> + &proc, 1, max_entries);
> +}
> +
> int __init
> acpi_table_parse_entries_array(char *id,
> unsigned long table_size,
> @@ -326,8 +340,8 @@ acpi_table_parse_entries_array(char *id,
> return -ENODEV;
> }
>
> - count = acpi_parse_entries(id, table_size, table_header,
> - proc, proc_num, max_entries);
> + count = acpi_parse_entries_array(id, table_size, table_header,
> + proc, proc_num, max_entries);
>
> early_acpi_os_unmap_memory((char *)table_header, tbl_size);
> return count;
> @@ -340,17 +354,13 @@ acpi_table_parse_entries(char *id,
> acpi_tbl_entry_handler handler,
> unsigned int max_entries)
> {
> - struct acpi_subtable_proc proc[1];
> -
> - if (!handler)
> - return -EINVAL;
> -
> - memset(proc, 0, sizeof(proc));
> - proc[0].id = entry_id;
> - proc[0].handler = handler;
> + struct acpi_subtable_proc proc = {
> + .id = entry_id,
> + .handler = handler,
> + };
>
> - return acpi_table_parse_entries_array(id, table_size, proc, 1,
> - max_entries);
> + return acpi_table_parse_entries_array(id, table_size, &proc, 1,
> + max_entries);
> }
>
> int __init
> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
> index 581336c..4dd8826 100644
> --- a/drivers/irqchip/irq-gic.c
> +++ b/drivers/irqchip/irq-gic.c
> @@ -1091,16 +1091,12 @@ gic_v2_acpi_init(struct acpi_table_header *table)
> {
> void __iomem *cpu_base, *dist_base;
> int count;
> - struct acpi_subtable_proc gic_proc[1];
> -
> - memset(gic_proc, 0, sizeof(gic_proc));
> - gic_proc[0].id = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
> - gic_proc[0].handler = gic_acpi_parse_madt_cpu;
>
> /* Collect CPU base addresses */
> count = acpi_parse_entries(ACPI_SIG_MADT,
> sizeof(struct acpi_table_madt),
> - table, gic_proc, 1, 0);
> + gic_acpi_parse_madt_cpu, table,
> + ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
> if (count <= 0) {
> pr_err("No valid GICC entries exist\n");
> return -EINVAL;
> @@ -1110,13 +1106,10 @@ gic_v2_acpi_init(struct acpi_table_header *table)
> * Find distributor base address. We expect one distributor entry since
> * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
> */
> - memset(gic_proc, 0, sizeof(gic_proc));
> - gic_proc[0].id = ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR;
> - gic_proc[0].handler = gic_acpi_parse_madt_distributor;
> -
> count = acpi_parse_entries(ACPI_SIG_MADT,
> sizeof(struct acpi_table_madt),
> - table, gic_proc, 1, 0);
> + gic_acpi_parse_madt_distributor, table,
> + ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
> if (count <= 0) {
> pr_err("No valid GICD entries exist\n");
> return -EINVAL;
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 52c8d20..0f6381d 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -152,9 +152,9 @@ int acpi_numa_init (void);
> int acpi_table_init (void);
> int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
> int __init acpi_parse_entries(char *id, unsigned long table_size,
> - struct acpi_table_header *table_header,
> - struct acpi_subtable_proc *proc, int proc_num,
> - unsigned int max_entries);
> + acpi_tbl_entry_handler handler,
> + struct acpi_table_header *table_header,
> + int entry_id, unsigned int max_entries);
> int __init acpi_table_parse_entries(char *id, unsigned long table_size,
> int entry_id,
> acpi_tbl_entry_handler handler,
>
> In my view, this makes the change a lot more palatable, and it
> can fit in exactly two patches:
>
> 1) add the acpi_subtable_proc stuff with the compatibility helpers
> 2) change arch/x86/kernel/acpi/boot.c to do whatever you want it
> to do
>
> It will be a lot easier to review and to verify.
>
> Thanks,
>
> M.
>
I have to agree with Marc here. His changes on top of the prior patches
make this much cleaner. The MADT parsing is messy enough as it is without
adding changes needed by only the APIC/X2APIC subtables into the interface
for all MADT parsing.
I'm also still not convinced we have to have the ability to call multiple
callbacks for each entry as we cycle through the MADT entries. I've looked
through the previous comments on these patches and I'm still not getting it;
maybe I'm just being dense (it wouldn't be the first time).
Logically, I see no difference between making two passes through the MADT
subtables, once for each subtable type and noting the info I need, versus
making two callbacks for each subtable, and noting the info I need between
callbacks. If nothing else, my personal opinion is that the former would
be easier to maintain over time since it would be specific to the users of
APIC/X2APIC and not affect other users parsing MADT subtables.
Obviously, though, I'm not the final arbiter of all things ACPI... this is
just my $0.02 worth...
--
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Red Hat, Inc.
ahs3@redhat.com
-----------------------------------
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Anaczkowski, Lukasz" <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 09:10 +0200 |
| Subject | RE: [PATCH 0/4] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6HG2-4db-5@gated-at.bofh.it> |
| In reply to | #1220959 |
From: Marc Zyngier [mailto:marc.zyngier@arm.com] Sent: Tuesday, September 8, 2015 6:28 PM > In my view, this makes the change a lot more palatable, and it can fit in exactly two patches: > > 1) add the acpi_subtable_proc stuff with the compatibility helpers > 2) change arch/x86/kernel/acpi/boot.c to do whatever you want it > to do > It will be a lot easier to review and to verify. Thanks, Marc. Sounds you're right, I'll try to follow KISS rule better next time. Will send updated patches. Cheers, Lukasz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 11:40 +0200 |
| Subject | [PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers |
| Message-ID | <q6K1b-7xZ-7@gated-at.bofh.it> |
| In reply to | #1220959 |
ACPI subtable parsing needs to be extended to allow two or more
handlers to be run in the same ACPI table walk, thus adding
acpi_subtable_proc structure which stores
() ACPI table id
() handler that processes table
() counter how many items has been processed
and passing it to acpi_parse_entries_array() and
acpi_table_parse_entries_array().
This is needed to fix CPU enumeration when APIC/X2APIC entries
are interleaved.
Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
---
drivers/acpi/tables.c | 89 +++++++++++++++++++++++++++++++++++++++++----------
include/linux/acpi.h | 13 ++++++++
2 files changed, 85 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 2e19189..13e5089 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -214,20 +214,37 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
}
+/**
+ * acpi_parse_entries_array - for each proc_num find a subtable with proc->id
+ * and run proc->handler on it. Assumption is that there's only
+ * single handler for particular entry id.
+ *
+ * @id: table id (for debugging purposes)
+ * @table_size: single entry size
+ * @table_header: where does the table start?
+ * @proc: array of acpi_subtable_proc struct containing entry id
+ * and associated handler with it
+ * @proc_num: how big proc is?
+ * @max_entries: how many entries can we process?
+ *
+ * On success returns sum of all matching entries for all proc handlers.
+ * Oterwise, -ENODEV or -EINVAL is returned.
+ */
int __init
-acpi_parse_entries(char *id, unsigned long table_size,
- acpi_tbl_entry_handler handler,
+acpi_parse_entries_array(char *id, unsigned long table_size,
struct acpi_table_header *table_header,
- int entry_id, unsigned int max_entries)
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries)
{
struct acpi_subtable_header *entry;
- int count = 0;
unsigned long table_end;
+ int count = 0;
+ int i;
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!table_size)
@@ -247,20 +264,27 @@ acpi_parse_entries(char *id, unsigned long table_size,
while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
table_end) {
- if (entry->type == entry_id
- && (!max_entries || count < max_entries)) {
- if (handler(entry, table_end))
+ if (max_entries && count >= max_entries)
+ break;
+
+ for (i = 0; i < proc_num; i++) {
+ if (entry->type != proc[i].id)
+ continue;
+ if (!proc->handler || proc[i].handler(entry, table_end))
return -EINVAL;
- count++;
+ proc->count++;
+ break;
}
+ if (i != proc_num)
+ count++;
/*
* If entry->length is 0, break from this loop to avoid
* infinite loop.
*/
if (entry->length == 0) {
- pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
+ pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
return -EINVAL;
}
@@ -270,17 +294,31 @@ acpi_parse_entries(char *id, unsigned long table_size,
if (max_entries && count > max_entries) {
pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
- id, entry_id, count - max_entries, count);
+ id, proc->id, count - max_entries, count);
}
return count;
}
+int __init acpi_parse_entries(char *id, unsigned long table_size,
+ acpi_tbl_entry_handler handler,
+ struct acpi_table_header *table_header,
+ int entry_id, unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ .count = 0,
+ };
+
+ return acpi_parse_entries_array(id, table_size, table_header,
+ &proc, 1, max_entries);
+}
+
int __init
-acpi_table_parse_entries(char *id,
+acpi_table_parse_entries_array(char *id,
unsigned long table_size,
- int entry_id,
- acpi_tbl_entry_handler handler,
+ struct acpi_subtable_proc *proc, int proc_num,
unsigned int max_entries)
{
struct acpi_table_header *table_header = NULL;
@@ -291,7 +329,7 @@ acpi_table_parse_entries(char *id,
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!strncmp(id, ACPI_SIG_MADT, 4))
@@ -303,14 +341,31 @@ acpi_table_parse_entries(char *id,
return -ENODEV;
}
- count = acpi_parse_entries(id, table_size, handler, table_header,
- entry_id, max_entries);
+ count = acpi_parse_entries_array(id, table_size, table_header,
+ proc, proc_num, max_entries);
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
}
int __init
+acpi_table_parse_entries(char *id,
+ unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ .count = 0,
+ };
+
+ return acpi_table_parse_entries_array(id, table_size, &proc, 1,
+ max_entries);
+}
+
+int __init
acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler, unsigned int max_entries)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d2445fa..7a25ef9 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -135,6 +135,12 @@ static inline void acpi_initrd_override(void *data, size_t size)
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
+struct acpi_subtable_proc {
+ int id;
+ acpi_tbl_entry_handler handler;
+ int count;
+};
+
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
void __acpi_unmap_table(char *map, unsigned long size);
int early_acpi_boot_init(void);
@@ -149,10 +155,17 @@ int __init acpi_parse_entries(char *id, unsigned long table_size,
acpi_tbl_entry_handler handler,
struct acpi_table_header *table_header,
int entry_id, unsigned int max_entries);
+int __init acpi_parse_entries_array(char *id, unsigned long table_size,
+ struct acpi_table_header *table_header,
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries);
int __init acpi_table_parse_entries(char *id, unsigned long table_size,
int entry_id,
acpi_tbl_entry_handler handler,
unsigned int max_entries);
+int __init acpi_table_parse_entries_array(char *id, unsigned long table_size,
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries);
int acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler,
unsigned int max_entries);
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 11:40 +0200 |
| Subject | [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order |
| Message-ID | <q6K1d-7xZ-19@gated-at.bofh.it> |
| In reply to | #1221339 |
ACPI specifies the following rules when listing APIC IDs:
(1) Boot processor is listed first
(2) For multi-threaded processors, BIOS should list the first logical
processor of each of the individual multi-threaded processors in MADT
before listing any of the second logical processors.
(3) APIC IDs < 0xFF should be listed in APIC subtable, APIC IDs >= 0xFF
should be listed in X2APIC subtable
Because of above, when there's more than 0xFF logical CPUs, BIOS
interleaves APIC/X2APIC subtables.
Assuming, there's 72 cores, 72 hyper-threads each, 288 CPUs total,
listing is like this:
APIC (0,4,8, .., 252)
X2APIC (258,260,264, .. 284)
APIC (1,5,9,...,253)
X2APIC (259,261,265,...,285)
APIC (2,6,10,...,254)
X2APIC (260,262,266,..,286)
APIC (3,7,11,...,251)
X2APIC (255,261,262,266,..,287)
Now, before this patch, due to how ACPI MADT subtables were parsed (BSP
then X2APIC then APIC), kernel enumerated CPUs in reverted order (i.e.
high APIC IDs were getting low logical IDs, and low APIC IDs were
getting high logical IDs).
This is wrong for the following reasons:
() it's hard to predict how cores and threads are enumerated
() when it's hard to predict, s/w threads cannot be properly affinitized
causing significant performance impact due to e.g. inproper cache
sharing
() enumeration is inconsistent with how threads are enumerated on
other Intel Xeon processors
So, order in which MADT APIC/X2APIC handlers are passed is
reverse and both handlers are passed to be called during same MADT
table to walk to achieve correct CPU enumeration.
In scenario when someone boots kernel with options 'maxcpus=72 nox2apic',
in result less cores may be booted, since some of the CPUs the kernel
will try to use will have APIC ID >= 0xFF. In such case, one
should not pass 'nox2apic'.
Disclimer: code parsing MADT APIC/X2APIC has not been touched since 2009,
when X2APIC support was initially added. I do not know why MADT parsing
code was added in the reversed order in the first place.
I guess it didn't matter at that time since nobody cared about cores
with APIC IDs >= 0xFF, right?
This patch is based on work of "Yinghai Lu <yinghai@kernel.org>"
previously published at https://lkml.org/lkml/2013/1/21/563
Here's the explanation why parsing interface needs to be changed
and why simpler approach will not work https://lkml.org/lkml/2015/9/7/285
Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de> (commit message)
---
arch/x86/kernel/acpi/boot.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e49ee24..116e911 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -981,6 +981,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
int x2count = 0;
+ int ret;
+ struct acpi_subtable_proc madt_proc[2];
if (!cpu_has_apic)
return -ENODEV;
@@ -1004,10 +1006,22 @@ static int __init acpi_parse_madt_lapic_entries(void)
acpi_parse_sapic, MAX_LOCAL_APIC);
if (!count) {
- x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
- acpi_parse_x2apic, MAX_LOCAL_APIC);
- count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
- acpi_parse_lapic, MAX_LOCAL_APIC);
+ memset(madt_proc, 0, sizeof(madt_proc));
+ madt_proc[0].id = ACPI_MADT_TYPE_LOCAL_APIC;
+ madt_proc[0].handler = acpi_parse_lapic;
+ madt_proc[1].id = ACPI_MADT_TYPE_LOCAL_X2APIC;
+ madt_proc[1].handler = acpi_parse_x2apic;
+ ret = acpi_table_parse_entries_array(ACPI_SIG_MADT,
+ sizeof(struct acpi_table_madt),
+ madt_proc, ARRAY_SIZE(madt_proc), MAX_LOCAL_APIC);
+ if (ret < 0) {
+ printk(KERN_ERR PREFIX
+ "Error parsing LAPIC/X2APIC entries\n");
+ return ret;
+ }
+
+ x2count = madt_proc[0].count;
+ count = madt_proc[1].count;
}
if (!count && !x2count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
|---|---|
| Date | 2015-09-09 16:00 +0200 |
| Subject | Re: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order |
| Message-ID | <q6O4O-4Sl-9@gated-at.bofh.it> |
| In reply to | #1221341 |
On Wed, Sep 09, 2015 at 10:30:18AM +0100, Lukasz Anaczkowski wrote:
> ACPI specifies the following rules when listing APIC IDs:
> (1) Boot processor is listed first
> (2) For multi-threaded processors, BIOS should list the first logical
> processor of each of the individual multi-threaded processors in MADT
> before listing any of the second logical processors.
> (3) APIC IDs < 0xFF should be listed in APIC subtable, APIC IDs >= 0xFF
> should be listed in X2APIC subtable
>
> Because of above, when there's more than 0xFF logical CPUs, BIOS
> interleaves APIC/X2APIC subtables.
>
> Assuming, there's 72 cores, 72 hyper-threads each, 288 CPUs total,
> listing is like this:
>
> APIC (0,4,8, .., 252)
> X2APIC (258,260,264, .. 284)
> APIC (1,5,9,...,253)
> X2APIC (259,261,265,...,285)
> APIC (2,6,10,...,254)
> X2APIC (260,262,266,..,286)
> APIC (3,7,11,...,251)
> X2APIC (255,261,262,266,..,287)
>
> Now, before this patch, due to how ACPI MADT subtables were parsed (BSP
> then X2APIC then APIC), kernel enumerated CPUs in reverted order (i.e.
> high APIC IDs were getting low logical IDs, and low APIC IDs were
> getting high logical IDs).
> This is wrong for the following reasons:
> () it's hard to predict how cores and threads are enumerated
So ? Why would the logical cpus order matters at all ? I guessed
there are probeable properties that allows the kernel to build
the affinity (ie topology list, shared caches, smt siblings, etc).
Please explain, since I am confused, to me all you need is a list
of existing physical ids, in whatever order they come, that's at least
what we need on ARM.
> () when it's hard to predict, s/w threads cannot be properly affinitized
> causing significant performance impact due to e.g. inproper cache
> sharing
See above. Why cpus logical ordering would matter here ?
> () enumeration is inconsistent with how threads are enumerated on
> other Intel Xeon processors
And why does that matter ? Is it because userspace is making assumptions
on the logical cpu enumeration scheme ? I am just asking, I would
like to understand.
> So, order in which MADT APIC/X2APIC handlers are passed is
> reverse and both handlers are passed to be called during same MADT
> table to walk to achieve correct CPU enumeration.
Define "correct" please, you define the logical ordering you
want to achieve, you do not define why that's more "correct"
than the current implementation.
Thank you,
Lorenzo
> In scenario when someone boots kernel with options 'maxcpus=72 nox2apic',
> in result less cores may be booted, since some of the CPUs the kernel
> will try to use will have APIC ID >= 0xFF. In such case, one
> should not pass 'nox2apic'.
>
> Disclimer: code parsing MADT APIC/X2APIC has not been touched since 2009,
> when X2APIC support was initially added. I do not know why MADT parsing
> code was added in the reversed order in the first place.
> I guess it didn't matter at that time since nobody cared about cores
> with APIC IDs >= 0xFF, right?
>
> This patch is based on work of "Yinghai Lu <yinghai@kernel.org>"
> previously published at https://lkml.org/lkml/2013/1/21/563
>
> Here's the explanation why parsing interface needs to be changed
> and why simpler approach will not work https://lkml.org/lkml/2015/9/7/285
>
> Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
> Acked-by: Thomas Gleixner <tglx@linutronix.de> (commit message)
> ---
> arch/x86/kernel/acpi/boot.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
> index e49ee24..116e911 100644
> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -981,6 +981,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
> {
> int count;
> int x2count = 0;
> + int ret;
> + struct acpi_subtable_proc madt_proc[2];
>
> if (!cpu_has_apic)
> return -ENODEV;
> @@ -1004,10 +1006,22 @@ static int __init acpi_parse_madt_lapic_entries(void)
> acpi_parse_sapic, MAX_LOCAL_APIC);
>
> if (!count) {
> - x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
> - acpi_parse_x2apic, MAX_LOCAL_APIC);
> - count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
> - acpi_parse_lapic, MAX_LOCAL_APIC);
> + memset(madt_proc, 0, sizeof(madt_proc));
> + madt_proc[0].id = ACPI_MADT_TYPE_LOCAL_APIC;
> + madt_proc[0].handler = acpi_parse_lapic;
> + madt_proc[1].id = ACPI_MADT_TYPE_LOCAL_X2APIC;
> + madt_proc[1].handler = acpi_parse_x2apic;
> + ret = acpi_table_parse_entries_array(ACPI_SIG_MADT,
> + sizeof(struct acpi_table_madt),
> + madt_proc, ARRAY_SIZE(madt_proc), MAX_LOCAL_APIC);
> + if (ret < 0) {
> + printk(KERN_ERR PREFIX
> + "Error parsing LAPIC/X2APIC entries\n");
> + return ret;
> + }
> +
> + x2count = madt_proc[0].count;
> + count = madt_proc[1].count;
> }
> if (!count && !x2count) {
> printk(KERN_ERR PREFIX "No LAPIC entries present\n");
> --
> 1.8.3.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Anaczkowski, Lukasz" <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 16:40 +0200 |
| Subject | RE: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order |
| Message-ID | <q6OHw-5QY-11@gated-at.bofh.it> |
| In reply to | #1221480 |
-----Original Message----- From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com] Sent: Wednesday, September 9, 2015 3:56 PM > On Wed, Sep 09, 2015 at 10:30:18AM +0100, Lukasz Anaczkowski wrote: > > () it's hard to predict how cores and threads are enumerated > So ? Why would the logical cpus order matters at all ? I guessed > there are probeable properties that allows the kernel to build > the affinity (ie topology list, shared caches, smt siblings, etc). > Please explain, since I am confused, to me all you need is a list > of existing physical ids, in whatever order they come, that's at least > what we need on ARM. Hi Lorenzo, Sure, let me try to explain this better. Proper (i.e. predictable way of CPU enumeration) matters for HPC software, (this is where I come from) as there are workloads that have some assumptions on CPU enumeration in order to keep cache hit ratio as high as possible. E.g. in KNL cores share L2 caches, and if during enumeration logical cores do not reflect physical cores, S/W can start affinitize threads to the same physical cores causing great performance impact exactly due to L2 cache misses. (e.g. s/w assumes that HT CPUs are separated by core count). Now, those changes would not be required if someone who have written APIC spec had reserved more than just 1 byte for CPU id :) Unfortunately, it's the case for x86 APIC ID and once it turns out there's a need to enumerate more than that, they added X2APIC spec which has 4 bytes for ID. Even that would be also fine if there were just physical cores, but with HT, ACPI clearly says, that first must be listed physical cores and only after that HT CPUs (and that's why APIC/X2APIC subtables are interleaved). When GIC spec was added, someone was smart enough to put 4 bytes from the begging, so you don't need to care about it on ARM :) > > () enumeration is inconsistent with how threads are enumerated on > > other Intel Xeon processors > And why does that matter ? Is it because userspace is making assumptions > on the logical cpu enumeration scheme ? I am just asking, I would > like to understand. Yes, HPC software makes some assumptions about CPU enumeration (as mentioned above) and having inconsistent enumeration between different x86 CPUs (Xeon vs Xeon Phi) make such s/w basically not portable. > > So, order in which MADT APIC/X2APIC handlers are passed is > > reverse and both handlers are passed to be called during same MADT > > table to walk to achieve correct CPU enumeration. > Define "correct" please, you define the logical ordering you > want to achieve, you do not define why that's more "correct" > than the current implementation. Ok, probably 'correct' word is not the best here :) Does 'compatible' sound better? Thanks, Lukasz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
|---|---|
| Date | 2015-09-09 17:50 +0200 |
| Subject | Re: [PATCH 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order |
| Message-ID | <q6PNf-7nE-1@gated-at.bofh.it> |
| In reply to | #1221501 |
On Wed, Sep 09, 2015 at 03:27:47PM +0100, Anaczkowski, Lukasz wrote: > -----Original Message----- > From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi@arm.com] > Sent: Wednesday, September 9, 2015 3:56 PM > > > On Wed, Sep 09, 2015 at 10:30:18AM +0100, Lukasz Anaczkowski wrote: > > > () it's hard to predict how cores and threads are enumerated > > > So ? Why would the logical cpus order matters at all ? I guessed > > there are probeable properties that allows the kernel to build > > the affinity (ie topology list, shared caches, smt siblings, etc). > > Please explain, since I am confused, to me all you need is a list > > of existing physical ids, in whatever order they come, that's at least > > what we need on ARM. > > Hi Lorenzo, > > Sure, let me try to explain this better. > > Proper (i.e. predictable way of CPU enumeration) matters for HPC software, > (this is where I come from) as there are workloads that have some assumptions > on CPU enumeration in order to keep cache hit ratio as high as possible. > E.g. in KNL cores share L2 caches, and if during enumeration logical cores do not > reflect physical cores, S/W can start affinitize threads to the same physical cores > causing great performance impact exactly due to L2 cache misses. > (e.g. s/w assumes that HT CPUs are separated by core count). > > Now, those changes would not be required if someone who have written > APIC spec had reserved more than just 1 byte for CPU id :) > Unfortunately, it's the case for x86 APIC ID and once it turns out there's a need > to enumerate more than that, they added X2APIC spec which has 4 bytes for ID. > Even that would be also fine if there were just physical cores, but with HT, ACPI > clearly says, that first must be listed physical cores and only after that HT CPUs > (and that's why APIC/X2APIC subtables are interleaved). > > When GIC spec was added, someone was smart enough to put 4 bytes from > the begging, so you don't need to care about it on ARM :) > > > > () enumeration is inconsistent with how threads are enumerated on > > > other Intel Xeon processors > > > And why does that matter ? Is it because userspace is making assumptions > > on the logical cpu enumeration scheme ? I am just asking, I would > > like to understand. > > Yes, HPC software makes some assumptions about CPU enumeration (as mentioned > above) and having inconsistent enumeration between different x86 CPUs (Xeon vs Xeon Phi) > make such s/w basically not portable. Eh, what about "other s/w" (since MADT APIC/X2APIC parsing is unchanged since 2009 as you mentioned) that relies on the way current enumeration is implemented ? I will leave that to you. /me going back to commenting the code :) > > > So, order in which MADT APIC/X2APIC handlers are passed is > > > reverse and both handlers are passed to be called during same MADT > > > table to walk to achieve correct CPU enumeration. > > > Define "correct" please, you define the logical ordering you > > want to achieve, you do not define why that's more "correct" > > than the current implementation. > > Ok, probably 'correct' word is not the best here :) > Does 'compatible' sound better? No, see above :) Thanks, Lorenzo -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2015-09-09 12:50 +0200 |
| Subject | Re: [PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers |
| Message-ID | <q6L6W-Ew-13@gated-at.bofh.it> |
| In reply to | #1221339 |
Hi Lucasz,
Nit: Please add a version number to the patches you send - this is at
least the 4th revision of this series, and it is harder to keep track of
what I'm reviewing. git send-email --subject-prefix "PATCH v4" is your
friend.
On 09/09/15 10:30, Lukasz Anaczkowski wrote:
> ACPI subtable parsing needs to be extended to allow two or more
> handlers to be run in the same ACPI table walk, thus adding
> acpi_subtable_proc structure which stores
> () ACPI table id
> () handler that processes table
> () counter how many items has been processed
> and passing it to acpi_parse_entries_array() and
> acpi_table_parse_entries_array().
>
> This is needed to fix CPU enumeration when APIC/X2APIC entries
> are interleaved.
>
> Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
> ---
> drivers/acpi/tables.c | 89 +++++++++++++++++++++++++++++++++++++++++----------
> include/linux/acpi.h | 13 ++++++++
> 2 files changed, 85 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index 2e19189..13e5089 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -214,20 +214,37 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
> }
> }
>
> +/**
> + * acpi_parse_entries_array - for each proc_num find a subtable with proc->id
> + * and run proc->handler on it. Assumption is that there's only
> + * single handler for particular entry id.
> + *
> + * @id: table id (for debugging purposes)
> + * @table_size: single entry size
> + * @table_header: where does the table start?
> + * @proc: array of acpi_subtable_proc struct containing entry id
> + * and associated handler with it
> + * @proc_num: how big proc is?
> + * @max_entries: how many entries can we process?
> + *
> + * On success returns sum of all matching entries for all proc handlers.
> + * Oterwise, -ENODEV or -EINVAL is returned.
s/Oterwise/Otherwise/
> + */
> int __init
> -acpi_parse_entries(char *id, unsigned long table_size,
> - acpi_tbl_entry_handler handler,
> +acpi_parse_entries_array(char *id, unsigned long table_size,
> struct acpi_table_header *table_header,
> - int entry_id, unsigned int max_entries)
> + struct acpi_subtable_proc *proc, int proc_num,
> + unsigned int max_entries)
It seems that there is no user of this function outside of this file, so
it can be made static.
> {
> struct acpi_subtable_header *entry;
> - int count = 0;
> unsigned long table_end;
> + int count = 0;
> + int i;
>
> if (acpi_disabled)
> return -ENODEV;
>
> - if (!id || !handler)
> + if (!id)
> return -EINVAL;
>
> if (!table_size)
> @@ -247,20 +264,27 @@ acpi_parse_entries(char *id, unsigned long table_size,
>
> while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
> table_end) {
> - if (entry->type == entry_id
> - && (!max_entries || count < max_entries)) {
> - if (handler(entry, table_end))
> + if (max_entries && count >= max_entries)
> + break;
> +
> + for (i = 0; i < proc_num; i++) {
> + if (entry->type != proc[i].id)
> + continue;
> + if (!proc->handler || proc[i].handler(entry, table_end))
> return -EINVAL;
>
> - count++;
> + proc->count++;
> + break;
> }
> + if (i != proc_num)
> + count++;
>
> /*
> * If entry->length is 0, break from this loop to avoid
> * infinite loop.
> */
> if (entry->length == 0) {
> - pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
> + pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
> return -EINVAL;
> }
>
> @@ -270,17 +294,31 @@ acpi_parse_entries(char *id, unsigned long table_size,
>
> if (max_entries && count > max_entries) {
> pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
> - id, entry_id, count - max_entries, count);
> + id, proc->id, count - max_entries, count);
> }
>
> return count;
> }
>
> +int __init acpi_parse_entries(char *id, unsigned long table_size,
> + acpi_tbl_entry_handler handler,
> + struct acpi_table_header *table_header,
> + int entry_id, unsigned int max_entries)
> +{
> + struct acpi_subtable_proc proc = {
> + .id = entry_id,
> + .handler = handler,
> + .count = 0,
count is implicitly initialized to zero when you have a partial initializer.
> + };
> +
> + return acpi_parse_entries_array(id, table_size, table_header,
> + &proc, 1, max_entries);
> +}
> +
> int __init
> -acpi_table_parse_entries(char *id,
> +acpi_table_parse_entries_array(char *id,
> unsigned long table_size,
> - int entry_id,
> - acpi_tbl_entry_handler handler,
> + struct acpi_subtable_proc *proc, int proc_num,
> unsigned int max_entries)
> {
> struct acpi_table_header *table_header = NULL;
> @@ -291,7 +329,7 @@ acpi_table_parse_entries(char *id,
> if (acpi_disabled)
> return -ENODEV;
>
> - if (!id || !handler)
> + if (!id)
> return -EINVAL;
>
> if (!strncmp(id, ACPI_SIG_MADT, 4))
> @@ -303,14 +341,31 @@ acpi_table_parse_entries(char *id,
> return -ENODEV;
> }
>
> - count = acpi_parse_entries(id, table_size, handler, table_header,
> - entry_id, max_entries);
> + count = acpi_parse_entries_array(id, table_size, table_header,
> + proc, proc_num, max_entries);
>
> early_acpi_os_unmap_memory((char *)table_header, tbl_size);
> return count;
> }
>
> int __init
> +acpi_table_parse_entries(char *id,
> + unsigned long table_size,
> + int entry_id,
> + acpi_tbl_entry_handler handler,
> + unsigned int max_entries)
> +{
> + struct acpi_subtable_proc proc = {
> + .id = entry_id,
> + .handler = handler,
> + .count = 0,
Same here.
> + };
> +
> + return acpi_table_parse_entries_array(id, table_size, &proc, 1,
> + max_entries);
> +}
> +
> +int __init
> acpi_table_parse_madt(enum acpi_madt_type id,
> acpi_tbl_entry_handler handler, unsigned int max_entries)
> {
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index d2445fa..7a25ef9 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -135,6 +135,12 @@ static inline void acpi_initrd_override(void *data, size_t size)
> (!entry) || (unsigned long)entry + sizeof(*entry) > end || \
> ((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
>
> +struct acpi_subtable_proc {
> + int id;
> + acpi_tbl_entry_handler handler;
> + int count;
> +};
> +
> char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
> void __acpi_unmap_table(char *map, unsigned long size);
> int early_acpi_boot_init(void);
> @@ -149,10 +155,17 @@ int __init acpi_parse_entries(char *id, unsigned long table_size,
> acpi_tbl_entry_handler handler,
> struct acpi_table_header *table_header,
> int entry_id, unsigned int max_entries);
> +int __init acpi_parse_entries_array(char *id, unsigned long table_size,
> + struct acpi_table_header *table_header,
> + struct acpi_subtable_proc *proc, int proc_num,
> + unsigned int max_entries);
and you can drop this one if you make it static in tables.c
> int __init acpi_table_parse_entries(char *id, unsigned long table_size,
> int entry_id,
> acpi_tbl_entry_handler handler,
> unsigned int max_entries);
> +int __init acpi_table_parse_entries_array(char *id, unsigned long table_size,
> + struct acpi_subtable_proc *proc, int proc_num,
> + unsigned int max_entries);
> int acpi_table_parse_madt(enum acpi_madt_type id,
> acpi_tbl_entry_handler handler,
> unsigned int max_entries);
>
Other than that, I gave it a quick run on arm64, and it did boot without
any observable issue. If you respin it to address the above minor
comments, you can add my:
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 15:50 +0200 |
| Subject | [PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6NV7-4H2-9@gated-at.bofh.it> |
| In reply to | #1221365 |
This series of patches attempts to fix how CPUs are enumerated by kernel when there's more than 255 of them on single processor. In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements specified in ACPI spec. Without this patches, kernel then would first enumerate BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence of that could be performance penalties due to wrong L2 cache sharing. More details in patch 2/2. Also, simpler approach has been considered, which did not required ACPI parsing interface changes, however it failed to meet requirements. More details can be found here: https://lkml.org/lkml/2015/9/7/285 Lukasz Anaczkowski (2): acpi: Added acpi_subtable_proc to ACPI table parsers x86, acpi: Handle apic/x2apic entries in MADT in correct order arch/x86/kernel/acpi/boot.c | 22 +++++++++-- drivers/acpi/tables.c | 91 ++++++++++++++++++++++++++++++++++++--------- include/linux/acpi.h | 19 ++++++++-- 3 files changed, 107 insertions(+), 25 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 15:50 +0200 |
| Subject | [PATCH v4 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers |
| Message-ID | <q6NV8-4H2-35@gated-at.bofh.it> |
| In reply to | #1221470 |
ACPI subtable parsing needs to be extended to allow two or more
handlers to be run in the same ACPI table walk, thus adding
acpi_subtable_proc structure which stores
() ACPI table id
() handler that processes table
() counter how many items has been processed
and passing it to acpi_parse_entries_array() and
acpi_table_parse_entries_array().
This is needed to fix CPU enumeration when APIC/X2APIC entries
are interleaved.
Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Tested-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/acpi/tables.c | 91 +++++++++++++++++++++++++++++++++++++++++----------
include/linux/acpi.h | 19 +++++++++--
2 files changed, 89 insertions(+), 21 deletions(-)
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 2e19189..b2608fe 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -214,20 +214,37 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
}
-int __init
-acpi_parse_entries(char *id, unsigned long table_size,
- acpi_tbl_entry_handler handler,
+/**
+ * acpi_parse_entries_array - for each proc_num find a subtable with proc->id
+ * and run proc->handler on it. Assumption is that there's only
+ * single handler for particular entry id.
+ *
+ * @id: table id (for debugging purposes)
+ * @table_size: single entry size
+ * @table_header: where does the table start?
+ * @proc: array of acpi_subtable_proc struct containing entry id
+ * and associated handler with it
+ * @proc_num: how big proc is?
+ * @max_entries: how many entries can we process?
+ *
+ * On success returns sum of all matching entries for all proc handlers.
+ * Otherwise, -ENODEV or -EINVAL is returned.
+ */
+static int __init
+acpi_parse_entries_array(char *id, unsigned long table_size,
struct acpi_table_header *table_header,
- int entry_id, unsigned int max_entries)
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries)
{
struct acpi_subtable_header *entry;
- int count = 0;
unsigned long table_end;
+ int count = 0;
+ int i;
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!table_size)
@@ -247,20 +264,27 @@ acpi_parse_entries(char *id, unsigned long table_size,
while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
table_end) {
- if (entry->type == entry_id
- && (!max_entries || count < max_entries)) {
- if (handler(entry, table_end))
+ if (max_entries && count >= max_entries)
+ break;
+
+ for (i = 0; i < proc_num; i++) {
+ if (entry->type != proc[i].id)
+ continue;
+ if (!proc->handler || proc[i].handler(entry, table_end))
return -EINVAL;
- count++;
+ proc->count++;
+ break;
}
+ if (i != proc_num)
+ count++;
/*
* If entry->length is 0, break from this loop to avoid
* infinite loop.
*/
if (entry->length == 0) {
- pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
+ pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
return -EINVAL;
}
@@ -270,17 +294,32 @@ acpi_parse_entries(char *id, unsigned long table_size,
if (max_entries && count > max_entries) {
pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
- id, entry_id, count - max_entries, count);
+ id, proc->id, count - max_entries, count);
}
return count;
}
int __init
-acpi_table_parse_entries(char *id,
+acpi_parse_entries(char *id,
+ unsigned long table_size,
+ acpi_tbl_entry_handler handler,
+ struct acpi_table_header *table_header,
+ int entry_id, unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
+
+ return acpi_parse_entries_array(id, table_size, table_header,
+ &proc, 1, max_entries);
+}
+
+int __init
+acpi_table_parse_entries_array(char *id,
unsigned long table_size,
- int entry_id,
- acpi_tbl_entry_handler handler,
+ struct acpi_subtable_proc *proc, int proc_num,
unsigned int max_entries)
{
struct acpi_table_header *table_header = NULL;
@@ -291,7 +330,7 @@ acpi_table_parse_entries(char *id,
if (acpi_disabled)
return -ENODEV;
- if (!id || !handler)
+ if (!id)
return -EINVAL;
if (!strncmp(id, ACPI_SIG_MADT, 4))
@@ -303,14 +342,30 @@ acpi_table_parse_entries(char *id,
return -ENODEV;
}
- count = acpi_parse_entries(id, table_size, handler, table_header,
- entry_id, max_entries);
+ count = acpi_parse_entries_array(id, table_size, table_header,
+ proc, proc_num, max_entries);
early_acpi_os_unmap_memory((char *)table_header, tbl_size);
return count;
}
int __init
+acpi_table_parse_entries(char *id,
+ unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries)
+{
+ struct acpi_subtable_proc proc = {
+ .id = entry_id,
+ .handler = handler,
+ };
+
+ return acpi_table_parse_entries_array(id, table_size, &proc, 1,
+ max_entries);
+}
+
+int __init
acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler, unsigned int max_entries)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d2445fa..3dd741f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -135,6 +135,12 @@ static inline void acpi_initrd_override(void *data, size_t size)
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
+struct acpi_subtable_proc {
+ int id;
+ acpi_tbl_entry_handler handler;
+ int count;
+};
+
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
void __acpi_unmap_table(char *map, unsigned long size);
int early_acpi_boot_init(void);
@@ -150,9 +156,16 @@ int __init acpi_parse_entries(char *id, unsigned long table_size,
struct acpi_table_header *table_header,
int entry_id, unsigned int max_entries);
int __init acpi_table_parse_entries(char *id, unsigned long table_size,
- int entry_id,
- acpi_tbl_entry_handler handler,
- unsigned int max_entries);
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries);
+int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+ int entry_id,
+ acpi_tbl_entry_handler handler,
+ unsigned int max_entries);
+int __init acpi_table_parse_entries_array(char *id, unsigned long table_size,
+ struct acpi_subtable_proc *proc, int proc_num,
+ unsigned int max_entries);
int acpi_table_parse_madt(enum acpi_madt_type id,
acpi_tbl_entry_handler handler,
unsigned int max_entries);
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 15:50 +0200 |
| Subject | [PATCH v4 2/2] x86, acpi: Handle apic/x2apic entries in MADT in correct order |
| Message-ID | <q6NV8-4H2-39@gated-at.bofh.it> |
| In reply to | #1221476 |
ACPI specifies the following rules when listing APIC IDs:
(1) Boot processor is listed first
(2) For multi-threaded processors, BIOS should list the first logical
processor of each of the individual multi-threaded processors in MADT
before listing any of the second logical processors.
(3) APIC IDs < 0xFF should be listed in APIC subtable, APIC IDs >= 0xFF
should be listed in X2APIC subtable
Because of above, when there's more than 0xFF logical CPUs, BIOS
interleaves APIC/X2APIC subtables.
Assuming, there's 72 cores, 72 hyper-threads each, 288 CPUs total,
listing is like this:
APIC (0,4,8, .., 252)
X2APIC (258,260,264, .. 284)
APIC (1,5,9,...,253)
X2APIC (259,261,265,...,285)
APIC (2,6,10,...,254)
X2APIC (260,262,266,..,286)
APIC (3,7,11,...,251)
X2APIC (255,261,262,266,..,287)
Now, before this patch, due to how ACPI MADT subtables were parsed (BSP
then X2APIC then APIC), kernel enumerated CPUs in reverted order (i.e.
high APIC IDs were getting low logical IDs, and low APIC IDs were
getting high logical IDs).
This is wrong for the following reasons:
() it's hard to predict how cores and threads are enumerated
() when it's hard to predict, s/w threads cannot be properly affinitized
causing significant performance impact due to e.g. inproper cache
sharing
() enumeration is inconsistent with how threads are enumerated on
other Intel Xeon processors
So, order in which MADT APIC/X2APIC handlers are passed is
reverse and both handlers are passed to be called during same MADT
table to walk to achieve correct CPU enumeration.
In scenario when someone boots kernel with options 'maxcpus=72 nox2apic',
in result less cores may be booted, since some of the CPUs the kernel
will try to use will have APIC ID >= 0xFF. In such case, one
should not pass 'nox2apic'.
Disclimer: code parsing MADT APIC/X2APIC has not been touched since 2009,
when X2APIC support was initially added. I do not know why MADT parsing
code was added in the reversed order in the first place.
I guess it didn't matter at that time since nobody cared about cores
with APIC IDs >= 0xFF, right?
This patch is based on work of "Yinghai Lu <yinghai@kernel.org>"
previously published at https://lkml.org/lkml/2013/1/21/563
Here's the explanation why parsing interface needs to be changed
and why simpler approach will not work https://lkml.org/lkml/2015/9/7/285
Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de> (commit message)
---
arch/x86/kernel/acpi/boot.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e49ee24..116e911 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -981,6 +981,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
int x2count = 0;
+ int ret;
+ struct acpi_subtable_proc madt_proc[2];
if (!cpu_has_apic)
return -ENODEV;
@@ -1004,10 +1006,22 @@ static int __init acpi_parse_madt_lapic_entries(void)
acpi_parse_sapic, MAX_LOCAL_APIC);
if (!count) {
- x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
- acpi_parse_x2apic, MAX_LOCAL_APIC);
- count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
- acpi_parse_lapic, MAX_LOCAL_APIC);
+ memset(madt_proc, 0, sizeof(madt_proc));
+ madt_proc[0].id = ACPI_MADT_TYPE_LOCAL_APIC;
+ madt_proc[0].handler = acpi_parse_lapic;
+ madt_proc[1].id = ACPI_MADT_TYPE_LOCAL_X2APIC;
+ madt_proc[1].handler = acpi_parse_x2apic;
+ ret = acpi_table_parse_entries_array(ACPI_SIG_MADT,
+ sizeof(struct acpi_table_madt),
+ madt_proc, ARRAY_SIZE(madt_proc), MAX_LOCAL_APIC);
+ if (ret < 0) {
+ printk(KERN_ERR PREFIX
+ "Error parsing LAPIC/X2APIC entries\n");
+ return ret;
+ }
+
+ x2count = madt_proc[0].count;
+ count = madt_proc[1].count;
}
if (!count && !x2count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Rafael J. Wysocki" <rjw@rjwysocki.net> |
|---|---|
| Date | 2015-09-09 22:20 +0200 |
| Subject | Re: [PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6U0y-56Z-17@gated-at.bofh.it> |
| In reply to | #1221470 |
On Wednesday, September 09, 2015 03:47:27 PM Lukasz Anaczkowski wrote: > This series of patches attempts to fix how CPUs are enumerated by kernel when > there's more than 255 of them on single processor. > In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements > specified in ACPI spec. Without this patches, kernel then would first enumerate > BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high > logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence > of that could be performance penalties due to wrong L2 cache sharing. > More details in patch 2/2. > > Also, simpler approach has been considered, which did not required ACPI parsing > interface changes, however it failed to meet requirements. More details can be > found here: https://lkml.org/lkml/2015/9/7/285 > > Lukasz Anaczkowski (2): > acpi: Added acpi_subtable_proc to ACPI table parsers > x86, acpi: Handle apic/x2apic entries in MADT in correct order > > arch/x86/kernel/acpi/boot.c | 22 +++++++++-- > drivers/acpi/tables.c | 91 ++++++++++++++++++++++++++++++++++++--------- > include/linux/acpi.h | 19 ++++++++-- > 3 files changed, 107 insertions(+), 25 deletions(-) OK Does anyone in the CC have any objections against merging this series? If not, I'll queue it up as 4.3-rc material. Thanks, Rafael -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Rafael J. Wysocki" <rjw@rjwysocki.net> |
|---|---|
| Date | 2015-09-19 00:20 +0200 |
| Subject | Re: [PATCH v4 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <qacaB-7wO-15@gated-at.bofh.it> |
| In reply to | #1221694 |
On Wednesday, September 09, 2015 10:45:48 PM Rafael J. Wysocki wrote: > On Wednesday, September 09, 2015 03:47:27 PM Lukasz Anaczkowski wrote: > > This series of patches attempts to fix how CPUs are enumerated by kernel when > > there's more than 255 of them on single processor. > > In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements > > specified in ACPI spec. Without this patches, kernel then would first enumerate > > BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high > > logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence > > of that could be performance penalties due to wrong L2 cache sharing. > > More details in patch 2/2. > > > > Also, simpler approach has been considered, which did not required ACPI parsing > > interface changes, however it failed to meet requirements. More details can be > > found here: https://lkml.org/lkml/2015/9/7/285 > > > > Lukasz Anaczkowski (2): > > acpi: Added acpi_subtable_proc to ACPI table parsers > > x86, acpi: Handle apic/x2apic entries in MADT in correct order > > > > arch/x86/kernel/acpi/boot.c | 22 +++++++++-- > > drivers/acpi/tables.c | 91 ++++++++++++++++++++++++++++++++++++--------- > > include/linux/acpi.h | 19 ++++++++-- > > 3 files changed, 107 insertions(+), 25 deletions(-) > > OK > > Does anyone in the CC have any objections against merging this series? > > If not, I'll queue it up as 4.3-rc material. Well, I had a plan to push this for 4.3-rc2, but then I looked at it again and realized that I'd like it to stay in linux-next for a couple of weeks at least as I'm really unsure that it's not going to uncover some nastiness somewhere. Which practically means it's now scheduled for v4.4. Thanks, Rafael -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 15:50 +0200 |
| Subject | Re: [PATCH 1/2] acpi: Added acpi_subtable_proc to ACPI table parsers |
| Message-ID | <q6NV7-4H2-11@gated-at.bofh.it> |
| In reply to | #1221365 |
From: Marc Zyngier [mailto:marc.zyngier@arm.com] Sent: Wednesday, September 9, 2015 12:48 PM > Nit: Please add a version number to the patches you send - this is at > least the 4th revision of this series, and it is harder to keep track of > what I'm reviewing. git send-email --subject-prefix "PATCH v4" is your > friend. Oh... so this is how you do that! Thanks! Let me put 'v4' on this series and I'll start counting from that. > If you respin it to address the above minor > comments, you can add my: > Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> > Tested-by: Marc Zyngier <marc.zyngier@arm.com> I've incorporated your comments and putting tags into 1/2 patch. Thanks, Marc, for all your support! Cheers, Lukasz -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> |
|---|---|
| Date | 2015-09-09 11:40 +0200 |
| Subject | [PATCH 0/2] Fix how CPUs are enumerated when there's more than 255 CPUs |
| Message-ID | <q6K1b-7xZ-9@gated-at.bofh.it> |
| In reply to | #1220959 |
This series of patches attempts to fix how CPUs are enumerated by kernel when there's more than 255 of them on single processor. In such case, BIOS may interleave APIC/X2APIC MADT subtables, to obey requirements specified in ACPI spec. Without this patches, kernel then would first enumerate BSP, then X2APIC then APIC, resulting in low APIC IDs to be assigned with high logical IDs and high APIC IDs to be assigned low logical IDs. Biggest consequence of that could be performance penalties due to wrong L2 cache sharing. More details in patch 2/2. Also, simpler approach has been considered, which did not required ACPI parsing interface changes, however it failed to meet requirements. More details can be found here: https://lkml.org/lkml/2015/9/7/285 Lukasz Anaczkowski (2): acpi: Added acpi_subtable_proc to ACPI table parsers x86, acpi: Handle apic/x2apic entries in MADT in correct order arch/x86/kernel/acpi/boot.c | 22 +++++++++-- drivers/acpi/tables.c | 89 ++++++++++++++++++++++++++++++++++++--------- include/linux/acpi.h | 13 +++++++ 3 files changed, 103 insertions(+), 21 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web