Don't sync the I/D caches when they are coherent
In the arm64 loader we need to syncronise the I and D caches. On some newer CPUs the I and D caches are coherent so we don't need to perform these operations. While here remove the arguments to cpu_inval_icache as they are unneeded. Reported by: cperciva Tested by: cperciva Sponsored by: Innovate UK
This commit is contained in:
parent
cae1884d47
commit
c1381f07f6
@ -32,20 +32,29 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <machine/armreg.h>
|
#include <machine/armreg.h>
|
||||||
|
#include <machine/atomic.h>
|
||||||
|
|
||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
static unsigned int
|
static bool
|
||||||
get_dcache_line_size(void)
|
get_cache_dic(uint64_t ctr)
|
||||||
{
|
{
|
||||||
uint64_t ctr;
|
return (CTR_DIC_VAL(ctr) != 0);
|
||||||
unsigned int dcl_size;
|
}
|
||||||
|
|
||||||
/* Accessible from all security levels */
|
static bool
|
||||||
ctr = READ_SPECIALREG(ctr_el0);
|
get_cache_idc(uint64_t ctr)
|
||||||
|
{
|
||||||
|
return (CTR_IDC_VAL(ctr) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
get_dcache_line_size(uint64_t ctr)
|
||||||
|
{
|
||||||
|
unsigned int dcl_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Relevant field [19:16] is LOG2
|
* Relevant field [19:16] is LOG2
|
||||||
@ -60,36 +69,46 @@ get_dcache_line_size(void)
|
|||||||
void
|
void
|
||||||
cpu_flush_dcache(const void *ptr, size_t len)
|
cpu_flush_dcache(const void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
|
uint64_t cl_size, ctr;
|
||||||
uint64_t cl_size;
|
|
||||||
vm_offset_t addr, end;
|
vm_offset_t addr, end;
|
||||||
|
|
||||||
cl_size = get_dcache_line_size();
|
/* Accessible from all security levels */
|
||||||
|
ctr = READ_SPECIALREG(ctr_el0);
|
||||||
|
|
||||||
/* Calculate end address to clean */
|
if (get_cache_idc(ctr)) {
|
||||||
end = (vm_offset_t)ptr + (vm_offset_t)len;
|
dsb(ishst);
|
||||||
/* Align start address to cache line */
|
} else {
|
||||||
addr = (vm_offset_t)ptr;
|
cl_size = get_dcache_line_size(ctr);
|
||||||
addr = rounddown2(addr, cl_size);
|
|
||||||
|
|
||||||
for (; addr < end; addr += cl_size)
|
/* Calculate end address to clean */
|
||||||
__asm __volatile("dc civac, %0" : : "r" (addr) : "memory");
|
end = (vm_offset_t)ptr + (vm_offset_t)len;
|
||||||
/* Full system DSB */
|
/* Align start address to cache line */
|
||||||
__asm __volatile("dsb sy" : : : "memory");
|
addr = (vm_offset_t)ptr;
|
||||||
|
addr = rounddown2(addr, cl_size);
|
||||||
|
|
||||||
|
for (; addr < end; addr += cl_size)
|
||||||
|
__asm __volatile("dc civac, %0" : : "r" (addr) :
|
||||||
|
"memory");
|
||||||
|
/* Full system DSB */
|
||||||
|
dsb(ish);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cpu_inval_icache(const void *ptr, size_t len)
|
cpu_inval_icache(void)
|
||||||
{
|
{
|
||||||
|
uint64_t ctr;
|
||||||
|
|
||||||
/* NULL ptr or 0 len means all */
|
/* Accessible from all security levels */
|
||||||
if (ptr == NULL || len == 0) {
|
ctr = READ_SPECIALREG(ctr_el0);
|
||||||
|
|
||||||
|
if (get_cache_dic(ctr)) {
|
||||||
|
isb();
|
||||||
|
} else {
|
||||||
__asm __volatile(
|
__asm __volatile(
|
||||||
"ic ialluis \n"
|
"ic ialluis \n"
|
||||||
"dsb ish \n"
|
"dsb ish \n"
|
||||||
|
"isb \n"
|
||||||
: : : "memory");
|
: : : "memory");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Other cache ranges if necessary */
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,6 @@
|
|||||||
|
|
||||||
/* cache.c */
|
/* cache.c */
|
||||||
void cpu_flush_dcache(const void *, size_t);
|
void cpu_flush_dcache(const void *, size_t);
|
||||||
void cpu_inval_icache(const void *, size_t);
|
void cpu_inval_icache(void);
|
||||||
|
|
||||||
#endif /* _CACHE_H_ */
|
#endif /* _CACHE_H_ */
|
||||||
|
@ -128,7 +128,7 @@ elf64_exec(struct preloaded_file *fp)
|
|||||||
clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr;
|
clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr;
|
||||||
|
|
||||||
cpu_flush_dcache((void *)clean_addr, clean_size);
|
cpu_flush_dcache((void *)clean_addr, clean_size);
|
||||||
cpu_inval_icache(NULL, 0);
|
cpu_inval_icache();
|
||||||
|
|
||||||
(*entry)(modulep);
|
(*entry)(modulep);
|
||||||
panic("exec returned");
|
panic("exec returned");
|
||||||
|
Loading…
Reference in New Issue
Block a user