xref: /illumos-gate/usr/src/uts/i86pc/os/fastboot.c (revision 0bb073995ac5a95bd35f2dd790df1ea3d8c2d507)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/segments.h>
31 #include <sys/sysmacros.h>
32 #include <sys/vm.h>
33 
34 #include <sys/proc.h>
35 #include <sys/buf.h>
36 #include <sys/kmem.h>
37 
38 #include <sys/reboot.h>
39 #include <sys/uadmin.h>
40 
41 #include <sys/cred.h>
42 #include <sys/vnode.h>
43 #include <sys/file.h>
44 
45 #include <sys/cmn_err.h>
46 #include <sys/dumphdr.h>
47 #include <sys/bootconf.h>
48 #include <sys/ddidmareq.h>
49 #include <sys/varargs.h>
50 #include <sys/promif.h>
51 #include <sys/modctl.h>
52 
53 #include <vm/hat.h>
54 #include <vm/as.h>
55 #include <vm/page.h>
56 #include <vm/seg.h>
57 #include <vm/hat_i86.h>
58 #include <sys/vm_machparam.h>
59 #include <sys/archsystm.h>
60 #include <sys/machsystm.h>
61 #include <sys/mman.h>
62 #include <sys/x86_archext.h>
63 
64 #include <sys/fastboot.h>
65 #include <sys/machelf.h>
66 #include <sys/kobj.h>
67 #include <sys/multiboot.h>
68 
69 fastboot_info_t newkernel = { 0 };
70 static char fastboot_filename[2][OBP_MAXPATHLEN] = { { 0 }, { 0 }};
71 static x86pte_t ptp_bits = PT_VALID | PT_REF | PT_USER | PT_WRITABLE;
72 static x86pte_t pte_bits =
73     PT_VALID | PT_REF | PT_MOD | PT_NOCONSIST | PT_WRITABLE;
74 static uint_t fastboot_shift_amt_pae[] = {12, 21, 30, 39};
75 
76 
77 int fastboot_debug = 0;
78 int fastboot_contig = 0;
79 
80 /*
81  * Fake starting va for new kernel and boot archive.
82  */
83 static uintptr_t fake_va = FASTBOOT_FAKE_VA;
84 
85 /*
86  * Below 1G for page tables as we are using 2G as the fake virtual address for
87  * the new kernel and boot archive.
88  */
89 static ddi_dma_attr_t fastboot_below_1G_dma_attr = {
90 	DMA_ATTR_V0,
91 	0x0000000008000000ULL,	/* dma_attr_addr_lo: 128MB */
92 	0x000000003FFFFFFFULL,	/* dma_attr_addr_hi: 1G */
93 	0x00000000FFFFFFFFULL,	/* dma_attr_count_max */
94 	0x0000000000001000ULL,	/* dma_attr_align: 4KB */
95 	1,			/* dma_attr_burstsize */
96 	1,			/* dma_attr_minxfer */
97 	0x00000000FFFFFFFFULL,	/* dma_attr_maxxfer */
98 	0x00000000FFFFFFFFULL,	/* dma_attr_seg */
99 	1,			/* dma_attr_sgllen */
100 	0x1000ULL,		/* dma_attr_granular */
101 	0,			/* dma_attr_flags */
102 };
103 
104 static ddi_dma_attr_t fastboot_dma_attr = {
105 	DMA_ATTR_V0,
106 	0x0000000008000000ULL,	/* dma_attr_addr_lo: 128MB */
107 	0x0000000FFFFFFFFFULL,	/* dma_attr_addr_hi: 64GB */
108 	0x00000000FFFFFFFFULL,	/* dma_attr_count_max */
109 	0x0000000000001000ULL,	/* dma_attr_align: 4KB */
110 	1,			/* dma_attr_burstsize */
111 	1,			/* dma_attr_minxfer */
112 	0x00000000FFFFFFFFULL,	/* dma_attr_maxxfer */
113 	0x00000000FFFFFFFFULL,	/* dma_attr_seg */
114 	1,			/* dma_attr_sgllen */
115 	0x1000ULL,		/* dma_attr_granular */
116 	0,			/* dma_attr_flags */
117 };
118 
119 /*
120  * Various information saved from the previous boot to reconstruct
121  * multiboot_info.
122  */
123 extern multiboot_info_t saved_mbi;
124 extern mb_memory_map_t saved_mmap[FASTBOOT_SAVED_MMAP_COUNT];
125 extern struct sol_netinfo saved_drives[FASTBOOT_SAVED_DRIVES_COUNT];
126 extern char saved_cmdline[FASTBOOT_SAVED_CMDLINE_LEN];
127 extern int saved_cmdline_len;
128 
129 extern void* contig_alloc(size_t size, ddi_dma_attr_t *attr,
130     uintptr_t align, int cansleep);
131 
132 /* PRINTLIKE */
133 extern void vprintf(const char *, va_list);
134 
135 
136 /*
137  * Need to be able to get boot_archives from other places
138  */
139 #define	BOOTARCHIVE64	"/platform/i86pc/amd64/boot_archive"
140 #define	BOOTARCHIVE32	"/platform/i86pc/boot_archive"
141 #define	BOOTARCHIVE_FAILSAFE	"/boot/x86.miniroot-safe"
142 #define	FAILSAFE_BOOTFILE	"/boot/platform/i86pc/kernel/unix"
143 
144 static uint_t fastboot_vatoindex(fastboot_info_t *, uintptr_t, int);
145 static void fastboot_map_with_size(fastboot_info_t *, uintptr_t,
146     paddr_t, size_t, int);
147 static void fastboot_build_pagetables(fastboot_info_t *);
148 static int fastboot_build_mbi(char *, fastboot_info_t *);
149 
150 static const char fastboot_enomem_msg[] = "Fastboot: Couldn't allocate 0x%"
151 	PRIx64" bytes below %s to do fast reboot";
152 
153 static void
154 dprintf(char *fmt, ...)
155 {
156 	va_list adx;
157 
158 	if (!fastboot_debug)
159 		return;
160 
161 	va_start(adx, fmt);
162 	vprintf(fmt, adx);
163 	va_end(adx);
164 }
165 
166 
167 /*
168  * Return the index corresponding to a virt address at a given page table level.
169  */
170 static uint_t
171 fastboot_vatoindex(fastboot_info_t *nk, uintptr_t va, int level)
172 {
173 	return ((va >> nk->fi_shift_amt[level]) & (nk->fi_ptes_per_table - 1));
174 }
175 
176 
177 /*
178  * Add mapping from vstart to pstart for the specified size.
179  * Only handles 2 level.  Must use 2M pages.  vstart, pstart
180  * and size should all have been aligned at 2M boundaries.
181  */
182 static void
183 fastboot_map_with_size(fastboot_info_t *nk, uintptr_t vstart, paddr_t pstart,
184     size_t size, int level)
185 {
186 	x86pte_t	pteval, *table;
187 	uintptr_t	vaddr;
188 	paddr_t		paddr;
189 	int		index, l;
190 
191 	table = (x86pte_t *)(nk->fi_pagetable_va);
192 
193 	for (l = nk->fi_top_level; l >= level; l--) {
194 
195 		index = fastboot_vatoindex(nk, vstart, l);
196 
197 		if (l == level) {
198 			/*
199 			 * Last level.  Program the page table entries.
200 			 */
201 			for (vaddr = vstart, paddr = pstart;
202 			    vaddr < vstart + size;
203 			    vaddr += (1ULL << nk->fi_shift_amt[l]),
204 			    paddr += (1ULL << nk->fi_shift_amt[l])) {
205 
206 				uint_t index = fastboot_vatoindex(nk, vaddr, l);
207 
208 				if (l > 0)
209 					pteval = paddr | pte_bits | PT_PAGESIZE;
210 				else
211 					pteval = paddr | pte_bits;
212 
213 				table[index] = pteval;
214 			}
215 		} else if (table[index] & PT_VALID) {
216 			if (l == level)
217 				break;
218 
219 			table = (x86pte_t *)
220 			    ((uintptr_t)(((paddr_t)table[index] & MMU_PAGEMASK)
221 			    - nk->fi_pagetable_pa) + nk->fi_pagetable_va);
222 		} else {
223 			/*
224 			 * Intermediate levels.  Program with either valid
225 			 * bit or PTP bits.
226 			 */
227 			if (l == nk->fi_top_level) {
228 				table[index] = nk->fi_next_table_pa | PT_VALID;
229 			} else {
230 				table[index] = nk->fi_next_table_pa | ptp_bits;
231 			}
232 			table = (x86pte_t *)(nk->fi_next_table_va);
233 			nk->fi_next_table_va += MMU_PAGESIZE;
234 			nk->fi_next_table_pa += MMU_PAGESIZE;
235 		}
236 	}
237 }
238 
239 /*
240  * Build page tables for the lower 1G of physical memory using 2M
241  * pages, and prepare page tables for mapping new kernel and boot
242  * archive pages using 4K pages.
243  */
244 static void
245 fastboot_build_pagetables(fastboot_info_t *nk)
246 {
247 	/*
248 	 * Map lower 1G physical memory.  Use large pages.
249 	 */
250 	fastboot_map_with_size(nk, 0, 0, ONE_GIG, 1);
251 
252 	/*
253 	 * Map one 4K page to get the middle page tables set up.
254 	 */
255 	fake_va = P2ALIGN_TYPED(fake_va, nk->fi_lpagesize, uintptr_t);
256 	fastboot_map_with_size(nk, fake_va,
257 	    nk->fi_files[0].fb_pte_list_va[0] & MMU_PAGEMASK, PAGESIZE, 0);
258 }
259 
260 
261 /*
262  * Sanity check.  Look for dboot offset.
263  */
264 static int
265 fastboot_elf64_find_dboot_load_offset(void *img, off_t imgsz, uint32_t *offp)
266 {
267 	Elf64_Ehdr	*ehdr = (Elf64_Ehdr *)img;
268 	Elf64_Phdr	*phdr;
269 	uint8_t		*phdrbase;
270 	int		i;
271 
272 	if ((ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize) >= imgsz)
273 		return (-1);
274 
275 	phdrbase = (uint8_t *)img + ehdr->e_phoff;
276 
277 	for (i = 0; i < ehdr->e_phnum; i++) {
278 		phdr = (Elf64_Phdr *)(phdrbase + ehdr->e_phentsize * i);
279 
280 		if (phdr->p_type == PT_LOAD) {
281 			if (phdr->p_vaddr == phdr->p_paddr &&
282 			    phdr->p_vaddr == DBOOT_ENTRY_ADDRESS) {
283 				ASSERT(phdr->p_offset <= UINT32_MAX);
284 				*offp = (uint32_t)phdr->p_offset;
285 				return (0);
286 			}
287 		}
288 	}
289 
290 	return (-1);
291 }
292 
293 
294 /*
295  * Initialize text and data section information for 32-bit kernel.
296  */
297 static int
298 fastboot_elf32_find_loadables(void *img, off_t imgsz, fastboot_section_t *sectp,
299     int *sectcntp, uint32_t *offp)
300 {
301 	Elf32_Ehdr	*ehdr = (Elf32_Ehdr *)img;
302 	Elf32_Phdr	*phdr;
303 	uint8_t		*phdrbase;
304 	int		i;
305 	int		used_sections = 0;
306 
307 
308 	if ((ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize) >= imgsz)
309 		return (-1);
310 
311 	phdrbase = (uint8_t *)img + ehdr->e_phoff;
312 
313 	for (i = 0; i < ehdr->e_phnum; i++) {
314 		phdr = (Elf32_Phdr *)(phdrbase + ehdr->e_phentsize * i);
315 
316 		if (phdr->p_type == PT_INTERP)
317 			return (-1);
318 
319 		if (phdr->p_type != PT_LOAD)
320 			continue;
321 
322 		if (phdr->p_vaddr == phdr->p_paddr &&
323 		    phdr->p_paddr == DBOOT_ENTRY_ADDRESS) {
324 			*offp = (uint32_t)phdr->p_offset;
325 		} else {
326 			sectp[used_sections].fb_sec_offset = phdr->p_offset;
327 			sectp[used_sections].fb_sec_paddr = phdr->p_paddr;
328 			sectp[used_sections].fb_sec_size = phdr->p_filesz;
329 			sectp[used_sections].fb_sec_bss_size =
330 			    (phdr->p_filesz < phdr->p_memsz) ?
331 			    (phdr->p_memsz - phdr->p_filesz) : 0;
332 
333 			used_sections++;
334 		}
335 
336 	}
337 
338 	*sectcntp = used_sections;
339 	return (0);
340 }
341 
342 /*
343  * Create multiboot info structure
344  */
345 static int
346 fastboot_build_mbi(char *mdep, fastboot_info_t *nk)
347 {
348 	mb_module_t	*mbp;
349 	uintptr_t	next_addr;
350 	uintptr_t	new_mbi_pa;
351 	size_t		size;
352 	void		*buf = NULL;
353 	size_t		arglen;
354 	char		bootargs[OBP_MAXPATHLEN];
355 
356 	bzero(bootargs, OBP_MAXPATHLEN);
357 
358 	if (mdep != NULL) {
359 		arglen = strlen(mdep) + 1;
360 	} else {
361 		arglen = saved_cmdline_len;
362 	}
363 
364 	size = PAGESIZE + P2ROUNDUP(arglen, PAGESIZE);
365 	buf = contig_alloc(size, &fastboot_below_1G_dma_attr, PAGESIZE, 0);
366 	if (buf == NULL) {
367 		cmn_err(CE_WARN, fastboot_enomem_msg, (uint64_t)size, "1G");
368 		return (-1);
369 	}
370 
371 	bzero(buf, size);
372 
373 	new_mbi_pa = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat, (caddr_t)buf));
374 
375 	hat_devload(kas.a_hat, (caddr_t)new_mbi_pa, size,
376 	    mmu_btop(new_mbi_pa), PROT_READ | PROT_WRITE, HAT_LOAD_NOCONSIST);
377 
378 	nk->fi_new_mbi_pa = (paddr_t)new_mbi_pa;
379 
380 	bcopy(&saved_mbi, (void *)new_mbi_pa, sizeof (multiboot_info_t));
381 
382 	next_addr = new_mbi_pa + sizeof (multiboot_info_t);
383 	((multiboot_info_t *)new_mbi_pa)->mods_addr = next_addr;
384 	mbp = (mb_module_t *)(uintptr_t)next_addr;
385 	mbp->mod_start = newkernel.fi_files[FASTBOOT_BOOTARCHIVE].fb_dest_pa;
386 	mbp->mod_end = newkernel.fi_files[FASTBOOT_BOOTARCHIVE].fb_next_pa;
387 
388 	next_addr += sizeof (mb_module_t);
389 	bcopy(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE], (void *)next_addr,
390 	    strlen(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE]));
391 
392 	mbp->mod_name = next_addr;
393 	mbp->reserved = 0;
394 	next_addr += strlen(fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE]);
395 	*(char *)next_addr = '\0';
396 	next_addr++;
397 	next_addr = P2ROUNDUP_TYPED(next_addr, 16, uintptr_t);
398 
399 	((multiboot_info_t *)new_mbi_pa)->mmap_addr = next_addr;
400 	bcopy((void *)(uintptr_t)saved_mmap, (void *)next_addr,
401 	    saved_mbi.mmap_length);
402 	next_addr += saved_mbi.mmap_length;
403 
404 	((multiboot_info_t *)new_mbi_pa)->drives_addr = next_addr;
405 	bcopy((void *)(uintptr_t)saved_drives, (void *)next_addr,
406 	    saved_mbi.drives_length);
407 	next_addr += saved_mbi.drives_length;
408 
409 	((multiboot_info_t *)new_mbi_pa)->cmdline = next_addr;
410 
411 	if (mdep != NULL) {
412 		bcopy(mdep, (void *)(uintptr_t)
413 		    (((multiboot_info_t *)new_mbi_pa)->cmdline), (arglen - 1));
414 	} else {
415 		bcopy((void *)saved_cmdline, (void *)next_addr, (arglen - 1));
416 	}
417 	/* Terminate the string */
418 	((char *)(intptr_t)next_addr)[arglen - 1] = '\0';
419 
420 	return (0);
421 }
422 
423 
424 void
425 load_kernel(char *mdep)
426 {
427 	struct _buf	*file;
428 	void		*buf = NULL;
429 	uintptr_t	va;
430 	int		i, j;
431 	fastboot_file_t	*fb;
432 	uint32_t	dboot_start_offset;
433 	Ehdr		*ehdr;
434 	char		kern_bootpath[OBP_MAXPATHLEN];
435 	char		bootargs[OBP_MAXPATHLEN];
436 	extern uintptr_t postbootkernelbase;
437 	extern char	fb_swtch_image[];
438 	int bootpath_len = 0;
439 	int is_failsafe = 0;
440 	uintptr_t next_pa = 0;	/* next available physical addr */
441 
442 	ASSERT(fastreboot_capable);
443 
444 	postbootkernelbase = 0;
445 
446 	if (x86_feature & X86_PAE) {
447 		newkernel.fi_has_pae = 1;
448 		newkernel.fi_shift_amt = fastboot_shift_amt_pae;
449 		newkernel.fi_ptes_per_table = 512;
450 		newkernel.fi_lpagesize = (2 << 20);	/* 2M */
451 		newkernel.fi_top_level = 2;
452 	}
453 
454 	bzero(kern_bootpath, OBP_MAXPATHLEN);
455 	bzero(bootargs, OBP_MAXPATHLEN);
456 
457 	/*
458 	 * If mdep is not NULL, it comes in the format of
459 	 *	mountpoint unix args
460 	 */
461 	if (mdep != NULL) {
462 		if (mdep[0] != '-') {
463 			/* First get the root argument */
464 			i = 0;
465 			while (mdep[i] != '\0' && mdep[i] != ' ') {
466 				i++;
467 			}
468 
469 			if (i < 4 || strncmp(&mdep[i-4], "unix", 4) != 0) {
470 				/* mount point */
471 				bcopy(mdep, kern_bootpath, i);
472 				kern_bootpath[i] = '\0';
473 				bootpath_len = i;
474 
475 				/*
476 				 * Get the next argument. It should be unix as
477 				 * we have validated in in halt.c.
478 				 */
479 				if (strlen(mdep) > i) {
480 					mdep += (i + 1);
481 					i = 0;
482 					while (mdep[i] != '\0' &&
483 					    mdep[i] != ' ') {
484 						i++;
485 					}
486 				}
487 
488 			}
489 			bcopy(mdep, kern_bootfile, i);
490 			kern_bootfile[i] = '\0';
491 		} else {
492 			int off = strlen(kern_bootfile);
493 			bcopy(kern_bootfile, bootargs, off);
494 			bcopy(" ", &bootargs[off++], 1);
495 			bcopy(mdep, &bootargs[off], strlen(mdep));
496 			off += strlen(mdep);
497 			bootargs[off] = '\0';
498 			mdep = bootargs;
499 		}
500 	}
501 
502 	/*
503 	 * Make sure we get the null character
504 	 */
505 	bcopy(kern_bootpath, fastboot_filename[FASTBOOT_NAME_UNIX],
506 	    bootpath_len);
507 	bcopy(kern_bootfile,
508 	    &fastboot_filename[FASTBOOT_NAME_UNIX][bootpath_len],
509 	    strlen(kern_bootfile) + 1);
510 
511 	bcopy(kern_bootpath, fastboot_filename[FASTBOOT_NAME_BOOTARCHIVE],
512 	    bootpath_len);
513 
514 	if (bcmp(kern_bootfile, FAILSAFE_BOOTFILE,
515 	    (sizeof (FAILSAFE_BOOTFILE) - 1)) == 0) {
516 		is_failsafe = 1;
517 	}
518 
519 	/*
520 	 * Read in unix and boot_archive
521 	 */
522 	for (i = 0; i < FASTBOOT_MAX_FILES_MAP; i++) {
523 		uint64_t fsize;
524 		size_t fsize_roundup, pt_size;
525 		int page_index;
526 		uintptr_t offset;
527 		int pt_entry_count;
528 		ddi_dma_attr_t dma_attr = fastboot_dma_attr;
529 
530 		dprintf("fastboot_filename[%d] = %s\n",
531 		    i, fastboot_filename[i]);
532 
533 		if ((file = kobj_open_file(fastboot_filename[i])) ==
534 		    (struct _buf *)-1) {
535 			cmn_err(CE_WARN, "Fastboot: Couldn't open %s",
536 			    fastboot_filename[i]);
537 			goto err_out;
538 		}
539 
540 		if (kobj_get_filesize(file, &fsize) != 0) {
541 			cmn_err(CE_WARN,
542 			    "Fastboot: Couldn't get filesize for %s",
543 			    fastboot_filename[i]);
544 			goto err_out;
545 		}
546 
547 		if (i == FASTBOOT_BOOTARCHIVE && is_failsafe) {
548 			/* Adjust low memory for failsafe mode */
549 			fastboot_below_1G_dma_attr.dma_attr_addr_lo =
550 			    dma_attr.dma_attr_addr_lo =
551 			    P2ROUNDUP_TYPED(fsize, PAGESIZE, uint64_t) +
552 			    next_pa;
553 		}
554 
555 		if (!fastboot_contig)
556 			dma_attr.dma_attr_sgllen = (fsize / PAGESIZE) +
557 			    (((fsize % PAGESIZE) == 0) ? 0 : 1);
558 
559 		if ((buf = contig_alloc(fsize, &dma_attr, PAGESIZE, 0))
560 		    == NULL) {
561 			cmn_err(CE_WARN, fastboot_enomem_msg, fsize,
562 			    "64G");
563 			goto err_out;
564 		}
565 
566 		va = P2ROUNDUP_TYPED((uintptr_t)buf, PAGESIZE, uintptr_t);
567 
568 		if (kobj_read_file(file, (char *)va, fsize, 0) < 0) {
569 			cmn_err(CE_WARN, "Fastboot: Couldn't read %s",
570 			    fastboot_filename[i]);
571 			goto err_out;
572 		}
573 
574 		fb = &newkernel.fi_files[i];
575 		fb->fb_va = va;
576 		fb->fb_size = fsize;
577 		fb->fb_sectcnt = 0;
578 
579 		fsize_roundup = P2ROUNDUP_TYPED(fb->fb_size, PAGESIZE, size_t);
580 
581 		/*
582 		 * Allocate one extra page table entry for terminating
583 		 * the list.
584 		 */
585 		pt_entry_count = (fsize_roundup >> PAGESHIFT) + 1;
586 		pt_size = P2ROUNDUP(pt_entry_count * 8, PAGESIZE);
587 
588 		if ((fb->fb_pte_list_va =
589 		    (x86pte_t *)contig_alloc(pt_size,
590 		    &fastboot_below_1G_dma_attr, PAGESIZE, 0)) == NULL) {
591 			cmn_err(CE_WARN, fastboot_enomem_msg,
592 			    (uint64_t)pt_size, "1G");
593 			goto err_out;
594 		}
595 
596 		bzero((void *)(fb->fb_pte_list_va), pt_size);
597 
598 		fb->fb_pte_list_pa = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat,
599 		    (caddr_t)fb->fb_pte_list_va));
600 
601 		for (page_index = 0, offset = 0; offset < fb->fb_size;
602 		    offset += PAGESIZE) {
603 			uint64_t paddr;
604 
605 			paddr = mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat,
606 			    (caddr_t)fb->fb_va + offset));
607 
608 			ASSERT(paddr >= fastboot_dma_attr.dma_attr_addr_lo);
609 
610 			/*
611 			 * Include the pte_bits so we don't have to make
612 			 * it in assembly.
613 			 */
614 			fb->fb_pte_list_va[page_index++] = (x86pte_t)
615 			    (paddr | pte_bits);
616 		}
617 
618 		fb->fb_pte_list_va[page_index] = FASTBOOT_TERMINATE;
619 
620 		if (i == FASTBOOT_UNIX) {
621 			ehdr = (Ehdr *)va;
622 
623 			/*
624 			 * Sanity checks:
625 			 */
626 			for (j = 0; j < SELFMAG; j++) {
627 				if (ehdr->e_ident[j] != ELFMAG[j]) {
628 					cmn_err(CE_WARN, "Fastboot: Bad ELF "
629 					    "signature");
630 					goto err_out;
631 				}
632 			}
633 
634 			if (ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
635 			    ehdr->e_ident[EI_DATA] == ELFDATA2LSB &&
636 			    ehdr->e_machine == EM_386) {
637 
638 				if (fastboot_elf32_find_loadables((void *)va,
639 				    fsize, &fb->fb_sections[0],
640 				    &fb->fb_sectcnt, &dboot_start_offset) < 0) {
641 					cmn_err(CE_WARN, "Fastboot: ELF32 "
642 					    "program section failure");
643 					goto err_out;
644 				}
645 
646 				if (fb->fb_sectcnt == 0) {
647 					cmn_err(CE_WARN, "Fastboot: No ELF32 "
648 					    "program sections found");
649 					goto err_out;
650 				}
651 
652 				if (is_failsafe) {
653 					/* Failsafe boot_archive */
654 					bcopy(BOOTARCHIVE_FAILSAFE,
655 					    &fastboot_filename
656 					    [FASTBOOT_NAME_BOOTARCHIVE]
657 					    [bootpath_len],
658 					    sizeof (BOOTARCHIVE_FAILSAFE));
659 				} else {
660 					bcopy(BOOTARCHIVE32,
661 					    &fastboot_filename
662 					    [FASTBOOT_NAME_BOOTARCHIVE]
663 					    [bootpath_len],
664 					    sizeof (BOOTARCHIVE32));
665 				}
666 
667 			} else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64 &&
668 			    ehdr->e_ident[EI_DATA] == ELFDATA2LSB &&
669 			    ehdr->e_machine == EM_AMD64) {
670 
671 				if (fastboot_elf64_find_dboot_load_offset(
672 				    (void *)va, fsize, &dboot_start_offset)
673 				    != 0) {
674 					cmn_err(CE_WARN, "Fastboot: Couldn't "
675 					    "find ELF64 dboot entry offset");
676 					goto err_out;
677 				}
678 
679 				if ((x86_feature & X86_64) == 0 ||
680 				    newkernel.fi_has_pae == 0) {
681 					cmn_err(CE_WARN, "Fastboot: Cannot "
682 					    "reboot to %s: "
683 					    "not a 64-bit capable system",
684 					    kern_bootfile);
685 					goto err_out;
686 				}
687 
688 				bcopy(BOOTARCHIVE64,
689 				    &fastboot_filename
690 				    [FASTBOOT_NAME_BOOTARCHIVE][bootpath_len],
691 				    sizeof (BOOTARCHIVE64));
692 			} else {
693 				cmn_err(CE_WARN, "Fastboot: Unknown ELF type");
694 				goto err_out;
695 			}
696 
697 			fb->fb_dest_pa = DBOOT_ENTRY_ADDRESS -
698 			    dboot_start_offset;
699 
700 			fb->fb_next_pa = DBOOT_ENTRY_ADDRESS + fsize_roundup;
701 		} else {
702 			fb->fb_dest_pa = newkernel.fi_files[i - 1].fb_next_pa;
703 			fb->fb_next_pa = fb->fb_dest_pa + fsize_roundup;
704 		}
705 
706 		next_pa = fb->fb_next_pa;
707 
708 		kobj_close_file(file);
709 
710 		/*
711 		 * Set fb_va to fake_va
712 		 */
713 		fb->fb_va = fake_va;
714 	}
715 
716 
717 	/*
718 	 * Add the function that will switch us to 32-bit protected mode
719 	 */
720 	fb = &newkernel.fi_files[FASTBOOT_SWTCH];
721 	fb->fb_va = fb->fb_dest_pa = FASTBOOT_SWTCH_PA;
722 	fb->fb_size = PAGESIZE;
723 
724 	/*
725 	 * Map in FASTBOOT_SWTCH_PA
726 	 */
727 	hat_devload(kas.a_hat, (caddr_t)fb->fb_va, MMU_PAGESIZE,
728 	    mmu_btop(fb->fb_dest_pa),
729 	    PROT_READ | PROT_WRITE | PROT_EXEC, HAT_LOAD_NOCONSIST);
730 
731 	bcopy((void *)fb_swtch_image, (void *)fb->fb_va, fb->fb_size);
732 
733 	/*
734 	 * Build the new multiboot_info structure
735 	 */
736 	if (fastboot_build_mbi(mdep, &newkernel) != 0) {
737 		goto err_out;
738 	}
739 
740 	/*
741 	 * Build page table for low 1G physical memory. Use big pages.
742 	 * Allocate 4 pages for the page tables.
743 	 *    1 page for Page-Directory-Pointer Table
744 	 *    2 page for Page Directory
745 	 *    1 page for Page Table.
746 	 * The page table entry will be rewritten to map the physical
747 	 * address as we do the copying.
748 	 */
749 	if (newkernel.fi_has_pae) {
750 		size_t size = MMU_PAGESIZE * 4;
751 
752 		if ((newkernel.fi_pagetable_va = (uintptr_t)
753 		    contig_alloc(size, &fastboot_below_1G_dma_attr,
754 		    PAGESIZE, 0)) == NULL) {
755 			cmn_err(CE_WARN, fastboot_enomem_msg,
756 			    (uint64_t)size, "1G");
757 			goto err_out;
758 		}
759 
760 		bzero((void *)(newkernel.fi_pagetable_va), size);
761 
762 		newkernel.fi_pagetable_pa =
763 		    mmu_ptob((uint64_t)hat_getpfnum(kas.a_hat,
764 		    (caddr_t)newkernel.fi_pagetable_va));
765 
766 		newkernel.fi_last_table_pa = newkernel.fi_pagetable_pa +
767 		    MMU_PAGESIZE * 3;
768 
769 		newkernel.fi_next_table_va = newkernel.fi_pagetable_va +
770 		    MMU_PAGESIZE;
771 		newkernel.fi_next_table_pa = newkernel.fi_pagetable_pa +
772 		    MMU_PAGESIZE;
773 
774 		fastboot_build_pagetables(&newkernel);
775 	}
776 
777 
778 	/* Mark it as valid */
779 	newkernel.fi_valid = 1;
780 	newkernel.fi_magic = FASTBOOT_MAGIC;
781 
782 	return;
783 
784 err_out:
785 	/* XXX Do we need to free up the memory we allocated? */
786 
787 	newkernel.fi_valid = 0;
788 }
789 
790 
791 void
792 fast_reboot()
793 {
794 	void (*fastboot_func)(fastboot_info_t *);
795 
796 	fastboot_func = (void (*)())(newkernel.fi_files[FASTBOOT_SWTCH].fb_va);
797 	(*fastboot_func)(&newkernel);
798 }
799