Author: andrew
Date: Tue Oct 10 13:05:26 2017
New Revision: 324495
URL: https://svnweb.freebsd.org/changeset/base/324495

Log:
  Support the EFI Runtime Services on arm64. As with amd64 we use the 1:1
  mapping. This uses the new common code shared with amd64.
  
  The RTC should only be accessed via EFI. There is no locking around it as
  the spec only has this as a requirement for the PC-AT CMOS device.
  
  Reviewed by:  kib, imp
  Sponsored by: DARPA, AFRL
  Differential Revision:        https://reviews.freebsd.org/D12595

Added:
  head/sys/arm64/arm64/efirt_machdep.c   (contents, props changed)
Modified:
  head/sys/arm64/arm64/machdep.c
  head/sys/arm64/include/efi.h
  head/sys/conf/files.arm64
  head/sys/conf/options.arm64
  head/sys/modules/Makefile

Added: head/sys/arm64/arm64/efirt_machdep.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm64/arm64/efirt_machdep.c        Tue Oct 10 13:05:26 2017        
(r324495)
@@ -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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/efi.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rwlock.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <machine/metadata.h>
+#include <machine/pcb.h>
+#include <machine/pte.h>
+#include <machine/vfp.h>
+#include <machine/vmparam.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+
+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));
+}

Modified: head/sys/arm64/arm64/machdep.c
==============================================================================
--- head/sys/arm64/arm64/machdep.c      Tue Oct 10 13:02:58 2017        
(r324494)
+++ head/sys/arm64/arm64/machdep.c      Tue Oct 10 13:05:26 2017        
(r324495)
@@ -121,6 +121,12 @@ int64_t idcache_line_size; /* The minimum cache line s
 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 @@ initarm(struct arm64_bootparams *abp)
 #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);

Modified: head/sys/arm64/include/efi.h
==============================================================================
--- head/sys/arm64/include/efi.h        Tue Oct 10 13:02:58 2017        
(r324494)
+++ head/sys/arm64/include/efi.h        Tue Oct 10 13:05:26 2017        
(r324495)
@@ -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_ */

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64   Tue Oct 10 13:02:58 2017        (r324494)
+++ head/sys/conf/files.arm64   Tue Oct 10 13:05:26 2017        (r324495)
@@ -95,6 +95,7 @@ arm64/arm64/db_trace.c                optional        ddb
 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

Modified: head/sys/conf/options.arm64
==============================================================================
--- head/sys/conf/options.arm64 Tue Oct 10 13:02:58 2017        (r324494)
+++ head/sys/conf/options.arm64 Tue Oct 10 13:05:26 2017        (r324495)
@@ -7,6 +7,10 @@ SOCDEV_VA                      opt_global.h
 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

Modified: head/sys/modules/Makefile
==============================================================================
--- head/sys/modules/Makefile   Tue Oct 10 13:02:58 2017        (r324494)
+++ head/sys/modules/Makefile   Tue Oct 10 13:05:26 2017        (r324495)
@@ -562,6 +562,7 @@ _cxgb=              cxgb
 
 .if ${MACHINE_CPUARCH} == "aarch64"
 _armv8crypto=  armv8crypto
+_efirt=                efirt
 _em=           em
 .endif
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to