119397407SSherry Moore/* 219397407SSherry Moore * CDDL HEADER START 319397407SSherry Moore * 419397407SSherry Moore * The contents of this file are subject to the terms of the 519397407SSherry Moore * Common Development and Distribution License (the "License"). 619397407SSherry Moore * You may not use this file except in compliance with the License. 719397407SSherry Moore * 819397407SSherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 919397407SSherry Moore * or http://www.opensolaris.org/os/licensing. 1019397407SSherry Moore * See the License for the specific language governing permissions 1119397407SSherry Moore * and limitations under the License. 1219397407SSherry Moore * 1319397407SSherry Moore * When distributing Covered Code, include this CDDL HEADER in each 1419397407SSherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1519397407SSherry Moore * If applicable, add the following below this CDDL HEADER, with the 1619397407SSherry Moore * fields enclosed by brackets "[]" replaced with your own identifying 1719397407SSherry Moore * information: Portions Copyright [yyyy] [name of copyright owner] 1819397407SSherry Moore * 1919397407SSherry Moore * CDDL HEADER END 2019397407SSherry Moore */ 2119397407SSherry Moore 2219397407SSherry Moore/* 2319397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2419397407SSherry Moore * Use is subject to license terms. 2574ecdb51SJohn Levon * Copyright 2018 Joyent, Inc. 2619397407SSherry Moore */ 2719397407SSherry Moore 2819397407SSherry Moore 2919397407SSherry Moore#include <sys/asm_linkage.h> 3019397407SSherry Moore#include <sys/segments.h> 3119397407SSherry Moore#include <sys/controlregs.h> 3219397407SSherry Moore#include <sys/machparam.h> 3319397407SSherry Moore#include <sys/multiboot.h> 3419397407SSherry Moore#include <sys/fastboot.h> 3519397407SSherry Moore#include "assym.h" 3619397407SSherry Moore 3719397407SSherry Moore/* 3819397407SSherry Moore * This code is to switch from 64-bit or 32-bit to protected mode. 3919397407SSherry Moore */ 4019397407SSherry Moore 4119397407SSherry Moore/* 4219397407SSherry Moore * For debugging with LEDs 4319397407SSherry Moore */ 4419397407SSherry Moore#define FB_OUTB_ASM(val) \ 4519397407SSherry Moore movb val, %al; \ 4619397407SSherry Moore outb $0x80; 4719397407SSherry Moore 4819397407SSherry Moore 4919397407SSherry Moore#define DISABLE_PAGING \ 5074ecdb51SJohn Levon movl %cr4, %eax ;\ 5174ecdb51SJohn Levon btrl $17, %eax /* clear PCIDE bit */ ;\ 5274ecdb51SJohn Levon movl %eax, %cr4 ;\ 5319397407SSherry Moore movl %cr0, %eax ;\ 5419397407SSherry Moore btrl $31, %eax /* clear PG bit */ ;\ 5519397407SSherry Moore movl %eax, %cr0 5619397407SSherry Moore 57877400d3SKonstantin Ananyev/* 58877400d3SKonstantin Ananyev * This macro contains common code for 64/32-bit versions of copy_sections(). 59877400d3SKonstantin Ananyev * On entry: 60877400d3SKonstantin Ananyev * fbf points to the fboot_file_t 61877400d3SKonstantin Ananyev * snum contains the number of sections 62877400d3SKonstantin Ananyev * Registers that would be clobbered: 63877400d3SKonstantin Ananyev * fbs, snum, %eax, %ecx, %edi, %esi. 64877400d3SKonstantin Ananyev * NOTE: fb_dest_pa is supposed to be in the first 1GB, 65877400d3SKonstantin Ananyev * therefore it is safe to use 32-bit register to hold it's value 66877400d3SKonstantin Ananyev * even for 64-bit code. 67877400d3SKonstantin Ananyev */ 68877400d3SKonstantin Ananyev 69877400d3SKonstantin Ananyev#define COPY_SECT(fbf, fbs, snum) \ 70877400d3SKonstantin Ananyev lea FB_SECTIONS(fbf), fbs; \ 71877400d3SKonstantin Ananyev xorl %eax, %eax; \ 72877400d3SKonstantin Ananyev1: movl FB_DEST_PA(fbf), %esi; \ 73877400d3SKonstantin Ananyev addl FB_SEC_OFFSET(fbs), %esi; \ 74877400d3SKonstantin Ananyev movl FB_SEC_PADDR(fbs), %edi; \ 75877400d3SKonstantin Ananyev movl FB_SEC_SIZE(fbs), %ecx; \ 76877400d3SKonstantin Ananyev rep \ 77877400d3SKonstantin Ananyev movsb; \ 78877400d3SKonstantin Ananyev /* Zero BSS */ \ 79877400d3SKonstantin Ananyev movl FB_SEC_BSS_SIZE(fbs), %ecx; \ 80877400d3SKonstantin Ananyev rep \ 81877400d3SKonstantin Ananyev stosb; \ 82877400d3SKonstantin Ananyev add $FB_SECTIONS_INCR, fbs; \ 83877400d3SKonstantin Ananyev dec snum; \ 84877400d3SKonstantin Ananyev jnz 1b 85877400d3SKonstantin Ananyev 8619397407SSherry Moore 8719397407SSherry Moore .globl _start 8819397407SSherry Moore_start: 8919397407SSherry Moore 9019397407SSherry Moore /* Disable interrupts */ 9119397407SSherry Moore cli 9219397407SSherry Moore 9319397407SSherry Moore /* Switch to a low memory stack */ 9419397407SSherry Moore movq $_start, %rsp 9519397407SSherry Moore addq $FASTBOOT_STACK_OFFSET, %rsp 9619397407SSherry Moore 9719397407SSherry Moore /* 9819397407SSherry Moore * Copy from old stack to new stack 9919397407SSherry Moore * If the content before fi_valid gets bigger than 0x200 bytes, 10019397407SSherry Moore * the reserved stack size above will need to be changed. 10119397407SSherry Moore */ 10219397407SSherry Moore movq %rdi, %rsi /* source from old stack */ 10319397407SSherry Moore movq %rsp, %rdi /* destination on the new stack */ 10419397407SSherry Moore movq $FI_VALID, %rcx /* size to copy */ 10519397407SSherry Moore rep 10619397407SSherry Moore smovb 10719397407SSherry Moore 10819397407SSherry Moore xorl %eax, %eax 10919397407SSherry Moore xorl %edx, %edx 11019397407SSherry Moore 11119397407SSherry Moore movl $MSR_AMD_FSBASE, %ecx 11219397407SSherry Moore wrmsr 11319397407SSherry Moore 11419397407SSherry Moore movl $MSR_AMD_GSBASE, %ecx 11519397407SSherry Moore wrmsr 11619397407SSherry Moore 11719397407SSherry Moore movl $MSR_AMD_KGSBASE, %ecx 11819397407SSherry Moore wrmsr 11919397407SSherry Moore 12019397407SSherry Moore /* 12119397407SSherry Moore * zero out all the registers to make sure they're 16 bit clean 12219397407SSherry Moore */ 12319397407SSherry Moore xorq %r8, %r8 12419397407SSherry Moore xorq %r9, %r9 12519397407SSherry Moore xorq %r10, %r10 12619397407SSherry Moore xorq %r11, %r11 12719397407SSherry Moore xorq %r12, %r12 12819397407SSherry Moore xorq %r13, %r13 12919397407SSherry Moore xorq %r14, %r14 13019397407SSherry Moore xorq %r15, %r15 13119397407SSherry Moore xorl %eax, %eax 13219397407SSherry Moore xorl %ebx, %ebx 13319397407SSherry Moore xorl %ecx, %ecx 13419397407SSherry Moore xorl %edx, %edx 13519397407SSherry Moore xorl %ebp, %ebp 13619397407SSherry Moore 13719397407SSherry Moore /* 13819397407SSherry Moore * Load our own GDT 13919397407SSherry Moore */ 14019397407SSherry Moore lgdt gdt_info 14119397407SSherry Moore /* 14219397407SSherry Moore * Load our own IDT 14319397407SSherry Moore */ 14419397407SSherry Moore lidt idt_info 14519397407SSherry Moore 146877400d3SKonstantin Ananyev /* 147877400d3SKonstantin Ananyev * Invalidate all TLB entries. 148877400d3SKonstantin Ananyev * Load temporary pagetables to copy kernel and boot-archive 149877400d3SKonstantin Ananyev */ 150877400d3SKonstantin Ananyev movq %cr4, %rax 151877400d3SKonstantin Ananyev andq $_BITNOT(CR4_PGE), %rax 152877400d3SKonstantin Ananyev movq %rax, %cr4 153877400d3SKonstantin Ananyev movq FI_PAGETABLE_PA(%rsp), %rax 154877400d3SKonstantin Ananyev movq %rax, %cr3 155877400d3SKonstantin Ananyev 156877400d3SKonstantin Ananyev leaq FI_FILES(%rsp), %rbx /* offset to the files */ 157877400d3SKonstantin Ananyev 158877400d3SKonstantin Ananyev /* copy unix to final destination */ 159877400d3SKonstantin Ananyev movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */ 160877400d3SKonstantin Ananyev leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi 161877400d3SKonstantin Ananyev call map_copy 162877400d3SKonstantin Ananyev 163877400d3SKonstantin Ananyev /* copy boot archive to final destination */ 164877400d3SKonstantin Ananyev movq FI_LAST_TABLE_PA(%rsp), %rsi /* page table PA */ 165877400d3SKonstantin Ananyev leaq _MUL(FASTBOOT_BOOTARCHIVE, FI_FILES_INCR)(%rbx), %rdi 166877400d3SKonstantin Ananyev call map_copy 167877400d3SKonstantin Ananyev 168*55fea89dSDan Cross /* Copy sections if there are any */ 169877400d3SKonstantin Ananyev leaq _MUL(FASTBOOT_UNIX, FI_FILES_INCR)(%rbx), %rdi 170877400d3SKonstantin Ananyev movl FB_SECTCNT(%rdi), %esi 171877400d3SKonstantin Ananyev cmpl $0, %esi 172877400d3SKonstantin Ananyev je 1f 173877400d3SKonstantin Ananyev call copy_sections 174877400d3SKonstantin Ananyev1: 17519397407SSherry Moore /* 17619397407SSherry Moore * Shut down 64 bit mode. First get into compatiblity mode. 17719397407SSherry Moore */ 17819397407SSherry Moore movq %rsp, %rax 17919397407SSherry Moore pushq $B32DATA_SEL 18019397407SSherry Moore pushq %rax 18119397407SSherry Moore pushf 18219397407SSherry Moore pushq $B32CODE_SEL 18319397407SSherry Moore pushq $1f 18419397407SSherry Moore iretq 18519397407SSherry Moore 18619397407SSherry Moore .code32 18719397407SSherry Moore1: 18819397407SSherry Moore movl $B32DATA_SEL, %eax 18919397407SSherry Moore movw %ax, %ss 19019397407SSherry Moore movw %ax, %ds 19119397407SSherry Moore movw %ax, %es 19219397407SSherry Moore movw %ax, %fs 19319397407SSherry Moore movw %ax, %gs 19419397407SSherry Moore 19519397407SSherry Moore /* 19619397407SSherry Moore * Disable long mode by: 19719397407SSherry Moore * - shutting down paging (bit 31 of cr0). This will flush the 19819397407SSherry Moore * TLBs. 19974ecdb51SJohn Levon * - turning off PCID in cr4 200877400d3SKonstantin Ananyev * - disabling LME (long mode enable) in EFER (extended feature reg) 20119397407SSherry Moore */ 20219397407SSherry Moore DISABLE_PAGING /* clobbers %eax */ 20319397407SSherry Moore 20419397407SSherry Moore ljmp $B32CODE_SEL, $1f 20519397407SSherry Moore1: 20619397407SSherry Moore 20719397407SSherry Moore /* 20819397407SSherry Moore * Clear PGE, PAE and PSE flags as dboot expects them to be 20919397407SSherry Moore * cleared. 21019397407SSherry Moore */ 21119397407SSherry Moore movl %cr4, %eax 21219397407SSherry Moore andl $_BITNOT(CR4_PGE | CR4_PAE | CR4_PSE), %eax 21319397407SSherry Moore movl %eax, %cr4 21419397407SSherry Moore 21519397407SSherry Moore movl $MSR_AMD_EFER, %ecx /* Extended Feature Enable */ 21619397407SSherry Moore rdmsr 21719397407SSherry Moore btcl $8, %eax /* bit 8 Long Mode Enable bit */ 21819397407SSherry Moore wrmsr 21919397407SSherry Moore 22019397407SSherry Mooredboot_jump: 22119397407SSherry Moore /* Jump to dboot */ 22219397407SSherry Moore movl $DBOOT_ENTRY_ADDRESS, %edi 22319397407SSherry Moore movl FI_NEW_MBI_PA(%esp), %ebx 22419397407SSherry Moore movl $MB_BOOTLOADER_MAGIC, %eax 22519397407SSherry Moore jmp *%edi 22619397407SSherry Moore 227877400d3SKonstantin Ananyev .code64 228877400d3SKonstantin Ananyev ENTRY_NP(copy_sections) 229877400d3SKonstantin Ananyev /* 230877400d3SKonstantin Ananyev * On entry 231877400d3SKonstantin Ananyev * %rdi points to the fboot_file_t 232877400d3SKonstantin Ananyev * %rsi contains number of sections 233877400d3SKonstantin Ananyev */ 234877400d3SKonstantin Ananyev movq %rdi, %rdx 235877400d3SKonstantin Ananyev movq %rsi, %r9 236877400d3SKonstantin Ananyev 237877400d3SKonstantin Ananyev COPY_SECT(%rdx, %r8, %r9) 238877400d3SKonstantin Ananyev ret 239877400d3SKonstantin Ananyev SET_SIZE(copy_sections) 240877400d3SKonstantin Ananyev 241877400d3SKonstantin Ananyev ENTRY_NP(map_copy) 242877400d3SKonstantin Ananyev /* 243877400d3SKonstantin Ananyev * On entry 244877400d3SKonstantin Ananyev * %rdi points to the fboot_file_t 245877400d3SKonstantin Ananyev * %rsi has FI_LAST_TABLE_PA(%rsp) 246877400d3SKonstantin Ananyev */ 247877400d3SKonstantin Ananyev 248877400d3SKonstantin Ananyev movq %rdi, %rdx 249877400d3SKonstantin Ananyev movq %rsi, %r8 250877400d3SKonstantin Ananyev movq FB_PTE_LIST_PA(%rdx), %rax /* PA list of the source */ 251877400d3SKonstantin Ananyev movq FB_DEST_PA(%rdx), %rdi /* PA of the destination */ 252877400d3SKonstantin Ananyev 253877400d3SKonstantin Ananyev2: 254877400d3SKonstantin Ananyev movq (%rax), %rcx /* Are we done? */ 255877400d3SKonstantin Ananyev cmpl $FASTBOOT_TERMINATE, %ecx 256877400d3SKonstantin Ananyev je 1f 257877400d3SKonstantin Ananyev 258877400d3SKonstantin Ananyev movq %rcx, (%r8) 259877400d3SKonstantin Ananyev movq %cr3, %rsi /* Reload cr3 */ 260877400d3SKonstantin Ananyev movq %rsi, %cr3 261877400d3SKonstantin Ananyev movq FB_VA(%rdx), %rsi /* Load from VA */ 262877400d3SKonstantin Ananyev movq $PAGESIZE, %rcx 263877400d3SKonstantin Ananyev shrq $3, %rcx /* 8-byte at a time */ 264877400d3SKonstantin Ananyev rep 265877400d3SKonstantin Ananyev smovq 266877400d3SKonstantin Ananyev addq $8, %rax /* Go to next PTE */ 267877400d3SKonstantin Ananyev jmp 2b 268877400d3SKonstantin Ananyev1: 269877400d3SKonstantin Ananyev ret 270*55fea89dSDan Cross SET_SIZE(map_copy) 271877400d3SKonstantin Ananyev 27219397407SSherry Mooreidt_info: 27319397407SSherry Moore .value 0x3ff 27419397407SSherry Moore .quad 0 27519397407SSherry Moore 27619397407SSherry Moore/* 27719397407SSherry Moore * We need to trampoline thru a gdt we have in low memory. 27819397407SSherry Moore */ 27919397407SSherry Moore#include "../boot/boot_gdt.s" 280