1 /* $OpenBSD: exec.c,v 1.8 2020/05/10 11:55:42 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2016 Mark Kettenis 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/reboot.h> 21 #include <dev/cons.h> 22 23 #include <lib/libkern/libkern.h> 24 #include <lib/libsa/loadfile.h> 25 #include <sys/exec_elf.h> 26 27 #include <efi.h> 28 #include <stand/boot/cmd.h> 29 30 #include <machine/armreg.h> 31 32 #include "efiboot.h" 33 #include "libsa.h" 34 #include "fdt.h" 35 36 typedef void (*startfuncp)(void *, void *, void *) __attribute__ ((noreturn)); 37 38 unsigned int cpu_get_dcache_line_size(void); 39 void cpu_flush_dcache(vaddr_t, vsize_t); 40 void cpu_inval_icache(void); 41 42 unsigned int 43 cpu_get_dcache_line_size(void) 44 { 45 uint64_t ctr; 46 unsigned int dcl_size; 47 48 /* Accessible from all security levels */ 49 ctr = READ_SPECIALREG(ctr_el0); 50 51 /* 52 * Relevant field [19:16] is LOG2 53 * of the number of words in DCache line 54 */ 55 dcl_size = CTR_DLINE_SIZE(ctr); 56 57 /* Size of word shifted by cache line size */ 58 return (sizeof(int) << dcl_size); 59 } 60 61 void 62 cpu_flush_dcache(vaddr_t addr, vsize_t len) 63 { 64 uint64_t cl_size; 65 vaddr_t end; 66 67 cl_size = cpu_get_dcache_line_size(); 68 69 /* Calculate end address to clean */ 70 end = addr + len; 71 /* Align start address to cache line */ 72 addr = addr & ~(cl_size - 1); 73 74 for (; addr < end; addr += cl_size) 75 __asm volatile("dc civac, %0" :: "r" (addr) : "memory"); 76 77 /* Full system DSB */ 78 __asm volatile("dsb sy" ::: "memory"); 79 } 80 81 void 82 cpu_inval_icache(void) 83 { 84 __asm volatile( 85 "ic ialluis \n" 86 "dsb ish \n" 87 : : : "memory"); 88 } 89 90 void 91 run_loadfile(uint64_t *marks, int howto) 92 { 93 char args[256]; 94 char *cp; 95 void *fdt; 96 97 strlcpy(args, cmd.path, sizeof(args)); 98 cp = args + strlen(args); 99 100 *cp++ = ' '; 101 *cp = '-'; 102 if (howto & RB_ASKNAME) 103 *++cp = 'a'; 104 if (howto & RB_CONFIG) 105 *++cp = 'c'; 106 if (howto & RB_SINGLE) 107 *++cp = 's'; 108 if (howto & RB_KDB) 109 *++cp = 'd'; 110 if (*cp == '-') 111 *--cp = 0; 112 else 113 *++cp = 0; 114 115 fdt = efi_makebootargs(args, howto); 116 117 efi_cleanup(); 118 119 cpu_flush_dcache(marks[MARK_ENTRY], marks[MARK_END] - marks[MARK_ENTRY]); 120 cpu_inval_icache(); 121 122 cpu_flush_dcache((vaddr_t)fdt, fdt_get_size(fdt)); 123 124 (*(startfuncp)(marks[MARK_ENTRY]))((void *)marks[MARK_END], 0, fdt); 125 126 /* NOTREACHED */ 127 } 128