Do runtime detection of MP extensions to allow using a MULTIPROCESSOR

kernel on CPUs without the MP extensions feature (like Cortex-A8).
This commit is contained in:
jmcneill 2017-08-24 14:19:36 +00:00
parent 8ae9876451
commit 91a285accd
6 changed files with 135 additions and 78 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpufunc.c,v 1.163 2017/01/28 13:21:11 jakllsch Exp $ */
/* $NetBSD: cpufunc.c,v 1.164 2017/08/24 14:19:36 jmcneill Exp $ */
/*
* arm7tdmi support code Copyright (c) 2001 John Fremlin
@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.163 2017/01/28 13:21:11 jakllsch Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.164 2017/08/24 14:19:36 jmcneill Exp $");
#include "opt_compat_netbsd.h"
#include "opt_cpuoptions.h"
@ -1300,12 +1300,12 @@ struct cpu_functions armv7_cpufuncs = {
/* TLB functions */
.cf_tlb_flushID = armv7_tlb_flushID,
.cf_tlb_flushID_SE = armv7_tlb_flushID_SE,
.cf_tlb_flushI = armv7_tlb_flushI,
.cf_tlb_flushI_SE = armv7_tlb_flushI_SE,
.cf_tlb_flushD = armv7_tlb_flushD,
.cf_tlb_flushD_SE = armv7_tlb_flushD_SE,
.cf_tlb_flushID = armv7up_tlb_flushID,
.cf_tlb_flushID_SE = armv7up_tlb_flushID_SE,
.cf_tlb_flushI = armv7up_tlb_flushI,
.cf_tlb_flushI_SE = armv7up_tlb_flushI_SE,
.cf_tlb_flushD = armv7up_tlb_flushD,
.cf_tlb_flushD_SE = armv7up_tlb_flushD_SE,
/* Cache operations */
@ -2134,6 +2134,18 @@ set_cpufuncs(void)
#if defined(CPU_CORTEX)
if (CPU_ID_CORTEX_P(cputype)) {
cpufuncs = armv7_cpufuncs;
#ifdef MULTIPROCESSOR
/* If MP extensions are present, patch in MP TLB ops */
const uint32_t mpidr = armreg_mpidr_read();
if ((mpidr & (MPIDR_MP|MPIDR_U)) == MPIDR_MP) {
cpufuncs.cf_tlb_flushID = armv7mp_tlb_flushID;
cpufuncs.cf_tlb_flushID_SE = armv7mp_tlb_flushID_SE;
cpufuncs.cf_tlb_flushI = armv7mp_tlb_flushI;
cpufuncs.cf_tlb_flushI_SE = armv7mp_tlb_flushI_SE;
cpufuncs.cf_tlb_flushD = armv7mp_tlb_flushD;
cpufuncs.cf_tlb_flushD_SE = armv7mp_tlb_flushD_SE;
}
#endif
cpu_do_powersave = 1; /* Enable powersave */
#if defined(CPU_ARMV6) || defined(CPU_PRE_ARMV6)
cpu_armv7_p = true;

View File

@ -64,64 +64,87 @@ ENTRY(armv7_context_switch)
END(armv7_context_switch)
#ifdef ARM_MMU_EXTENDED_XXX
ENTRY(armv7_tlb_flushID_ASID)
#ifdef MULTIPROCESSOR
mcr p15, 0, r0, c8, c3, 2 @ flush I+D tlb all ASID
#else
ENTRY(armv7up_tlb_flushID_ASID)
mcr p15, 0, r0, c8, c7, 2 @ flush I+D tlb all ASID
#endif
dsb @ data synchronization barrier
isb
bx lr
END(armv7_tlb_flushID_ASID)
#endif
END(armv7up_tlb_flushID_ASID)
STRONG_ALIAS(armv7_tlb_flushD_SE, armv7_tlb_flushID_SE)
STRONG_ALIAS(armv7_tlb_flushI_SE, armv7_tlb_flushID_SE)
ENTRY(armv7_tlb_flushID_SE)
bfc r0, #0, #12 @ Always KERNEL_PID, i.e. 0
#ifdef MULTIPROCESSOR
mcr p15, 0, r0, c8, c3, 1 @ flush I+D tlb single entry
#if PAGE_SIZE == 2*L2_S_SIZE
add r0, r0, #L2_S_SIZE
mcr p15, 0, r0, c8, c3, 1 @ flush I+D tlb single entry
#endif
#else /* !MULTIPROCESSOR */
mcr p15, 0, r0, c8, c7, 1 @ flush I+D tlb single entry
#if PAGE_SIZE == 2*L2_S_SIZE
add r0, r0, #L2_S_SIZE
mcr p15, 0, r0, c8, c7, 1 @ flush I+D tlb single entry
#endif
#endif /* !MULTIPROCESSOR */
ENTRY(armv7mp_tlb_flushID_ASID)
mcr p15, 0, r0, c8, c3, 2 @ flush I+D tlb all ASID
dsb @ data synchronization barrier
isb
bx lr
END(armv7_tlb_flushID_SE)
END(armv7mp_tlb_flushID_ASID)
#endif
#endif
ENTRY(armv7_tlb_flushD)
STRONG_ALIAS(armv7up_tlb_flushD_SE, armv7up_tlb_flushID_SE)
STRONG_ALIAS(armv7up_tlb_flushI_SE, armv7up_tlb_flushID_SE)
ENTRY(armv7up_tlb_flushID_SE)
bfc r0, #0, #12 @ Always KERNEL_PID, i.e. 0
mcr p15, 0, r0, c8, c7, 1 @ flush I+D tlb single entry
#if PAGE_SIZE == 2*L2_S_SIZE
add r0, r0, #L2_S_SIZE
mcr p15, 0, r0, c8, c7, 1 @ flush I+D tlb single entry
#endif
dsb @ data synchronization barrier
isb
bx lr
END(armv7up_tlb_flushID_SE)
#ifdef MULTIPROCESSOR
STRONG_ALIAS(armv7mp_tlb_flushD_SE, armv7mp_tlb_flushID_SE)
STRONG_ALIAS(armv7mp_tlb_flushI_SE, armv7mp_tlb_flushID_SE)
ENTRY(armv7mp_tlb_flushID_SE)
bfc r0, #0, #12 @ Always KERNEL_PID, i.e. 0
mcr p15, 0, r0, c8, c3, 1 @ flush I+D tlb single entry
#if PAGE_SIZE == 2*L2_S_SIZE
add r0, r0, #L2_S_SIZE
mcr p15, 0, r0, c8, c3, 1 @ flush I+D tlb single entry
#endif
dsb @ data synchronization barrier
isb
bx lr
END(armv7mp_tlb_flushID_SE)
#endif
#ifdef MULTIPROCESSOR
STRONG_ALIAS(armv7mp_tlb_flushD, armv7up_tlb_flushD)
#endif
ENTRY(armv7up_tlb_flushD)
mov r0, #0
mcr p15, 0, r0, c8, c6, 0 @ flush entire D tlb
dsb @ data synchronization barrier
isb
bx lr
END(armv7_tlb_flushD)
END(armv7up_tlb_flushD)
STRONG_ALIAS(armv7_tlb_flushI, armv7_tlb_flushID)
ENTRY(armv7_tlb_flushID)
STRONG_ALIAS(armv7up_tlb_flushI, armv7up_tlb_flushID)
ENTRY(armv7up_tlb_flushID)
dsb
mov r0, #0
#ifdef MULTIPROCESSOR
mcr p15, 0, r0, c8, c3, 0 @ flush entire I+D tlb, IS
mcr p15, 0, r0, c7, c1, 6 @ branch predictor invalidate, IS
#else
mcr p15, 0, r0, c8, c7, 0 @ flush entire I+D tlb
mcr p15, 0, r0, c7, c5, 6 @ branch predictor invalidate
#endif
dsb @ data synchronization barrier
isb
bx lr
END(armv7_tlb_flushID)
END(armv7up_tlb_flushID)
#ifdef MULTIPROCESSOR
STRONG_ALIAS(armv7mp_tlb_flushI, armv7mp_tlb_flushID)
ENTRY(armv7mp_tlb_flushID)
dsb
mov r0, #0
mcr p15, 0, r0, c8, c3, 0 @ flush entire I+D tlb, IS
mcr p15, 0, r0, c7, c1, 6 @ branch predictor invalidate, IS
dsb @ data synchronization barrier
isb
bx lr
END(armv7mp_tlb_flushID)
#endif
ENTRY_NP(armv7_setttb)
mrc p15, 0, ip, c0, c0, 5 @ get MPIDR

View File

@ -30,7 +30,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: arm32_tlb.c,v 1.10 2016/07/11 16:09:27 matt Exp $");
__KERNEL_RCSID(1, "$NetBSD: arm32_tlb.c,v 1.11 2017/08/24 14:19:36 jmcneill Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -40,6 +40,7 @@ __KERNEL_RCSID(1, "$NetBSD: arm32_tlb.c,v 1.10 2016/07/11 16:09:27 matt Exp $");
#include <arm/locore.h>
bool arm_has_tlbiasid_p; // CPU supports TLBIASID system coprocessor op
bool arm_has_mpext_p; // CPU supports MP extensions
tlb_asid_t
tlb_get_asid(void)
@ -64,11 +65,11 @@ tlb_invalidate_all(void)
{
const bool vivt_icache_p = arm_pcache.icache_type == CACHE_TYPE_VIVT;
arm_dsb();
#ifdef MULTIPROCESSOR
armreg_tlbiallis_write(0);
#else
armreg_tlbiall_write(0);
#endif
if (arm_has_mpext_p) {
armreg_tlbiallis_write(0);
} else {
armreg_tlbiall_write(0);
}
arm_isb();
if (__predict_false(vivt_icache_p)) {
if (arm_has_tlbiasid_p) {
@ -94,20 +95,20 @@ tlb_invalidate_asids(tlb_asid_t lo, tlb_asid_t hi)
arm_dsb();
if (arm_has_tlbiasid_p) {
for (; lo <= hi; lo++) {
#ifdef MULTIPROCESSOR
armreg_tlbiasidis_write(lo);
#else
armreg_tlbiasid_write(lo);
#endif
if (arm_has_mpext_p) {
armreg_tlbiasidis_write(lo);
} else {
armreg_tlbiasid_write(lo);
}
}
arm_dsb();
arm_isb();
if (__predict_false(vivt_icache_p)) {
#ifdef MULTIPROCESSOR
armreg_icialluis_write(0);
#else
armreg_iciallu_write(0);
#endif
if (arm_has_mpext_p) {
armreg_icialluis_write(0);
} else {
armreg_iciallu_write(0);
}
}
} else {
armreg_tlbiall_write(0);
@ -125,12 +126,11 @@ tlb_invalidate_addr(vaddr_t va, tlb_asid_t asid)
arm_dsb();
va = trunc_page(va) | asid;
for (vaddr_t eva = va + PAGE_SIZE; va < eva; va += L2_S_SIZE) {
#ifdef MULTIPROCESSOR
armreg_tlbimvais_write(va);
#else
armreg_tlbimva_write(va);
#endif
//armreg_tlbiall_write(asid);
if (arm_has_mpext_p) {
armreg_tlbimvais_write(va);
} else {
armreg_tlbimva_write(va);
}
}
arm_isb();
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.352 2017/07/27 10:56:42 skrll Exp $ */
/* $NetBSD: pmap.c,v 1.353 2017/08/24 14:19:36 jmcneill Exp $ */
/*
* Copyright 2003 Wasabi Systems, Inc.
@ -217,7 +217,7 @@
#include <arm/locore.h>
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.352 2017/07/27 10:56:42 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.353 2017/08/24 14:19:36 jmcneill Exp $");
//#define PMAP_DEBUG
#ifdef PMAP_DEBUG
@ -5071,11 +5071,11 @@ pmap_update(pmap_t pm)
pmap_md_pdetab_activate(pm, curlwp);
}
#if defined(MULTIPROCESSOR)
armreg_bpiallis_write(0);
#else
armreg_bpiall_write(0);
#endif
if (arm_has_mpext_p)
armreg_bpiallis_write(0);
else
armreg_bpiall_write(0);
kpreempt_enable();
KASSERTMSG(pm == pmap_kernel()
@ -7527,6 +7527,15 @@ pmap_pte_init_armv7(void)
arm_has_tlbiasid_p = true;
}
/*
* Check the MPIDR to see if this CPU supports MP extensions.
*/
#ifdef MULTIPROCESSOR
arm_has_mpext_p = (armreg_mpidr_read() & (MPIDR_MP|MPIDR_U)) == MPIDR_MP;
#else
arm_has_mpext_p = false;
#endif
pte_l1_s_prot_u = L1_S_PROT_U_armv7;
pte_l1_s_prot_w = L1_S_PROT_W_armv7;
pte_l1_s_prot_ro = L1_S_PROT_RO_armv7;

View File

@ -44,6 +44,8 @@
#ifdef _KERNEL
#include "opt_multiprocessor.h"
#include <sys/types.h>
#include <arm/armreg.h>
#include <arm/cpuconf.h>
@ -309,13 +311,23 @@ void armv7_dcache_wbinv_all(void);
void armv7_idcache_wbinv_range(vaddr_t, vsize_t);
void armv7_idcache_wbinv_all(void);
void armv7_tlb_flushID(void);
void armv7_tlb_flushI(void);
void armv7_tlb_flushD(void);
void armv7up_tlb_flushID(void);
void armv7up_tlb_flushI(void);
void armv7up_tlb_flushD(void);
void armv7_tlb_flushID_SE(vaddr_t);
void armv7_tlb_flushI_SE(vaddr_t);
void armv7_tlb_flushD_SE(vaddr_t);
void armv7up_tlb_flushID_SE(vaddr_t);
void armv7up_tlb_flushI_SE(vaddr_t);
void armv7up_tlb_flushD_SE(vaddr_t);
#ifdef MULTIPROCESSOR
void armv7mp_tlb_flushID(void);
void armv7mp_tlb_flushI(void);
void armv7mp_tlb_flushD(void);
void armv7mp_tlb_flushID_SE(vaddr_t);
void armv7mp_tlb_flushI_SE(vaddr_t);
void armv7mp_tlb_flushD_SE(vaddr_t);
#endif
void armv7_cpu_sleep(int);
void armv7_drain_writebuf(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.h,v 1.27 2017/03/16 16:13:20 chs Exp $ */
/* $NetBSD: locore.h,v 1.28 2017/08/24 14:19:36 jmcneill Exp $ */
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
@ -181,6 +181,7 @@ extern int cpu_processor_features[2];
extern int cpu_media_and_vfp_features[2];
extern bool arm_has_tlbiasid_p;
extern bool arm_has_mpext_p;
#ifdef MULTIPROCESSOR
extern u_int arm_cpu_max;
extern volatile u_int arm_cpu_hatched;