Commit 020295b4 authored by Hanjun Guo's avatar Hanjun Guo Committed by Will Deacon

ACPI / processor: Make it possible to get CPU hardware ID via GICC

Introduce a new function map_gicc_mpidr() to allow MPIDRs to be obtained
from the GICC Structure introduced by ACPI 5.1, since MPIDR for ARM64 is
64-bit, so typedef u64 for phys_cpuid_t.

The ARM architecture defines the MPIDR register as the CPU hardware
identifier. This patch adds the code infrastructure to retrieve the MPIDR
values from the ARM ACPI GICC structure in order to look-up the kernel CPU
hardware ids required by the ACPI core code to identify CPUs.

CC: Rafael J. Wysocki <rjw@rjwysocki.net>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
Tested-by: default avatarSuravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: default avatarYijing Wang <wangyijing@huawei.com>
Tested-by: default avatarMark Langsdorf <mlangsdo@redhat.com>
Tested-by: default avatarJon Masters <jcm@redhat.com>
Tested-by: default avatarTimur Tabi <timur@codeaurora.org>
Tested-by: default avatarRobert Richter <rrichter@cavium.com>
Acked-by: default avatarRobert Richter <rrichter@cavium.com>
Acked-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarGrant Likely <grant.likely@linaro.org>
Signed-off-by: default avatarHanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 828aef37
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#define _ASM_ACPI_H #define _ASM_ACPI_H
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cputype.h>
#include <asm/smp_plat.h>
/* Basic configuration for ACPI */ /* Basic configuration for ACPI */
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
...@@ -27,6 +29,9 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys, ...@@ -27,6 +29,9 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
} }
#define acpi_os_ioremap acpi_os_ioremap #define acpi_os_ioremap acpi_os_ioremap
typedef u64 phys_cpuid_t;
#define PHYS_CPUID_INVALID INVALID_HWID
#define acpi_strict 1 /* No out-of-spec workarounds on ARM64 */ #define acpi_strict 1 /* No out-of-spec workarounds on ARM64 */
extern int acpi_disabled; extern int acpi_disabled;
extern int acpi_noirq; extern int acpi_noirq;
...@@ -58,6 +63,13 @@ static inline void enable_acpi(void) ...@@ -58,6 +63,13 @@ static inline void enable_acpi(void)
acpi_noirq = 0; acpi_noirq = 0;
} }
/*
* The ACPI processor driver for ACPI core code needs this macro
* to find out this cpu was already mapped (mapping from CPU hardware
* ID to CPU logical ID) or not.
*/
#define cpu_physical_id(cpu) cpu_logical_map(cpu)
/* /*
* It's used from ACPI core in kdump to boot UP system with SMP kernel, * It's used from ACPI core in kdump to boot UP system with SMP kernel,
* with this check the ACPI core will not override the CPU index * with this check the ACPI core will not override the CPU index
......
...@@ -83,6 +83,31 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, ...@@ -83,6 +83,31 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
return 0; return 0;
} }
/*
* Retrieve the ARM CPU physical identifier (MPIDR)
*/
static int map_gicc_mpidr(struct acpi_subtable_header *entry,
int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr)
{
struct acpi_madt_generic_interrupt *gicc =
container_of(entry, struct acpi_madt_generic_interrupt, header);
if (!(gicc->flags & ACPI_MADT_ENABLED))
return -ENODEV;
/* device_declaration means Device object in DSDT, in the
* GIC interrupt model, logical processors are required to
* have a Processor Device object in the DSDT, so we should
* check device_declaration here
*/
if (device_declaration && (gicc->uid == acpi_id)) {
*mpidr = gicc->arm_mpidr;
return 0;
}
return -EINVAL;
}
static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
{ {
unsigned long madt_end, entry; unsigned long madt_end, entry;
...@@ -111,6 +136,9 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) ...@@ -111,6 +136,9 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
if (!map_lsapic_id(header, type, acpi_id, &phys_id)) if (!map_lsapic_id(header, type, acpi_id, &phys_id))
break; break;
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
if (!map_gicc_mpidr(header, type, acpi_id, &phys_id))
break;
} }
entry += header->length; entry += header->length;
} }
...@@ -143,6 +171,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) ...@@ -143,6 +171,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
map_lsapic_id(header, type, acpi_id, &phys_id); map_lsapic_id(header, type, acpi_id, &phys_id);
else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
map_x2apic_id(header, type, acpi_id, &phys_id); map_x2apic_id(header, type, acpi_id, &phys_id);
else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
map_gicc_mpidr(header, type, acpi_id, &phys_id);
exit: exit:
kfree(buffer.pointer); kfree(buffer.pointer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment