Store mpidr as a 64-bit value on arm64

The mpidr register is 64 bit on arm64 and 32 bit on arm. Fix this by
extending the arm64 definition to include the top 32 bits.

To preserve KBI when MFCing split the value into two 32 bit values.
This will be cleaned up later only on main.

Reviewed by:	bz
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D36346
This commit is contained in:
Andrew Turner 2022-08-25 08:28:28 +00:00
parent 998b0a4ad8
commit 544f047f89
6 changed files with 24 additions and 11 deletions

View File

@ -72,7 +72,7 @@ madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
for (i = 0; i < MAXCPU; i++) {
pcpu = pcpu_find(i);
if (pcpu != NULL && pcpu->pc_mpidr == intr->ArmMpidr) {
if (pcpu != NULL && PCPU_GET_MPIDR(pcpu) == intr->ArmMpidr) {
cpuid = i;
break;
}

View File

@ -105,7 +105,7 @@ pmu_parse_affinity(device_t dev, struct pmu_softc *sc, struct pmu_intr *irq,
for (i = 0; i < MAXCPU; i++) {
pcpu = pcpu_find(i);
if (pcpu != NULL && pcpu->pc_mpidr == mpidr) {
if (pcpu != NULL && PCPU_GET_MPIDR(pcpu) == mpidr) {
irq->cpuid = i;
return (0);
}

View File

@ -139,6 +139,8 @@ set_tls(void *tls)
#define PCPU_PTR(member) (&get_pcpu()->pc_ ## member)
#define PCPU_SET(member,value) (get_pcpu()->pc_ ## member = (value))
#define PCPU_GET_MPIDR(pc) ((pc)->pc_mpidr)
void pcpu0_init(void);
#endif /* _KERNEL */

View File

@ -300,7 +300,8 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
{
pcpu->pc_acpi_id = 0xffffffff;
pcpu->pc_mpidr = 0xffffffff;
pcpu->pc_mpidr_low = 0xffffffff;
pcpu->pc_mpidr_high = 0xffffffff;
}
void

View File

@ -153,7 +153,7 @@ static bool
is_boot_cpu(uint64_t target_cpu)
{
return (cpuid_to_pcpu[0]->pc_mpidr == (target_cpu & CPU_AFF_MASK));
return (PCPU_GET_MPIDR(cpuid_to_pcpu[0]) == (target_cpu & CPU_AFF_MASK));
}
static void
@ -207,7 +207,7 @@ init_secondary(uint64_t cpu)
{
struct pcpu *pcpup;
pmap_t pmap0;
u_int mpidr;
uint64_t mpidr;
ptrauth_mp_start(cpu);
@ -218,10 +218,10 @@ init_secondary(uint64_t cpu)
*/
mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
if (cpu >= MAXCPU || cpuid_to_pcpu[cpu] == NULL ||
cpuid_to_pcpu[cpu]->pc_mpidr != mpidr) {
PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) != mpidr) {
for (cpu = 0; cpu < mp_maxid; cpu++)
if (cpuid_to_pcpu[cpu] != NULL &&
cpuid_to_pcpu[cpu]->pc_mpidr == mpidr)
PCPU_GET_MPIDR(cpuid_to_pcpu[cpu]) == mpidr)
break;
if ( cpu >= MAXCPU)
panic("MPIDR for this CPU is not in pcpu table");
@ -517,7 +517,8 @@ start_cpu(u_int cpuid, uint64_t target_cpu, int domain)
pcpup = (struct pcpu *)pcpu_mem;
pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
pcpup->pc_mpidr = target_cpu & CPU_AFF_MASK;
pcpup->pc_mpidr_low = target_cpu & CPU_AFF_MASK;
pcpup->pc_mpidr_high = (target_cpu & CPU_AFF_MASK) >> 32;
dpcpu[cpuid - 1] = (void *)(pcpup + 1);
dpcpu_init(dpcpu[cpuid - 1], cpuid);
@ -688,11 +689,15 @@ cpu_init_fdt(void)
void
cpu_mp_start(void)
{
uint64_t mpidr;
mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
/* CPU 0 is always boot CPU. */
CPU_SET(0, &all_cpus);
cpuid_to_pcpu[0]->pc_mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK;
cpuid_to_pcpu[0]->pc_mpidr_low = mpidr;
cpuid_to_pcpu[0]->pc_mpidr_high = mpidr >> 32;
switch(arm64_bus_method) {
#ifdef DEV_ACPI

View File

@ -48,8 +48,10 @@ struct debug_monitor_state;
struct pmap *pc_curpmap; \
struct pmap *pc_curvmpmap; \
u_int pc_bcast_tlbi_workaround; \
u_int pc_mpidr; /* stored MPIDR value */ \
char __pad[201]
/* Store as two u_int values to preserve KBI */ \
u_int pc_mpidr_low; /* lower MPIDR 32 bits */ \
u_int pc_mpidr_high; /* upper MPIDR 32 bits */ \
char __pad[197]
#ifdef _KERNEL
@ -83,6 +85,9 @@ get_curthread(void)
#define PCPU_PTR(member) (&pcpup->pc_ ## member)
#define PCPU_SET(member,value) (pcpup->pc_ ## member = (value))
#define PCPU_GET_MPIDR(pc) \
((((uint64_t)((pc)->pc_mpidr_high)) << 32) | ((pc)->pc_mpidr_low))
#endif /* _KERNEL */
#endif /* !_MACHINE_PCPU_H_ */