Skip to content

Commit

Permalink
x86, ACPI: add support for x2apic ACPI extensions
Browse files Browse the repository at this point in the history
All logical processors with APIC ID values of 255 and greater will have their
APIC reported through Processor X2APIC structure (type-9 entry type) and all
logical processors with APIC ID less than 255 will have their APIC reported
through legacy Processor Local APIC (type-0 entry type) only. This is the
same case even for NMI structure reporting.
    
The Processor X2APIC Affinity structure provides the association between the
X2APIC ID of a logical processor and the proximity domain to which the logical
processor belongs.
    
For OSPM, Procssor IDs outside the 0-254 range are to be declared as Device()
objects in the ACPI namespace.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Suresh Siddha authored and Len Brown committed Apr 4, 2009
1 parent 8e0ee43 commit 7237d3d
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 5 deletions.
63 changes: 59 additions & 4 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,35 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled)
generic_processor_info(id, ver);
}

static int __init
acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
{
struct acpi_madt_local_x2apic *processor = NULL;

processor = (struct acpi_madt_local_x2apic *)header;

if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;

acpi_table_print_madt_entry(header);

#ifdef CONFIG_X86_X2APIC
/*
* 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_lapic(processor->local_apic_id, /* APIC ID */
processor->lapic_flags & ACPI_MADT_ENABLED);
#else
printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
#endif

return 0;
}

static int __init
acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
{
Expand Down Expand Up @@ -318,6 +347,25 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
return 0;
}

static int __init
acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL;

x2apic_nmi = (struct acpi_madt_local_x2apic_nmi *)header;

if (BAD_MADT_ENTRY(x2apic_nmi, end))
return -EINVAL;

acpi_table_print_madt_entry(header);

if (x2apic_nmi->lint != 1)
printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");

return 0;
}

static int __init
acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end)
{
Expand Down Expand Up @@ -823,6 +871,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
int x2count = 0;

if (!cpu_has_apic)
return -ENODEV;
Expand All @@ -846,22 +895,28 @@ static int __init acpi_parse_madt_lapic_entries(void)
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
acpi_parse_sapic, MAX_APICS);

if (!count)
if (!count) {
x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
acpi_parse_x2apic, MAX_APICS);
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
acpi_parse_lapic, MAX_APICS);
if (!count) {
}
if (!count && !x2count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
return -ENODEV;
} else if (count < 0) {
} else if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}

x2count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
acpi_parse_x2apic_nmi, 0);
count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
if (count < 0) {
if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
Expand Down
30 changes: 30 additions & 0 deletions arch/x86/mm/srat_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,36 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
reserve_early(phys, phys + length, "ACPI SLIT");
}

/* Callback for Proximity Domain -> x2APIC mapping */
void __init
acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
{
int pxm, node;
int apic_id;

if (srat_disabled())
return;
if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) {
bad_srat();
return;
}
if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
return;
pxm = pa->proximity_domain;
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
bad_srat();
return;
}

apic_id = pa->apic_id;
apicid_to_node[apic_id] = node;
acpi_numa = 1;
printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
pxm, apic_id, node);
}

/* Callback for Proximity Domain -> LAPIC mapping */
void __init
acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
Expand Down
46 changes: 45 additions & 1 deletion drivers/acpi/numa.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
#endif /* ACPI_DEBUG_OUTPUT */
break;

case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
{
struct acpi_srat_x2apic_cpu_affinity *p =
(struct acpi_srat_x2apic_cpu_affinity *)header;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"SRAT Processor (x2apicid[0x%08x]) in"
" proximity domain %d %s\n",
p->apic_id,
p->proximity_domain,
(p->flags & ACPI_SRAT_CPU_ENABLED) ?
"enabled" : "disabled"));
}
#endif /* ACPI_DEBUG_OUTPUT */
break;
default:
printk(KERN_WARNING PREFIX
"Found unsupported SRAT entry (type = 0x%x)\n",
Expand Down Expand Up @@ -180,8 +195,35 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
return 0;
}

void __init __attribute__ ((weak))
acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
{
printk(KERN_WARNING PREFIX
"Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
return;
}


static int __init
acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_x2apic_cpu_affinity *processor_affinity;

processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
if (!processor_affinity)
return -EINVAL;

acpi_table_print_srat_entry(header);

/* let architecture-dependent part to do it */
acpi_numa_x2apic_affinity_init(processor_affinity);

return 0;
}

static int __init
acpi_parse_processor_affinity(struct acpi_subtable_header * header,
acpi_parse_processor_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_cpu_affinity *processor_affinity;
Expand Down Expand Up @@ -241,6 +283,8 @@ int __init acpi_numa_init(void)
{
/* SRAT: Static Resource Affinity Table */
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
acpi_parse_x2apic_affinity, NR_CPUS);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, NR_CPUS);
acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
Expand Down
26 changes: 26 additions & 0 deletions drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,29 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
return 0;
}

static int map_x2apic_id(struct acpi_subtable_header *entry,
int device_declaration, u32 acpi_id, int *apic_id)
{
struct acpi_madt_local_x2apic *apic =
(struct acpi_madt_local_x2apic *)entry;
u32 tmp = apic->local_apic_id;

/* Only check enabled APICs*/
if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
return 0;

/* Device statement declaration type */
if (device_declaration) {
if (apic->uid == acpi_id)
goto found;
}

return 0;
found:
*apic_id = tmp;
return 1;
}

static int map_lsapic_id(struct acpi_subtable_header *entry,
int device_declaration, u32 acpi_id, int *apic_id)
{
Expand Down Expand Up @@ -476,6 +499,9 @@ static int map_madt_entry(int type, u32 acpi_id)
if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
if (map_lapic_id(header, acpi_id, &apic_id))
break;
} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
if (map_x2apic_id(header, type, acpi_id, &apic_id))
break;
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
if (map_lsapic_id(header, type, acpi_id, &apic_id))
break;
Expand Down
30 changes: 30 additions & 0 deletions drivers/acpi/tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;

case ACPI_MADT_TYPE_LOCAL_X2APIC:
{
struct acpi_madt_local_x2apic *p =
(struct acpi_madt_local_x2apic *)header;
printk(KERN_INFO PREFIX
"X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n",
p->local_apic_id, p->uid,
(p->lapic_flags & ACPI_MADT_ENABLED) ?
"enabled" : "disabled");
}
break;

case ACPI_MADT_TYPE_IO_APIC:
{
struct acpi_madt_io_apic *p =
Expand Down Expand Up @@ -116,6 +128,24 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;

case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
{
u16 polarity, trigger;
struct acpi_madt_local_x2apic_nmi *p =
(struct acpi_madt_local_x2apic_nmi *)header;

polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK;
trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2;

printk(KERN_INFO PREFIX
"X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n",
p->uid,
mps_inti_flags_polarity[polarity],
mps_inti_flags_trigger[trigger],
p->lint);
}
break;

case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
{
struct acpi_madt_local_apic_override *p =
Expand Down
1 change: 1 addition & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
/* the following four functions are architecture-dependent */
void acpi_numa_slit_init (struct acpi_table_slit *slit);
void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
void acpi_numa_arch_fixup(void);

Expand Down

0 comments on commit 7237d3d

Please sign in to comment.