From 3da704e7e63651cd1463d9a530913ef66900f7a0 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 9 Mar 2015 14:46:10 +0000 Subject: [PATCH] Add minimum cache line sizes to struct cpuinfo, use them in the new cache maintenance routines. Also add a routine to invalidate the branch cache. Submitted by: Michal Meloun --- sys/arm/arm/cpuinfo.c | 15 ++++++++++++++- sys/arm/arm/genassym.c | 6 ++++++ sys/arm/include/cpu-v6.h | 30 +++++++++++++++++++++++------- sys/arm/include/cpuinfo.h | 6 ++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c index b0b8a88f0222..46170033a0e6 100644 --- a/sys/arm/arm/cpuinfo.c +++ b/sys/arm/arm/cpuinfo.c @@ -34,7 +34,14 @@ __FBSDID("$FreeBSD$"); #include #include -struct cpuinfo cpuinfo; +struct cpuinfo cpuinfo = +{ + /* Use safe defaults for start */ + .dcache_line_size = 32, + .dcache_line_mask = 31, + .icache_line_size = 32, + .icache_line_mask = 31, +}; /* Read and parse CPU id scheme */ void @@ -122,4 +129,10 @@ cpuinfo_init(void) cpuinfo.generic_timer_ext = (cpuinfo.id_pfr1 >> 16) & 0xF; cpuinfo.virtualization_ext = (cpuinfo.id_pfr1 >> 12) & 0xF; cpuinfo.security_ext = (cpuinfo.id_pfr1 >> 4) & 0xF; + + /* L1 Cache sizes */ + cpuinfo.dcache_line_size = 1 << (CPU_CT_DMINLINE(cpuinfo.ctr ) + 2); + cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1; + cpuinfo.icache_line_size= 1 << (CPU_CT_IMINLINE(cpuinfo.ctr ) + 2); + cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1; } diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index 7f949e6c70b2..19c2ed3d3a28 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -146,3 +147,8 @@ ASSYM(MAXCOMLEN, MAXCOMLEN); ASSYM(MAXCPU, MAXCPU); ASSYM(NIRQ, NIRQ); ASSYM(PCPU_SIZE, sizeof(struct pcpu)); + +ASSYM(DCACHE_LINE_SIZE, offsetof(struct cpuinfo, dcache_line_size)); +ASSYM(DCACHE_LINE_MASK, offsetof(struct cpuinfo, dcache_line_mask)); +ASSYM(ICACHE_LINE_SIZE, offsetof(struct cpuinfo, icache_line_size)); +ASSYM(ICACHE_LINE_MASK, offsetof(struct cpuinfo, icache_line_mask)); diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index 1eafb62da7c3..a7f0b53e9a7b 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -37,6 +37,9 @@ #define CPU_ASID_KERNEL 0 +vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t); +vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t); + /* * Macros to generate CP15 (system control processor) read/write functions. */ @@ -302,7 +305,7 @@ icache_sync(vm_offset_t sva, vm_size_t size) vm_offset_t eva = sva + size; dsb(); - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { #if __ARM_ARCH >= 7 && defined SMP _CP15_DCCMVAU(va); #else @@ -332,6 +335,19 @@ icache_inv_all(void) isb(); } +/* Invalidate branch predictor buffer */ +static __inline void +bpb_inv_all(void) +{ +#if __ARM_ARCH >= 7 && defined SMP + _CP15_BPIALLIS(); +#else + _CP15_BPIALL(); +#endif + dsb(); + isb(); +} + /* Write back D-cache to PoU */ static __inline void dcache_wb_pou(vm_offset_t sva, vm_size_t size) @@ -340,7 +356,7 @@ dcache_wb_pou(vm_offset_t sva, vm_size_t size) vm_offset_t eva = sva + size; dsb(); - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { #if __ARM_ARCH >= 7 && defined SMP _CP15_DCCMVAU(va); #else @@ -358,7 +374,7 @@ dcache_inv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size) vm_offset_t eva = sva + size; /* invalidate L1 first */ - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { _CP15_DCIMVAC(va); } dsb(); @@ -368,7 +384,7 @@ dcache_inv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size) dsb(); /* then L1 again */ - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { _CP15_DCIMVAC(va); } dsb(); @@ -383,7 +399,7 @@ dcache_wb_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size) dsb(); - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { _CP15_DCCMVAC(va); } dsb(); @@ -401,7 +417,7 @@ dcache_wbinv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size) dsb(); /* write back L1 first */ - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { _CP15_DCCMVAC(va); } dsb(); @@ -410,7 +426,7 @@ dcache_wbinv_poc(vm_offset_t sva, vm_paddr_t pa, vm_size_t size) cpu_l2cache_wbinv_range(pa, size); /* then invalidate L1 */ - for (va = sva; va < eva; va += arm_dcache_align) { + for (va = sva; va < eva; va += cpuinfo.dcache_line_size) { _CP15_DCIMVAC(va); } dsb(); diff --git a/sys/arm/include/cpuinfo.h b/sys/arm/include/cpuinfo.h index f347294e5683..ce0d8e6594b6 100644 --- a/sys/arm/include/cpuinfo.h +++ b/sys/arm/include/cpuinfo.h @@ -82,6 +82,12 @@ struct cpuinfo { int generic_timer_ext; int virtualization_ext; int security_ext; + + /* L1 cache info */ + int dcache_line_size; + int dcache_line_mask; + int icache_line_size; + int icache_line_mask; }; extern struct cpuinfo cpuinfo;