SchOS/kernel/arch/x86_64/entry.S
Nexoniarz d0f7acf9eb Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP,
a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF
rasteriser, and a Linux-numbered syscall ABI.

No history before this point -- the tree was never under version control.
This commit exists so the rename that follows has something to undo to.
2026-08-09 13:47:01 +02:00

174 lines
No EOL
4.5 KiB
ArmAsm

/* entry.S
*
* Copyright (c) 2013 Brian Swetland
* Modified by Nexoniarz
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#define mboot_magic 0x1badb002
#define mboot_flags 0x00010000
#include "mmu.h"
.code64
.global mboot_header
.global mboot_entry
mboot_header:
.long mboot_magic
.long mboot_flags
.long (-mboot_magic -mboot_flags)
.long mboot_load_addr
.long mboot_load_addr
.long mboot_load_end
.long mboot_bss_end
.long mboot_entry_addr
.code32
mboot_entry:
mov %eax, %ebp
# bootstrap page tables (0x1000 - 0x3000)
xor %eax, %eax
mov $0x1000, %edi
mov $0x2000, %ecx
rep stosb
# Bootstrap page tables (Identity mapping 4GB)
# PML4T[0] i PML4T[256] -> PDPT pod 0x2000
mov $(0x2000 | PTE_P | PTE_W), %edx
mov %edx, 0x1000
mov %edx, 0x1800
# PDPT mapping 4GB using 1GB huge pages
mov $(0x00000000 | PTE_P | PTE_PS | PTE_W), %edx
mov %edx, 0x2000
mov $(0x40000000 | PTE_P | PTE_PS | PTE_W), %edx
mov %edx, 0x2008
mov $(0x80000000 | PTE_P | PTE_PS | PTE_W), %edx
mov %edx, 0x2010
mov $(0xC0000000 | PTE_P | PTE_PS | PTE_W), %edx
mov %edx, 0x2018
mov %ebp, %ebx
.global entry32mp
entry32mp:
mov $0x1000, %eax
mov %eax, %cr3
lgdt (gdtr64 - mboot_header + mboot_load_addr)
mov %cr4, %eax
bts $5, %eax
mov %eax, %cr4
mov $MSR_EFER, %ecx
rdmsr
bts $0, %eax
bts $8, %eax
wrmsr
mov %cr0, %eax
orl $(CR0_PG | CR0_WP | CR0_MP), %eax
mov %eax, %cr0
ljmp $8, $(entry64low - mboot_header + mboot_load_addr)
.align 16
gdtr64:
.word gdt64_end - gdt64_begin - 1;
.quad gdt64_begin - mboot_header + mboot_load_addr
.align 16
gdt64_begin:
.long 0x00000000
.long 0x00000000
.long 0x00000000 # 64-bit code
.long 0x00209800
.long 0x00000000 # 64-bit data
.long 0x00009000
gdt64_end:
.align 16
.code64
entry64low:
movabs $entry64high, %rax
jmp *%rax
.global _start
_start:
entry64high:
xor %rax, %rax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
# Is this an application processor, or the boot processor?
#
# This check used to be a comment saying it had not been written yet, and
# every AP fell straight through into the BSP path below: it set RSP to the
# *boot processor's* stack, passed its own flag to kmain() as a framebuffer
# address, and re-ran the entire bootstrap -- e820_init, kinit1, kvmalloc --
# on a second core sharing one stack with the first. That is the SMP triple
# fault. QEMU hid it for years by never reporting more than one CPU (see
# kernel/arch/x86_64/acpi.c); VMware did not.
#
# EBX is the discriminator, and entryother.S sets it to 1 immediately before
# entering long mode for exactly this purpose. It is safe: on the boot
# processor EBX carries the VESA framebuffer address from the loader, which is
# either zero or a physical MMIO address, and can never be 1.
cmp $1, %ebx
je entry64mp
# Setup initial stack
movabs $0xFFFF800000010000, %rax
mov %rax, %rsp
# Pass VESA address to main (1st argument in RDI)
mov %rbx, %rdi
call kmain
.global __deadloop
__deadloop:
jmp .
entry64mp:
mov $0x7000, %rax
mov -16(%rax), %rsp
jmp mpenter
.global wrmsr
wrmsr:
mov %rdi, %rcx
mov %rsi, %rax
shr $32, %rsi
mov %rsi, %rdx
wrmsr
retq
.global ignore_sysret
ignore_sysret:
mov $-38, %rax
sysretq