Hi all,
I have found a minor problem in Xen 4.6 unstable
When xen booted up and parsed all cpus by acpi_parse_x2apic,
if the number of “Processor Local x2APIC Structure”(struct acpi_madt_local_x2apic) parsed from acpi table bigger than the number of host cpu.
for all extra acpi_madt_local_x2apic structure,
struct acpi_madt_local_x2apic {
struct acpi_subtable_header header;
u16 reserved; /* Reserved - must be zero */
u32 local_apic_id; /* Processor x2APIC ID */
u32 lapic_flags;
u32 uid; /* ACPI processor UID */
};
member local_apic_id has default value
FFFFFFFF.
90 static int __init
91 acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
92 {
93 struct acpi_madt_local_x2apic *processor =
94 container_of(header, struct acpi_madt_local_x2apic, header);
95 bool_t enabled = 0;
96
97 if (BAD_MADT_ENTRY(processor, end))
98 return -EINVAL;
99
100 acpi_table_print_madt_entry(header);
101
102 /* Record local apic id only when enabled and fitting. */
103 if (processor->local_apic_id >= MAX_APICS ||
104 processor->uid >= MAX_MADT_ENTRIES) {
105 printk("%sAPIC ID %#x and/or ACPI ID %#x beyond limit"
106 " - processor ignored\n",
107 processor->lapic_flags & ACPI_MADT_ENABLED ?
108 KERN_WARNING "WARNING: " : KERN_INFO,
109 processor->local_apic_id, processor->uid);
110 /*
111 * Must not return an error here, to prevent
112 * acpi_table_parse_entries() from terminating early.
113 */
114 return 0 /* -ENOSPC */;
115 }
116 if (processor->lapic_flags & ACPI_MADT_ENABLED) {
117 x86_acpiid_to_apicid[processor->uid] =
118 processor->local_apic_id;
119 enabled = 1;
120 }
121
122 /*
123 * We need to register disabled CPU as well to permit
124 * counting disabled CPUs. This allows us to size
125 * cpus_possible_map more accurately, to permit
126 * to not preallocating memory for all NR_CPUS
127 * when we use CPU hotplug.
128 */
129 mp_register_lapic(processor->local_apic_id, enabled, 0);
130
131 return 0;
|
based on the above code, “processor->local_apic_id >= MAX_APICS”(line:103) and return ,caused each disabled CPU can’t be registered.
the following patch may fix the bug.
diff --git a/b/xen/arch/x86/acpi/boot.c b/a/xen/arch/x86/acpi/boot.c
index 9a8904b..6fad341 100644
--- a/b/xen/arch/x86/acpi/boot.c
+++ b/a/xen/arch/x86/acpi/boot.c
@@ -93,20 +93,23 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
struct acpi_madt_local_x2apic *processor =
container_of(header, struct acpi_madt_local_x2apic, header);
bool_t enabled = 0;
+ int apic_id = 0;
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
acpi_table_print_madt_entry(header);
+
+ apic_id = processor->local_apic_id;
/* Record local apic id only when enabled and fitting. */
- if (processor->local_apic_id >= MAX_APICS ||
+ if (apic_id >= MAX_APICS ||
processor->uid >= MAX_MADT_ENTRIES) {
printk("%sAPIC ID %#x and/or ACPI ID %#x beyond limit"
" - processor ignored\n",
processor->lapic_flags & ACPI_MADT_ENABLED ?
KERN_WARNING "WARNING: " : KERN_INFO,
- processor->local_apic_id, processor->uid);
+ apic_id, processor->uid);
/*
* Must not return an error here, to prevent
* acpi_table_parse_entries() from terminating early.
@@ -126,7 +129,7 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
* to not preallocating memory for all NR_CPUS
* when we use CPU hotplug.
*/
- mp_register_lapic(processor->local_apic_id, enabled, 0);
+ mp_register_lapic(apic_id, enabled, 0);
return 0;
}
diff --git a/b/xen/arch/x86/mpparse.c b/a/xen/arch/x86/mpparse.c
index 003c56e..e45854b 100644
--- a/b/xen/arch/x86/mpparse.c
+++ b/a/xen/arch/x86/mpparse.c
@@ -759,7 +759,7 @@ void __init mp_register_lapic_address (
int __devinit mp_register_lapic (
- u32 id,
+ int id,
bool_t enabled,
bool_t hotplug)
{
diff --git a/b/xen/include/asm-x86/mpspec.h b/a/xen/include/asm-x86/mpspec.h
index 8ae3cd5..2c718db 100644
--- a/b/xen/include/asm-x86/mpspec.h
+++ b/a/xen/include/asm-x86/mpspec.h
@@ -20,7 +20,7 @@ extern unsigned long mp_lapic_addr;
extern bool_t pic_mode;
#ifdef CONFIG_ACPI
-extern int mp_register_lapic(u32 id, bool_t enabled, bool_t hotplug);
+extern int mp_register_lapic(int id, bool_t enabled, bool_t hotplug);
extern void mp_unregister_lapic(uint32_t apic_id, uint32_t cpu);
extern void mp_register_lapic_address (u64 address);
extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
Thanks