1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2016 Toomas Soome <tsoome@me.com> 14 */ 15 16#include <x86/specialreg.h> 17 18 .file "multiboot_tramp.s" 19 20/* 21 * dboot expects a 32-bit multiboot environment and to execute in 32-bit mode. 22 * 23 * EAX: MB magic 24 * EBX: 32-bit physical address of MBI 25 * CS: 32-bit read/execute code segment with offset 0 and limit 0xFFFFFFFF 26 * DS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 27 * ES: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 28 * FS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 29 * GS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 30 * SS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF 31 * A20 enabled 32 * CR0: PG cleared, PE set 33 * EFLAGS: VM cleared, IF cleared 34 * interrupts disabled 35 */ 36 37 .set SEL_SCODE,0x8 38 .set SEL_SDATA,0x10 39 40 .text 41 .p2align 4 42 .globl multiboot_tramp 43 .type multiboot_tramp, STT_FUNC 44 45/* 46 * void multiboot_tramp(uint32_t magic, struct relocator *relocator, 47 * vm_offset_t entry) 48 */ 49multiboot_tramp: 50 cli 51 movq (%rsi), %rax 52 movq %rax, %rsp /* Switch to temporary stack. */ 53 movq 0x8(%rsi), %rax /* relocator->copy */ 54 pushq %rdi /* save magic */ 55 pushq %rdx /* save entry */ 56 movq %rsi, %rdi 57 callq *%rax 58 movq %rax, %rbx /* MBI */ 59 popq %rsi /* entry to rsi */ 60 popq %rdi /* restore magic */ 61 lea gdt(%rip), %rax 62 lea gdtaddr(%rip), %rdx 63 movq %rax, (%rdx) 64 lea gdtdesc(%rip), %rax 65 lgdt (%rax) 66 67 /* record the address */ 68 lea multiboot_tramp_2(%rip), %rcx 69 movq %rsp, %rax 70 pushq $SEL_SDATA 71 pushq %rax 72 pushf 73 pushq $SEL_SCODE 74 lea multiboot_tramp_1(%rip), %rax 75 pushq %rax 76 iretq 77 78 .code32 79multiboot_tramp_1: 80 movl $SEL_SDATA, %eax 81 movw %ax, %ss 82 movw %ax, %ds 83 movw %ax, %es 84 movw %ax, %fs 85 movw %ax, %gs 86 87 movl %cr0, %eax /* disable paging */ 88 btrl $31, %eax 89 movl %eax, %cr0 90 jmp *%ecx 91multiboot_tramp_2: 92 movl %cr4, %eax /* disable PAE, PGE, PSE */ 93 andl $~(CR4_PGE | CR4_PAE | CR4_PSE), %eax 94 movl %eax, %cr4 95 movl $MSR_EFER, %ecx 96 rdmsr /* updates %edx:%eax */ 97 btcl $8, %eax /* clear long mode */ 98 wrmsr 99 movl %edi, %eax /* magic */ 100 jmp *%esi /* jump to kernel */ 101 102/* GDT record */ 103 .p2align 4 104gdt: 105/* 106 * This will create access for 4GB flat memory with 107 * base = 0x00000000, segment limit = 0xffffffff 108 * page granulariy 4k 109 * 32-bit protected mode 110 * ring 0 111 * code segment is executable RW 112 * data segment is not-executable RW 113 */ 114 .word 0x0, 0x0 /* NULL entry */ 115 .byte 0x0, 0x0, 0x0, 0x0 116 .word 0xffff, 0x0 /* code segment */ 117 .byte 0x0, 0x9a, 0xcf, 0x0 118 .word 0xffff, 0x0 /* data segment */ 119 .byte 0x0, 0x92, 0xcf, 0x0 120gdt_end: 121 122 .p2align 4 123gdtdesc: .word gdt_end - gdt - 1 /* limit */ 124gdtaddr: .long 0 /* base */ 125 .long 0 126 127multiboot_tramp_end: 128