1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/* $OpenBSD: run_i386.S,v 1.2 2022/01/02 05:49:50 jsg Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <machine/asm.h>
#include <machine/specialreg.h>
#define CODE_SEGMENT 0x10
#define DATA_SEGMENT 0x18
.globl _C_LABEL(run_i386_size)
_C_LABEL(run_i386_size):
.long run_i386_end - _C_LABEL(run_i386_start)
.align 4
.text
.globl _C_LABEL(run_i386_start)
_C_LABEL(run_i386_start):
start:
/*
* run_i386(_start) is to call the loaded kernel's start() with
* 32bit segment mode from x64 mode.
* %rdi == loaded start address, %rsi == kernel start address
*/
/* re-arrange the parameters for the x86 calling convention */
mov %edx, (run_i386_end - start - 0x20)(%rdi)
mov %ecx, (run_i386_end - start - 0x1c)(%rdi)
mov %r8d, (run_i386_end - start - 0x18)(%rdi)
mov %r9d, (run_i386_end - start - 0x14)(%rdi)
mov 0x8(%rsp), %edx
mov %edx, (run_i386_end - start - 0x10)(%rdi)
mov 0x10(%rsp), %edx
mov %edx, (run_i386_end - start - 0xc)(%rdi)
mov 0x18(%rsp), %edx
mov %edx, (run_i386_end - start - 0x8)(%rdi)
mov 0x20(%rsp), %edx
mov %edx, (run_i386_end - start - 0x4)(%rdi)
/* Prepare jump address */
lea (start32a - start)(%rdi), %rax
movl %eax, (start32r - start)(%rdi)
cli
/* Setup GDT */
lea (gdt - start)(%rdi), %rax
mov %rax, (gdtrr - start)(%rdi)
lgdt (gdtr - start)(%rdi)
/* Jump to set %cs */
ljmp *(start32r - start)(%rdi)
.align 4
start32a:
.code32
movl $DATA_SEGMENT, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss
lea (run_i386_end - start - 0x20)(%edi), %eax
mov %eax, %esp
/* Disable Paging in CR0 */
movl %cr0, %eax
andl $(~CR0_PG), %eax
movl %eax, %cr0
/* Disable PAE in CR4 */
movl %cr4, %eax
andl $(~CR4_PAE), %eax
movl %eax, %cr4
jmp start32b
start32b:
.code32
call *%esi
.align 4
start32r:
.long 0
.long CODE_SEGMENT
.align 4
gdt:
.long 0, 0
.long 0, 0
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00
.byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00
gdtr:
.word gdtr - gdt
gdtrr:
.quad
start32end:
/* Space for the stack */
.align 4
.space 8192
run_i386_end:
|