diff --git a/stand/arm64/libarm64/cache.c b/stand/arm64/libarm64/cache.c index 25766ef564dd..ff52572399ac 100644 --- a/stand/arm64/libarm64/cache.c +++ b/stand/arm64/libarm64/cache.c @@ -1,95 +1,114 @@ /*- * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under * the sponsorship of the FreeBSD Foundation. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include "cache.h" +static bool +get_cache_dic(uint64_t ctr) +{ + return (CTR_DIC_VAL(ctr) != 0); +} + +static bool +get_cache_idc(uint64_t ctr) +{ + return (CTR_IDC_VAL(ctr) != 0); +} + static unsigned int -get_dcache_line_size(void) +get_dcache_line_size(uint64_t ctr) { - uint64_t ctr; unsigned int dcl_size; - /* Accessible from all security levels */ - ctr = READ_SPECIALREG(ctr_el0); - /* * Relevant field [19:16] is LOG2 * of the number of words in DCache line */ dcl_size = CTR_DLINE_SIZE(ctr); /* Size of word shifted by cache line size */ return (sizeof(int) << dcl_size); } void cpu_flush_dcache(const void *ptr, size_t len) { - - uint64_t cl_size; + uint64_t cl_size, ctr; vm_offset_t addr, end; - cl_size = get_dcache_line_size(); - - /* Calculate end address to clean */ - end = (vm_offset_t)ptr + (vm_offset_t)len; - /* Align start address to cache line */ - addr = (vm_offset_t)ptr; - addr = rounddown2(addr, cl_size); + /* Accessible from all security levels */ + ctr = READ_SPECIALREG(ctr_el0); - for (; addr < end; addr += cl_size) - __asm __volatile("dc civac, %0" : : "r" (addr) : "memory"); - /* Full system DSB */ - __asm __volatile("dsb sy" : : : "memory"); + if (get_cache_idc(ctr)) { + dsb(ishst); + } else { + cl_size = get_dcache_line_size(ctr); + + /* Calculate end address to clean */ + end = (vm_offset_t)ptr + (vm_offset_t)len; + /* Align start address to cache line */ + 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 -cpu_inval_icache(const void *ptr, size_t len) +cpu_inval_icache(void) { + uint64_t ctr; - /* NULL ptr or 0 len means all */ - if (ptr == NULL || len == 0) { + /* Accessible from all security levels */ + ctr = READ_SPECIALREG(ctr_el0); + + if (get_cache_dic(ctr)) { + isb(); + } else { __asm __volatile( "ic ialluis \n" "dsb ish \n" + "isb \n" : : : "memory"); - return; } - - /* TODO: Other cache ranges if necessary */ } diff --git a/stand/arm64/libarm64/cache.h b/stand/arm64/libarm64/cache.h index 89b094b19c18..5e560c4d578d 100644 --- a/stand/arm64/libarm64/cache.h +++ b/stand/arm64/libarm64/cache.h @@ -1,38 +1,38 @@ /*- * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under * the sponsorship of the FreeBSD Foundation. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _CACHE_H_ #define _CACHE_H_ /* cache.c */ void cpu_flush_dcache(const void *, size_t); -void cpu_inval_icache(const void *, size_t); +void cpu_inval_icache(void); #endif /* _CACHE_H_ */ diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c index 7783d46cd8e1..6cf4a4fd8e4d 100644 --- a/stand/efi/loader/arch/arm64/exec.c +++ b/stand/efi/loader/arch/arm64/exec.c @@ -1,145 +1,145 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "loader_efi.h" #include "cache.h" #include "platform/acfreebsd.h" #include "acconfig.h" #define ACPI_SYSTEM_XFACE #define ACPI_USE_SYSTEM_INTTYPES #include "actypes.h" #include "actbl.h" static EFI_GUID acpi_guid = ACPI_TABLE_GUID; static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID; static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs); static struct file_format arm64_elf = { elf64_loadfile, elf64_exec }; struct file_format *file_formats[] = { &arm64_elf, NULL }; static int elf64_exec(struct preloaded_file *fp) { vm_offset_t modulep, kernendp; vm_offset_t clean_addr; size_t clean_size; struct file_metadata *md; ACPI_TABLE_RSDP *rsdp; Elf_Ehdr *ehdr; char buf[24]; int err, revision; void (*entry)(vm_offset_t); rsdp = efi_get_table(&acpi20_guid); if (rsdp == NULL) { rsdp = efi_get_table(&acpi_guid); } if (rsdp != NULL) { sprintf(buf, "0x%016llx", (unsigned long long)rsdp); setenv("hint.acpi.0.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", (unsigned long long)rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); } } if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); entry = efi_translate(ehdr->e_entry); efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernendp, true); if (err != 0) { efi_time_init(); return (err); } dev_cleanup(); /* Clean D-cache under kernel area and invalidate whole I-cache */ clean_addr = (vm_offset_t)efi_translate(fp->f_addr); clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr; cpu_flush_dcache((void *)clean_addr, clean_size); - cpu_inval_icache(NULL, 0); + cpu_inval_icache(); (*entry)(modulep); panic("exec returned"); } static int elf64_obj_exec(struct preloaded_file *fp) { printf("%s called for preloaded file %p (=%s):\n", __func__, fp, fp->f_name); return (ENOSYS); }