File: | src/sys/arch/amd64/stand/boot/../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 | } |