| /* |
| * This file and its contents are supplied under the terms of the |
| * Common Development and Distribution License ("CDDL"), version 1.0. |
| * You may only use this file in accordance with the terms of version |
| * 1.0 of the CDDL. |
| * |
| * A full copy of the text of the CDDL should have accompanied this |
| * source. A copy of the CDDL is also available via the Internet at |
| * http://www.illumos.org/license/CDDL. |
| */ |
| |
| /* |
| * Copyright 2016 Toomas Soome <tsoome@me.com> |
| */ |
| |
| #include <x86/specialreg.h> |
| |
| .file "multiboot_tramp.s" |
| |
| /* |
| * dboot expects a 32-bit multiboot environment and to execute in 32-bit mode. |
| * |
| * EAX: MB magic |
| * EBX: 32-bit physical address of MBI |
| * CS: 32-bit read/execute code segment with offset 0 and limit 0xFFFFFFFF |
| * DS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF |
| * ES: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF |
| * FS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF |
| * GS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF |
| * SS: 32-bit read/write data segment with offset 0 and limit 0xFFFFFFFF |
| * A20 enabled |
| * CR0: PG cleared, PE set |
| * EFLAGS: VM cleared, IF cleared |
| * interrupts disabled |
| */ |
| |
| .set SEL_SCODE,0x8 |
| .set SEL_SDATA,0x10 |
| |
| .text |
| .p2align 4 |
| .globl multiboot_tramp |
| .type multiboot_tramp, STT_FUNC |
| |
| /* |
| * void multiboot_tramp(uint32_t magic, struct relocator *relocator, |
| * vm_offset_t entry) |
| */ |
| multiboot_tramp: |
| cli |
| movq (%rsi), %rax |
| movq %rax, %rsp /* Switch to temporary stack. */ |
| movq 0x8(%rsi), %rax /* relocator->copy */ |
| pushq %rdi /* save magic */ |
| pushq %rdx /* save entry */ |
| movq %rsi, %rdi |
| callq *%rax |
| movq %rax, %rbx /* MBI */ |
| popq %rsi /* entry to rsi */ |
| popq %rdi /* restore magic */ |
| lea gdt(%rip), %rax |
| lea gdtaddr(%rip), %rdx |
| movq %rax, (%rdx) |
| lea gdtdesc(%rip), %rax |
| lgdt (%rax) |
| |
| /* record the address */ |
| lea multiboot_tramp_2(%rip), %rcx |
| movq %rsp, %rax |
| pushq $SEL_SDATA |
| pushq %rax |
| pushf |
| pushq $SEL_SCODE |
| lea multiboot_tramp_1(%rip), %rax |
| pushq %rax |
| iretq |
| |
| .code32 |
| multiboot_tramp_1: |
| movl $SEL_SDATA, %eax |
| movw %ax, %ss |
| movw %ax, %ds |
| movw %ax, %es |
| movw %ax, %fs |
| movw %ax, %gs |
| |
| movl %cr0, %eax /* disable paging */ |
| btrl $31, %eax |
| movl %eax, %cr0 |
| jmp *%ecx |
| multiboot_tramp_2: |
| movl %cr4, %eax /* disable PAE, PGE, PSE */ |
| andl $~(CR4_PGE | CR4_PAE | CR4_PSE), %eax |
| movl %eax, %cr4 |
| movl $MSR_EFER, %ecx |
| rdmsr /* updates %edx:%eax */ |
| btcl $8, %eax /* clear long mode */ |
| wrmsr |
| movl %edi, %eax /* magic */ |
| jmp *%esi /* jump to kernel */ |
| |
| /* GDT record */ |
| .p2align 4 |
| gdt: |
| /* |
| * This will create access for 4GB flat memory with |
| * base = 0x00000000, segment limit = 0xffffffff |
| * page granulariy 4k |
| * 32-bit protected mode |
| * ring 0 |
| * code segment is executable RW |
| * data segment is not-executable RW |
| */ |
| .word 0x0, 0x0 /* NULL entry */ |
| .byte 0x0, 0x0, 0x0, 0x0 |
| .word 0xffff, 0x0 /* code segment */ |
| .byte 0x0, 0x9a, 0xcf, 0x0 |
| .word 0xffff, 0x0 /* data segment */ |
| .byte 0x0, 0x92, 0xcf, 0x0 |
| gdt_end: |
| |
| .p2align 4 |
| gdtdesc: .word gdt_end - gdt - 1 /* limit */ |
| gdtaddr: .long 0 /* base */ |
| .long 0 |
| |
| multiboot_tramp_end: |