Reduce complexity of arch-specific assembly

This commit is contained in:
Jeremy Soller
2022-08-19 10:05:24 -06:00
parent 62283649ba
commit 00fbd71519
3 changed files with 70 additions and 43 deletions
+17 -1
View File
@@ -1,5 +1,21 @@
#![no_std]
#![feature(alloc_error_handler, core_intrinsics, lang_items, panic_info_message)]
#![feature(
asm_const,
asm_sym,
alloc_error_handler,
core_intrinsics,
lang_items,
naked_functions,
panic_info_message
)]
#[cfg(target_arch = "x86")]
#[path = "i686.rs"]
pub mod arch;
#[cfg(target_arch = "x86_64")]
#[path = "x86_64.rs"]
pub mod arch;
pub mod exec;
pub mod initfs;
-42
View File
@@ -1,42 +0,0 @@
BITS 64
section .text
global ustart
extern start
ustart:
; Setup a stack.
mov rax, 0x21000384 ; SYS_CLASS_FILE+SYS_ARG_SLICE+SYS_MMAP
mov rdi, 0xFFFFFFFFFFFFFFFF ; dummy `fd`, indicates anonymous map
mov rsi, map ; pointer to Map struct
mov rdx, map_size ; size of Map struct
syscall
; Test for success (nonzero value).
cmp rax, 0
jg .continue
; (failure)
ud2
.continue:
; Subtract 16 since all instructions seem to hate non-canonical RSP values :)
lea rsp, [rax+size-16]
mov rbp, rsp
; Stack has the same alignment as `size`.
call start
; `start` must never return.
ud2
section .rodata
map:
dq 0 ; offset (unused)
dq size
dq flags
dq address - size
map_size equ $ - map
size equ 65536 ; 64 KiB
address equ 0x0000800000000000 ; highest possible (normal) user address, why not
flags equ 0x0006000E ; PROT_READ+PROT_WRITE, MAP_PRIVATE+MAP_FIXED_NOREPLACE
+53
View File
@@ -0,0 +1,53 @@
use core::mem;
use syscall::{
data::Map,
flag::MapFlags,
number::SYS_FMAP,
};
const STACK_SIZE: usize = 64 * 1024; // 64 KiB
static MAP: Map = Map {
offset: 0,
size: STACK_SIZE,
flags: MapFlags::PROT_READ
.union(MapFlags::PROT_WRITE)
.union(MapFlags::MAP_PRIVATE)
.union(MapFlags::MAP_FIXED_NOREPLACE),
address: 0x0000_8000_0000_0000 - STACK_SIZE, // highest possible user address
};
#[naked]
#[no_mangle]
pub unsafe extern "C" fn ustart() {
core::arch::asm!(
"
# Setup a stack.
mov rax, {number}
mov rdi, {fd}
lea rsi, {map} # pointer to Map struct
mov rdx, {map_size} # size of Map struct
syscall
# Test for success (nonzero value).
cmp rax, 0
jg 1f
# (failure)
ud2
1:
# Subtract 16 since all instructions seem to hate non-canonical RSP values :)
lea rsp, [rax+{stack_size}-16]
mov rbp, rsp
# Stack has the same alignment as `size`.
call start
# `start` must never return.
ud2
",
fd = const usize::MAX, // dummy fd indicates anonymous map
map = sym MAP,
map_size = const mem::size_of::<Map>(),
number = const SYS_FMAP,
stack_size = const STACK_SIZE,
options(noreturn),
);
}