]> pd.if.org Git - zos/blobdiff - bootz.s
early bootstrap assembly code
[zos] / bootz.s
diff --git a/bootz.s b/bootz.s
new file mode 100644 (file)
index 0000000..467a9d1
--- /dev/null
+++ b/bootz.s
@@ -0,0 +1,144 @@
+USE64
+
+section .text
+
+; TODO if this were aligned to a page, the kernel
+; could reclaim the memory below it from 0x100000 to the start of this section
+
+; import some symbols from boot32.s
+extern GDT64
+extern GDT_load
+extern multiboot_infoptr
+extern multiboot_magic
+
+; export so that boot32.s can find it
+global kernel_bootstrap:function
+
+; export for the kernel
+global _asm_physmap:data
+
+; I think from here the code expects to be using the high memory addresses
+kernel_bootstrap:
+       ; zero the other segment registers, we aren't going to use them
+       xor rax, rax
+       mov fs, ax
+       mov gs, ax
+
+       ; enable the floating point unit
+       mov rax, cr0
+       and ax, 0xFFFD
+       or ax, 0x10
+       mov cr0, rax
+       fninit
+
+       ; Enable Streaming SIMD Extensions
+       mov rax, cr0
+       and ax, 0xFFFB
+       or ax, 0x2
+       mov cr0, rax
+       mov rax, cr4
+       or rax, 0x600
+       mov cr4, rax
+
+       ; TODO might as well just enable syscall/sysret here
+
+       jmp beginkernel
+.end:
+size kernel_bootstrap (kernel_bootstrap.end - kernel_bootstrap)
+
+section .text
+
+extern stack
+extern kernel_main
+
+global beginkernel
+type beginkernel function
+beginkernel:
+       ; initialize the stack pointer
+       ; hard coded kernel stack.  could be freed later with
+       ; a dynamic stack, but 64 KB should be enough, and I'd
+       ; like to not page fault the kernel, especially for
+       ; a stack issue
+       ; TODO this stack pretty much leaks once tasking is set
+       ; up.  the initial task should probably be freed, and
+       ; the 64 KB handed over to the pmm, or used for DMA or
+       ; something
+       mov rsp, qword stack
+       add rsp, 65536 ; 64 KB, see kernel.c
+
+       ; sets up the 1 GB page maps for the first 512 GB
+       ; doing this early makes the pmm's job easier
+       call mapphys
+
+       ; reload GDT to high memory
+       mov rax, [ qword _asm_physmap ]
+       add rax, GDT64
+       mov qword [GDT_load + 2], rax
+       lgdt [GDT_load]
+
+       ; SysV ABI args for kernel_main, which is written in C
+       mov edi, [multiboot_infoptr]
+       mov esi, [multiboot_magic]
+       call kernel_main
+.end
+size beginkernel beginkernel.end - beginkernel
+
+mapphys:
+       ; rdi, rsi, rdx, rcx, r8, r9
+       ; scratch rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11
+
+       ; now that we're in 64 bit mode, map in the physical memory to
+       ; the high addreses
+       ; set up 1GB PDPT for physical map at 0xFFFFC00000000000
+       ;   1 GB = 0x    4000 0000
+       ; 512 GB = 0x 80 0000 0000
+
+       ; rax = physical address and bits
+       mov eax, 0x183 ; Global, 1 GB PS, RW, and Present bits
+       ; rdi = pdpt slot address, i.e. pdpe address
+       mov rdi, 0x19000
+       ; rsi = (1<<30) i.e. 1 GB
+       mov rsi, 0x40000000 ; 1 GB
+       ; ecx = GB count
+       xor ecx, ecx
+
+       .nextgb
+       stosq
+       add rax, rsi ; next physical address
+       inc ecx
+       cmp ecx, 512 ; could not use ecx and just cmp rdi to 0x2B000
+       jl .nextgb ; I think I can just do a loop .nextgb and skip the inc and cmp
+
+       ; calculate the pml4t offset
+       mov rax, [qword _asm_physmap]
+       mov rdx, rax
+       shr rdx, 39
+       and edx, 0x1ff ; edx is now 384 if the physmap offset is still 0xffffc000000000
+       mov rax, 0x19003 ; physical address of pdpt + ReadWrite and Present
+       mov rdi, cr3
+       ; now, set the pml4e
+       mov [rdi + rdx*8], rax
+
+       ret
+
+global allstop:function
+allstop:
+       mov rax, [rsp]
+       mov dr0, rax
+       cli
+       hlt
+       jmp allstop
+.end
+size allstop, allstop.end - allstop
+
+global halt:function
+halt:
+       sti ; ensure that we can receive interrupts
+       hlt
+       ret
+
+section .data
+
+align 8
+_asm_physmap:
+dq 0xFFFFC00000000000