blob: e8ba51324ab7d136227d5d8b7680a36868b8dd87 [file] [log] [blame]
/*
* 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: