| File: | src/sys/arch/amd64/stand/cdboot/../libsa/exec_i386.c |
| Warning: | line 180, column 2 Value stored to 'stack' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: exec_i386.c,v 1.35 2021/10/24 17:49:19 deraadt Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 1997-1998 Michael Shalayeff |
| 5 | * Copyright (c) 1997 Tobias Weingartner |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions |
| 10 | * are met: |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in the |
| 15 | * documentation and/or other materials provided with the distribution. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | * |
| 29 | */ |
| 30 | |
| 31 | #include <sys/param.h> |
| 32 | #include <sys/disklabel.h> |
| 33 | #include <dev/cons.h> |
| 34 | #include <lib/libsa/loadfile.h> |
| 35 | #include <machine/biosvar.h> |
| 36 | #include <machine/pte.h> |
| 37 | #include <machine/specialreg.h> |
| 38 | #include <stand/boot/bootarg.h> |
| 39 | |
| 40 | #include "cmd.h" |
| 41 | #include "disk.h" |
| 42 | #include "libsa.h" |
| 43 | |
| 44 | #ifdef SOFTRAID1 |
| 45 | #include <dev/softraidvar.h> |
| 46 | #include <lib/libsa/softraid.h> |
| 47 | #include "softraid_amd64.h" |
| 48 | #endif |
| 49 | |
| 50 | #define BOOT_DEBUG |
| 51 | |
| 52 | #ifdef BOOT_DEBUG |
| 53 | #define DPRINTF(x...)do { printf(x...); } while(0) do { printf(x); } while(0) |
| 54 | #else |
| 55 | #define DPRINTF(x...)do { printf(x...); } while(0) |
| 56 | #endif /* BOOT_DEBUG */ |
| 57 | |
| 58 | #define LEGACY_KERNEL_ENTRY_POINT0xffffffff81001000ULL 0xffffffff81001000ULL |
| 59 | |
| 60 | typedef void (*startfuncp)(int, int, int, int, int, int, int, int) |
| 61 | __attribute__ ((noreturn)); |
| 62 | |
| 63 | extern void launch_amd64_kernel_long(caddr_t, caddr_t, caddr_t, uint64_t, int, |
| 64 | int, int, uint64_t, int, int, int, uint64_t); |
| 65 | |
| 66 | caddr_t boot_alloc(void); |
| 67 | caddr_t make_kernel_page_tables(uint64_t); |
| 68 | |
| 69 | void ucode_load(void); |
| 70 | extern struct cmd_state cmd; |
| 71 | |
| 72 | char *bootmac = NULL((void *)0); |
| 73 | extern char end[], _start[]; |
| 74 | |
| 75 | caddr_t pt_base_addr; |
| 76 | |
| 77 | #define LONG_KERN_PML4_ADDR10x1000 0x1000 |
| 78 | #define LONG_KERN_PML4_ADDR2(((uint64_t)(end) + ((1 << 12) - 1)) & ~((1 << 12) - 1)) (((uint64_t)(end) + PAGE_MASK((1 << 12) - 1)) & ~PAGE_MASK((1 << 12) - 1)) |
| 79 | |
| 80 | /* |
| 81 | * N.B. - The following must stay in sync with pmap.h (including that here |
| 82 | * causes compile errors related to RBT_HEAD. |
| 83 | */ |
| 84 | #define NKL2_KIMG_ENTRIES64 64 |
| 85 | #define NPDPG512 512 |
| 86 | |
| 87 | void |
| 88 | run_loadfile(uint64_t *marks, int howto) |
| 89 | { |
| 90 | uint64_t entry; |
| 91 | dev_t bootdev = bootdev_dip->bootdev; |
| 92 | size_t ac = BOOTARG_LEN((1 << 12) * 1); |
| 93 | caddr_t av = (caddr_t)BOOTARG_OFF((1 << 12) * 2); |
| 94 | bios_consdev_t cd; |
| 95 | extern int com_speed; /* from bioscons.c */ |
| 96 | extern int com_addr; |
| 97 | bios_ddb_t ddb; |
| 98 | extern int db_console; |
| 99 | bios_bootduid_t bootduid; |
| 100 | caddr_t pml4, stack, new_av; |
| 101 | #ifdef SOFTRAID1 |
| 102 | bios_bootsr_t bootsr; |
| 103 | struct sr_boot_volume *bv; |
| 104 | #endif /* SOFTRAID */ |
| 105 | if (sa_cleanup != NULL((void *)0)) |
| 106 | (*sa_cleanup)(); |
| 107 | |
| 108 | cd.consdev = cn_tab->cn_dev; |
| 109 | cd.conspeed = com_speed; |
| 110 | cd.consaddr = com_addr; |
| 111 | cd.consfreq = 0; |
| 112 | addbootarg(BOOTARG_CONSDEV5, sizeof(cd), &cd); |
| 113 | |
| 114 | if (bootmac != NULL((void *)0)) |
| 115 | addbootarg(BOOTARG_BOOTMAC7, sizeof(bios_bootmac_t), bootmac); |
| 116 | |
| 117 | if (db_console != -1) { |
| 118 | ddb.db_console = db_console; |
| 119 | addbootarg(BOOTARG_DDB8, sizeof(ddb), &ddb); |
| 120 | } |
| 121 | |
| 122 | bcopy(bootdev_dip->disklabel.d_uid, &bootduid.duid, sizeof(bootduid))((void)memmove((&bootduid.duid),(bootdev_dip->disklabel .d_uid),(sizeof(bootduid)))); |
| 123 | addbootarg(BOOTARG_BOOTDUID9, sizeof(bootduid), &bootduid); |
| 124 | |
| 125 | ucode_load(); |
| 126 | |
| 127 | #ifdef SOFTRAID1 |
| 128 | if (bootdev_dip->sr_vol != NULL((void *)0)) { |
| 129 | bv = bootdev_dip->sr_vol; |
| 130 | bzero(&bootsr, sizeof(bootsr))((void)memset((&bootsr),0,(sizeof(bootsr)))); |
| 131 | bcopy(&bv->sbv_uuid, &bootsr.uuid, sizeof(bootsr.uuid))((void)memmove((&bootsr.uuid),(&bv->sbv_uuid),(sizeof (bootsr.uuid)))); |
| 132 | if (bv->sbv_maskkey != NULL((void *)0)) |
| 133 | bcopy(bv->sbv_maskkey, &bootsr.maskkey,((void)memmove((&bootsr.maskkey),(bv->sbv_maskkey),(sizeof (bootsr.maskkey)))) |
| 134 | sizeof(bootsr.maskkey))((void)memmove((&bootsr.maskkey),(bv->sbv_maskkey),(sizeof (bootsr.maskkey)))); |
| 135 | addbootarg(BOOTARG_BOOTSR10, sizeof(bios_bootsr_t), &bootsr); |
| 136 | explicit_bzero(&bootsr, sizeof(bootsr)); |
| 137 | } |
| 138 | |
| 139 | sr_clear_keys(); |
| 140 | #endif /* SOFTRAID */ |
| 141 | |
| 142 | entry = marks[MARK_ENTRY1]; |
| 143 | |
| 144 | printf("entry point at 0x%llx\n", entry); |
| 145 | |
| 146 | pt_base_addr = (caddr_t)LONG_KERN_PML4_ADDR10x1000; |
| 147 | |
| 148 | /* Pass memory map to the kernel */ |
| 149 | mem_pass(); |
| 150 | |
| 151 | makebootargs(av, &ac); |
| 152 | |
| 153 | /* |
| 154 | * Legacy kernels have entry set to 0xffffffff81001000. |
| 155 | * Other entry values indicate kernels that have random |
| 156 | * base VA and launch in 64 bit (long) mode. |
| 157 | */ |
| 158 | if (entry == LEGACY_KERNEL_ENTRY_POINT0xffffffff81001000ULL) { |
| 159 | /* |
| 160 | * Legacy boot code expects entry 0x1001000, so mask |
| 161 | * off the high bits. |
| 162 | */ |
| 163 | entry &= 0xFFFFFFF; |
| 164 | |
| 165 | /* |
| 166 | * Launch a legacy kernel |
| 167 | */ |
| 168 | (*(startfuncp)entry)(howto, bootdev, BOOTARG_APIVER(0x00000002|0x00000004|0x00000008), |
| 169 | marks[MARK_END4] & 0xfffffff, extmem, cnvmem, ac, (int)av); |
| 170 | /* not reached */ |
| 171 | } |
| 172 | |
| 173 | /* |
| 174 | * Launch a long mode/randomly linked (post-6.5) kernel? |
| 175 | */ |
| 176 | new_av = boot_alloc(); /* Replaces old heap */ |
| 177 | memcpy((void *)new_av, av, ac); |
| 178 | |
| 179 | /* Stack grows down, so grab two pages. We'll waste the 2nd */ |
| 180 | stack = boot_alloc(); |
Value stored to 'stack' is never read | |
| 181 | stack = boot_alloc(); |
| 182 | |
| 183 | pml4 = make_kernel_page_tables(entry); |
| 184 | launch_amd64_kernel_long((void *)launch_amd64_kernel_long, |
| 185 | pml4, stack, entry, howto, bootdev, BOOTARG_APIVER(0x00000002|0x00000004|0x00000008), |
| 186 | marks[MARK_END4], extmem, cnvmem, ac, (uint64_t)new_av); |
| 187 | /* not reached */ |
| 188 | } |
| 189 | |
| 190 | void |
| 191 | ucode_load(void) |
| 192 | { |
| 193 | uint32_t model, family, stepping; |
| 194 | uint32_t dummy, signature; |
| 195 | uint32_t vendor[4]; |
| 196 | bios_ucode_t uc; |
| 197 | struct stat sb; |
| 198 | char path[128]; |
| 199 | size_t buflen; |
| 200 | char *buf; |
| 201 | int fd; |
| 202 | |
| 203 | CPUID(0, dummy, vendor[0], vendor[2], vendor[1])__asm volatile("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]), "=d" (vendor[1]) : "a" (0)); |
| 204 | vendor[3] = 0; /* NULL-terminate */ |
| 205 | if (strcmp((char *)vendor, "GenuineIntel") != 0) |
| 206 | return; |
| 207 | |
| 208 | CPUID(1, signature, dummy, dummy, dummy)__asm volatile("cpuid" : "=a" (signature), "=b" (dummy), "=c" (dummy), "=d" (dummy) : "a" (1)); |
| 209 | family = (signature >> 8) & 0x0f; |
| 210 | model = (signature >> 4) & 0x0f; |
| 211 | if (family == 0x6 || family == 0xf) { |
| 212 | family += (signature >> 20) & 0xff; |
| 213 | model += ((signature >> 16) & 0x0f) << 4; |
| 214 | } |
| 215 | stepping = (signature >> 0) & 0x0f; |
| 216 | |
| 217 | snprintf(path, sizeof(path), "%s:/etc/firmware/intel/%02x-%02x-%02x", |
| 218 | cmd.bootdev, family, model, stepping); |
| 219 | |
| 220 | fd = open(path, O_RDONLY0x0000); |
| 221 | if (fd == -1) |
| 222 | return; |
| 223 | |
| 224 | if (fstat(fd, &sb) == -1) |
| 225 | return; |
| 226 | |
| 227 | buflen = sb.st_size; |
| 228 | if (buflen > 256*1024) { |
| 229 | printf("ucode too large\n"); |
| 230 | return; |
| 231 | } |
| 232 | |
| 233 | buf = (char *)(1*1024*1024); |
| 234 | |
| 235 | if (read(fd, buf, buflen) != buflen) { |
| 236 | close(fd); |
| 237 | return; |
| 238 | } |
| 239 | |
| 240 | uc.uc_addr = (uint64_t)buf; |
| 241 | uc.uc_size = (uint64_t)buflen; |
| 242 | addbootarg(BOOTARG_UCODE12, sizeof(uc), &uc); |
| 243 | |
| 244 | close(fd); |
| 245 | } |
| 246 | |
| 247 | /* |
| 248 | * boot_alloc |
| 249 | * |
| 250 | * Special allocator for page table pages and kernel stack |
| 251 | * |
| 252 | * Allocates 1 page (PAGE_SIZE) of data. |
| 253 | * |
| 254 | * We have 2 regions available to us: |
| 255 | * 0x1000 ... 0xF000 : range 1 (stack is at 0xF000) |
| 256 | * end ... 0xA0000 (640KB) : range 2 |
| 257 | * |
| 258 | * We allocate from range 1 until it is complete, then skip to range 2. If |
| 259 | * range 2 is exhausted, we panic. |
| 260 | * |
| 261 | * Return value: |
| 262 | * VA of requested allocation |
| 263 | */ |
| 264 | caddr_t |
| 265 | boot_alloc(void) |
| 266 | { |
| 267 | caddr_t ret; |
| 268 | static caddr_t cur = 0; |
| 269 | static int skipped = 0; |
| 270 | |
| 271 | /* First time? */ |
| 272 | if (cur == 0) |
| 273 | cur = (caddr_t)pt_base_addr; |
| 274 | |
| 275 | ret = cur; |
| 276 | |
| 277 | if (((uint64_t)cur + PAGE_SIZE(1 << 12) >= 0xF000) && !skipped) { |
| 278 | cur = (caddr_t)LONG_KERN_PML4_ADDR2(((uint64_t)(end) + ((1 << 12) - 1)) & ~((1 << 12) - 1)); |
| 279 | skipped = 1; |
| 280 | } else |
| 281 | cur += PAGE_SIZE(1 << 12); |
| 282 | |
| 283 | if ((uint64_t)cur >= 640 * 1024) |
| 284 | panic("out of memory"); |
| 285 | |
| 286 | return ret; |
| 287 | } |
| 288 | |
| 289 | /* |
| 290 | * make_kernel_page_tables |
| 291 | * |
| 292 | * Sets up a minimal set of page tables for early use in the kernel. In |
| 293 | * pre_init_x86_64, the kernel will rebuild its page tables, so the |
| 294 | * table constructed here only needs the minimal mapping. |
| 295 | * |
| 296 | * [entry ... end] => PA 0x1000000 (16MB, the current phys loadaddr) |
| 297 | * |
| 298 | * In BIOS boot mode, this function overwrites the heap with the long |
| 299 | * mode kernel bootstrap page tables and thus must be called immediately |
| 300 | * before switching to long mode and starting the kernel. |
| 301 | * |
| 302 | * Parameters: |
| 303 | * entry_lo: the low byte (masked) of the kernel entry point |
| 304 | * |
| 305 | * Return value: |
| 306 | * PML4 PA of the new table |
| 307 | */ |
| 308 | caddr_t |
| 309 | make_kernel_page_tables(uint64_t entry) |
| 310 | { |
| 311 | uint64_t *pml4, *pml3, *pml2, *pml1; |
| 312 | int i, j, k, kern_pml4, kern_pml3, kern_pml2, kern_pml1; |
| 313 | |
| 314 | kern_pml4 = (entry & L4_MASK0x0000ff8000000000UL) >> L4_SHIFT39; |
| 315 | kern_pml3 = (entry & L3_MASK0x0000007fc0000000UL) >> L3_SHIFT30; |
| 316 | kern_pml2 = (entry & L2_MASK0x000000003fe00000UL) >> L2_SHIFT21; |
| 317 | kern_pml1 = (entry & L1_MASK0x00000000001ff000UL) >> L1_SHIFT12; |
| 318 | |
| 319 | pml4 = (uint64_t *)boot_alloc(); |
| 320 | |
| 321 | /* Map kernel */ |
| 322 | pml3 = (uint64_t *)boot_alloc(); |
| 323 | pml4[kern_pml4] = (uint64_t)pml3 | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; |
| 324 | |
| 325 | pml2 = (uint64_t *)boot_alloc(); |
| 326 | pml3[kern_pml3] = (uint64_t)pml2 | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; |
| 327 | |
| 328 | for (i = 0; i < NKL2_KIMG_ENTRIES64; i++) { |
| 329 | pml1 = (uint64_t *)boot_alloc(); |
| 330 | pml2[i + kern_pml2] = (uint64_t)pml1 | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; |
| 331 | |
| 332 | /* The first page of PTEs may start at a different offset */ |
| 333 | if (i == kern_pml2) |
| 334 | k = kern_pml1; |
| 335 | else |
| 336 | k = 0; |
| 337 | |
| 338 | /* |
| 339 | * Map [k...511] PTEs. |
| 340 | */ |
| 341 | for (j = k; j < NPDPG512; j++) |
| 342 | pml1[j] = (uint64_t)(((8 + i) * NBPD_L2(1ULL << 21)) + |
| 343 | (j - kern_pml1) * PAGE_SIZE(1 << 12)) | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; |
| 344 | } |
| 345 | |
| 346 | /* Map first 4GB phys for kernel page table, stack, and bootstrap */ |
| 347 | pml3 = (uint64_t *)boot_alloc(); |
| 348 | pml4[0] = (uint64_t)pml3 | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; /* Covers 0-512GB */ |
| 349 | |
| 350 | pml2 = (uint64_t *)boot_alloc(); |
| 351 | pml3[0] = (uint64_t)pml2 | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL; /* Covers 0-1GB */ |
| 352 | |
| 353 | for (i = 0; i < NPDPG512; i++) |
| 354 | pml2[i] = (i << L2_SHIFT21) | PG_V0x0000000000000001UL | PG_RW0x0000000000000002UL | PG_PS0x0000000000000080UL; |
| 355 | |
| 356 | return (caddr_t)pml4; |
| 357 | } |