Index: head/sys/arm64/arm64/efirt_machdep.c =================================================================== --- head/sys/arm64/arm64/efirt_machdep.c +++ head/sys/arm64/arm64/efirt_machdep.c @@ -0,0 +1,252 @@ +/*- + * Copyright (c) 2004 Marcel Moolenaar + * Copyright (c) 2001 Doug Rabson + * Copyright (c) 2016 The FreeBSD Foundation + * Copyright (c) 2017 Andrew Turner + * All rights reserved. + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static vm_object_t obj_1t1_pt; +static vm_page_t efi_l0_page; +static pd_entry_t *efi_l0; + +void +efi_destroy_1t1_map(void) +{ + vm_page_t m; + + if (obj_1t1_pt != NULL) { + VM_OBJECT_RLOCK(obj_1t1_pt); + TAILQ_FOREACH(m, &obj_1t1_pt->memq, listq) + m->wire_count = 0; + atomic_subtract_int(&vm_cnt.v_wire_count, + obj_1t1_pt->resident_page_count); + VM_OBJECT_RUNLOCK(obj_1t1_pt); + vm_object_deallocate(obj_1t1_pt); + } + + obj_1t1_pt = NULL; + efi_l0 = NULL; + efi_l0_page = NULL; +} + +static vm_page_t +efi_1t1_page(vm_pindex_t idx) +{ + + return (vm_page_grab(obj_1t1_pt, idx, VM_ALLOC_NOBUSY | + VM_ALLOC_WIRED | VM_ALLOC_ZERO)); +} + +static pt_entry_t * +efi_1t1_l3(vm_offset_t va) +{ + pd_entry_t *l0, *l1, *l2; + pt_entry_t *l3; + vm_pindex_t l0_idx, l1_idx, l2_idx; + vm_page_t m; + vm_paddr_t mphys; + + l0_idx = pmap_l0_index(va); + l0 = &efi_l0[l0_idx]; + if (*l0 == 0) { + m = efi_1t1_page(1 + l0_idx); + mphys = VM_PAGE_TO_PHYS(m); + *l0 = mphys | L0_TABLE; + } else { + mphys = *l0 & ~ATTR_MASK; + } + + l1 = (pd_entry_t *)PHYS_TO_DMAP(mphys); + l1_idx = pmap_l1_index(va); + l1 += l1_idx; + if (*l1 == 0) { + m = efi_1t1_page(1 + L0_ENTRIES + (l0_idx + 1) * (l1_idx + 1)); + mphys = VM_PAGE_TO_PHYS(m); + *l1 = mphys | L1_TABLE; + } else { + mphys = *l1 & ~ATTR_MASK; + } + + l2 = (pd_entry_t *)PHYS_TO_DMAP(mphys); + l2_idx = pmap_l2_index(va); + l2 += l2_idx; + if (*l2 == 0) { + m = efi_1t1_page(1 + L0_ENTRIES + L0_ENTRIES * Ln_ENTRIES + + (l0_idx + 1) * (l1_idx + 1) * (l2_idx + 1)); + mphys = VM_PAGE_TO_PHYS(m); + *l2 = mphys | L2_TABLE; + } else { + mphys = *l2 & ~ATTR_MASK; + } + + l3 = (pt_entry_t *)PHYS_TO_DMAP(mphys); + l3 += pmap_l3_index(va); + KASSERT(*l3 == 0, ("%s: Already mapped: va %#jx *pt %#jx", __func__, + va, *l3)); + + return (l3); +} + +/* + * Create the 1:1 virtual to physical map for EFI + */ +bool +efi_create_1t1_map(struct efi_md *map, int ndesc, int descsz) +{ + struct efi_md *p; + pt_entry_t *l3; + vm_offset_t va; + uint64_t idx; + int i, mode; + + obj_1t1_pt = vm_pager_allocate(OBJT_PHYS, NULL, L0_ENTRIES + + L0_ENTRIES * Ln_ENTRIES + L0_ENTRIES * Ln_ENTRIES * Ln_ENTRIES + + L0_ENTRIES * Ln_ENTRIES * Ln_ENTRIES * Ln_ENTRIES, + VM_PROT_ALL, 0, NULL); + VM_OBJECT_WLOCK(obj_1t1_pt); + efi_l0_page = efi_1t1_page(0); + VM_OBJECT_WUNLOCK(obj_1t1_pt); + efi_l0 = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(efi_l0_page)); + bzero(efi_l0, L0_ENTRIES * sizeof(*efi_l0)); + + for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p, + descsz)) { + if ((p->md_attr & EFI_MD_ATTR_RT) == 0) + continue; + if (p->md_virt != NULL) { + if (bootverbose) + printf("EFI Runtime entry %d is mapped\n", i); + goto fail; + } + if ((p->md_phys & EFI_PAGE_MASK) != 0) { + if (bootverbose) + printf("EFI Runtime entry %d is not aligned\n", + i); + goto fail; + } + if (p->md_phys + p->md_pages * EFI_PAGE_SIZE < p->md_phys || + p->md_phys + p->md_pages * EFI_PAGE_SIZE >= + VM_MAXUSER_ADDRESS) { + printf("EFI Runtime entry %d is not in mappable for RT:" + "base %#016jx %#jx pages\n", + i, (uintmax_t)p->md_phys, + (uintmax_t)p->md_pages); + goto fail; + } + if ((p->md_attr & EFI_MD_ATTR_WB) != 0) + mode = VM_MEMATTR_WRITE_BACK; + else if ((p->md_attr & EFI_MD_ATTR_WT) != 0) + mode = VM_MEMATTR_WRITE_THROUGH; + else if ((p->md_attr & EFI_MD_ATTR_WC) != 0) + mode = VM_MEMATTR_WRITE_COMBINING; + else if ((p->md_attr & EFI_MD_ATTR_UC) != 0) + mode = VM_MEMATTR_UNCACHEABLE; + else { + if (bootverbose) + printf("EFI Runtime entry %d mapping " + "attributes unsupported\n", i); + mode = VM_MEMATTR_UNCACHEABLE; + } + + printf("MAP %lx mode %x pages %lu\n", p->md_phys, mode, p->md_pages); + VM_OBJECT_WLOCK(obj_1t1_pt); + for (va = p->md_phys, idx = 0; idx < p->md_pages; idx++, + va += PAGE_SIZE) { + l3 = efi_1t1_l3(va); + *l3 = va | ATTR_DEFAULT | ATTR_IDX(mode) | + ATTR_AP(ATTR_AP_RW) | L3_PAGE; + } + VM_OBJECT_WUNLOCK(obj_1t1_pt); + } + + return (true); +fail: + efi_destroy_1t1_map(); + return (false); +} + +int +efi_arch_enter(void) +{ + + __asm __volatile( + "msr ttbr0_el1, %0 \n" + "dsb ishst \n" + "tlbi vmalle1is \n" + "dsb ish \n" + "isb \n" + : : "r"(VM_PAGE_TO_PHYS(efi_l0_page))); + + return (0); +} + +void +efi_arch_leave(void) +{ + struct thread *td; + + td = curthread; + __asm __volatile( + "msr ttbr0_el1, %0 \n" + "dsb ishst \n" + "tlbi vmalle1is \n" + "dsb ish \n" + "isb \n" + : : "r"(td->td_proc->p_md.md_l0addr)); +} Index: head/sys/arm64/arm64/machdep.c =================================================================== --- head/sys/arm64/arm64/machdep.c +++ head/sys/arm64/arm64/machdep.c @@ -121,6 +121,12 @@ int64_t dczva_line_size; /* The size of cache line the dc zva zeroes */ int has_pan; +/* + * Physical address of the EFI System Table. Stashed from the metadata hints + * passed into the kernel and used by the EFI code to call runtime services. + */ +vm_paddr_t efi_systbl_phys; + /* pagezero_* implementations are provided in support.S */ void pagezero_simple(void *); void pagezero_cache(void *); @@ -985,6 +991,8 @@ #ifdef FDT try_load_dtb(kmdp); #endif + + efi_systbl_phys = MD_FETCH(kmdp, MODINFOMD_FW_HANDLE, vm_paddr_t); /* Find the address to start allocating from */ lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); Index: head/sys/arm64/include/efi.h =================================================================== --- head/sys/arm64/include/efi.h +++ head/sys/arm64/include/efi.h @@ -1,6 +1,32 @@ /*- - * This file is in the public domain since it's just boilerplate. + * Copyright (c) 2017 Andrew Turner + * All rights reserved. * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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$ */ @@ -8,5 +34,11 @@ #define __ARM64_INCLUDE_EFI_H_ #define EFIABI_ATTR + +#ifdef _KERNEL +#define EFI_TIME_LOCK() +#define EFI_TIME_UNLOCK() +#define EFI_TIME_OWNED() +#endif #endif /* __ARM64_INCLUDE_EFI_H_ */ Index: head/sys/conf/files.arm64 =================================================================== --- head/sys/conf/files.arm64 +++ head/sys/conf/files.arm64 @@ -95,6 +95,7 @@ arm64/arm64/debug_monitor.c optional ddb arm64/arm64/disassem.c optional ddb arm64/arm64/dump_machdep.c standard +arm64/arm64/efirt_machdep.c optional efirt arm64/arm64/elf_machdep.c standard arm64/arm64/exception.S standard arm64/arm64/gicv3_its.c optional intrng fdt Index: head/sys/conf/options.arm64 =================================================================== --- head/sys/conf/options.arm64 +++ head/sys/conf/options.arm64 @@ -7,6 +7,10 @@ THUNDERX_PASS_1_1_ERRATA opt_global.h VFP opt_global.h +# EFI Runtime services support +EFIRT opt_efirt.h + +# Devices DEV_PSCI opt_platform.h # SoC Support Index: head/sys/modules/Makefile =================================================================== --- head/sys/modules/Makefile +++ head/sys/modules/Makefile @@ -562,6 +562,7 @@ .if ${MACHINE_CPUARCH} == "aarch64" _armv8crypto= armv8crypto +_efirt= efirt _em= em .endif