Merge branch 'idiomatic-rust' into 'master'

Replace llvm_asm with asm

See merge request redox-os/kernel!141
This commit is contained in:
Jeremy Soller
2020-08-03 15:09:08 +00:00
14 changed files with 104 additions and 97 deletions

View File

@@ -2,34 +2,44 @@
#[inline(always)]
#[cold]
pub unsafe fn fast_copy(dst: *mut u8, src: *const u8, len: usize) {
llvm_asm!("cld
rep movsb"
:
: "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len)
: "cc", "memory", "rdi", "rsi", "rcx"
: "intel", "volatile");
asm!("cld
rep movsb",
in("rdi") (dst as usize),
in("rsi") (src as usize),
in("rcx") len,
out("cc") _,
out("rdi") _,
out("rsi") _,
out("rcx") _,
);
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[cold]
pub unsafe fn fast_set32(dst: *mut u32, src: u32, len: usize) {
llvm_asm!("cld
rep stosd"
:
: "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len)
: "cc", "memory", "rdi", "rcx"
: "intel", "volatile");
asm!("cld
rep stosd",
in("rdi") (dst as usize),
in("eax") src,
in("rcx") len,
out("cc") _,
out("rdi") _,
out("rcx") _,
);
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
#[cold]
pub unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) {
llvm_asm!("cld
asm!("cld
rep stosq"
:
: "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len)
: "cc", "memory", "rdi", "rcx"
: "intel", "volatile");
in("rdi") (dst as usize),
in("rax") src,
in("rcx") len,
out("cc") _,
out("rdi") _,
out("rcx") _,
);
}

View File

@@ -132,7 +132,7 @@ interrupt_error!(protection, |stack| {
interrupt_error!(page, |stack| {
let cr2: usize;
llvm_asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile");
asm!("mov {}, cr2", out(reg) cr2);
println!("Page fault: {:>016X}", cr2);
stack.dump();
stack_trace();

View File

@@ -1,7 +1,7 @@
use core::mem;
use syscall::IntRegisters;
const FLAG_SINGLESTEP: usize = 1 << 8;
use super::super::flags::*;
#[derive(Default)]
#[repr(packed)]
@@ -123,7 +123,7 @@ impl InterruptStack {
let cs: usize;
unsafe {
llvm_asm!("mov $0, cs" : "=r"(cs) ::: "intel");
asm!("mov {}, cs", out(reg) cs);
}
if self.iret.cs & CPL_MASK == cs & CPL_MASK {
@@ -132,7 +132,7 @@ impl InterruptStack {
+ mem::size_of::<Self>() // disregard Self
- mem::size_of::<usize>() * 2; // well, almost: rsp and ss need to be excluded as they aren't present
unsafe {
llvm_asm!("mov $0, ss" : "=r"(all.ss) ::: "intel");
asm!("mov {}, ss", out(reg) all.ss);
}
} else {
all.rsp = self.iret.rsp;

View File

@@ -24,18 +24,18 @@ unsafe fn ps2_interrupt(_index: usize) {
let data: u8;
let status: u8;
llvm_asm!("
asm!("
sti
nop
cli
in al, 0x64
mov ah, al
in al, 0x60
"
: "={al}"(data), "={ah}"(status)
:
: "memory"
: "intel", "volatile"
mov {}, al
mov {}, ah
",
out(reg_byte) data,
out(reg_byte) status,
);
if status & 1 != 0 {

View File

@@ -18,13 +18,13 @@ pub use super::device::local_apic::bsp_apic_id;
/// Clear interrupts
#[inline(always)]
pub unsafe fn disable() {
llvm_asm!("cli" : : : : "intel", "volatile");
asm!("cli", options(nomem, nostack));
}
/// Set interrupts
#[inline(always)]
pub unsafe fn enable() {
llvm_asm!("sti" : : : : "intel", "volatile");
asm!("sti", options(nomem, nostack));
}
/// Set interrupts and halt
@@ -32,9 +32,7 @@ pub unsafe fn enable() {
/// Performing enable followed by halt is not guaranteed to be atomic, use this instead!
#[inline(always)]
pub unsafe fn enable_and_halt() {
llvm_asm!("sti
hlt"
: : : : "intel", "volatile");
asm!("sti; hlt", options(nomem, nostack));
}
/// Set interrupts and nop
@@ -42,20 +40,18 @@ pub unsafe fn enable_and_halt() {
/// Simply enabling interrupts does not gurantee that they will trigger, use this instead!
#[inline(always)]
pub unsafe fn enable_and_nop() {
llvm_asm!("sti
nop"
: : : : "intel", "volatile");
asm!("sti; nop", options(nomem, nostack));
}
/// Halt instruction
#[inline(always)]
pub unsafe fn halt() {
llvm_asm!("hlt" : : : : "intel", "volatile");
asm!("hlt", options(nomem, nostack));
}
/// Pause instruction
/// Safe because it is similar to a NOP, and has no memory effects
#[inline(always)]
pub fn pause() {
unsafe { llvm_asm!("pause" : : : : "intel", "volatile"); }
unsafe { asm!("pause", options(nomem, nostack)); }
}

View File

@@ -41,7 +41,7 @@ pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack)
with_interrupt_stack!(|stack| {
// Set a restore point for clone
let rbp;
llvm_asm!("" : "={rbp}"(rbp) : : : "intel", "volatile");
asm!("mov {}, rbp", out(reg) rbp);
let scratch = &stack.scratch;
syscall::syscall(scratch.rax, scratch.rdi, scratch.rsi, scratch.rdx, scratch.r10, scratch.r8, rbp, stack)
@@ -104,7 +104,7 @@ interrupt_stack!(syscall, |stack| {
// Set a restore point for clone
let rbp;
llvm_asm!("" : "={rbp}"(rbp) : : : "intel", "volatile");
asm!("mov {}, rbp", out(reg) rbp);
let scratch = &stack.scratch;
syscall::syscall(scratch.rax, stack.preserved.rbx, scratch.rcx, scratch.rdx, scratch.rsi, scratch.rdi, rbp, stack)

View File

@@ -9,7 +9,7 @@ use crate::paging::{ActivePageTable, VirtualAddress};
#[inline(never)]
pub unsafe fn stack_trace() {
let mut rbp: usize;
llvm_asm!("" : "={rbp}"(rbp) : : : "intel", "volatile");
asm!("mov {}, rbp", out(reg) rbp);
println!("TRACE: {:>016X}", rbp);
//Maximum 64 frames

View File

@@ -35,3 +35,9 @@ pub mod start;
/// Stop function
pub mod stop;
// Flags
pub mod flags {
pub const FLAG_SINGLESTEP: usize = 1 << 8;
pub const FLAG_INTERRUPTS: usize = 1 << 9;
}

View File

@@ -20,7 +20,7 @@ pub static mut PTI_CONTEXT_STACK: usize = 0;
#[inline(always)]
unsafe fn switch_stack(old: usize, new: usize) {
let old_rsp: usize;
llvm_asm!("" : "={rsp}"(old_rsp) : : : "intel", "volatile");
asm!("", out("rsp") old_rsp);
let offset_rsp = old - old_rsp;
@@ -32,7 +32,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
offset_rsp
);
llvm_asm!("" : : "{rsp}"(new_rsp) : : "intel", "volatile");
asm!("", out("rsp") new_rsp);
}
#[cfg(feature = "pti")]

View File

@@ -12,6 +12,7 @@ use crate::acpi;
#[cfg(feature = "graphical_debug")]
use crate::arch::x86_64::graphical_debug;
use crate::arch::x86_64::pti;
use crate::arch::x86_64::flags::*;
use crate::device;
use crate::gdt;
use crate::idt;
@@ -237,32 +238,30 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize, singlestep: bool) -> ! {
let mut flags = 1 << 9;
let mut flags = FLAG_INTERRUPTS;
if singlestep {
flags |= 1 << 8;
flags |= FLAG_SINGLESTEP;
}
llvm_asm!("push r10
asm!("push r10
push r11
push r12
push r13
push r14
push r15"
: // No output
: "{r10}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
"{r11}"(sp), // Stack pointer
"{r12}"(flags), // Flags - Set interrupt enable flag
"{r13}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
"{r14}"(ip), // IP
"{r15}"(arg) // Argument
: // No clobbers
: "intel", "volatile");
push r15",
in("r10") (gdt::GDT_USER_DATA << 3 | 3), // Data segment
in("r11") sp, // Stack pointer
in("r12") flags, // Flags
in("r13") (gdt::GDT_USER_CODE << 3 | 3), // Code segment
in("r14") ip, // IP
in("r15") arg, // Argument
);
// Unmap kernel
pti::unmap();
// Go to usermode
llvm_asm!("mov ds, r14d
asm!("mov ds, r14d
mov es, r14d
mov fs, r15d
mov gs, r14d
@@ -283,11 +282,9 @@ pub unsafe fn usermode(ip: usize, sp: usize, arg: usize, singlestep: bool) -> !
xor r15, r15
fninit
pop rdi
iretq"
: // No output because it never returns
: "{r14}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
"{r15}"(gdt::GDT_USER_TLS << 3 | 3) // TLS segment
: // No clobbers because it never returns
: "intel", "volatile");
unreachable!();
iretq",
in("r14") (gdt::GDT_USER_DATA << 3 | 3), // Data segment
in("r15") (gdt::GDT_USER_TLS << 3 | 3), // TLS segment
options(noreturn),
);
}

View File

@@ -15,9 +15,9 @@ pub unsafe extern fn kreset() -> ! {
}
// Use triple fault to guarantee reset
llvm_asm!("cli" : : : : "intel", "volatile");
llvm_asm!("lidt cs:0" : : : : "intel", "volatile");
llvm_asm!("int $$3" : : : : "intel", "volatile");
asm!("cli");
asm!("lidt cs:0");
asm!("int $3");
unreachable!();
}
@@ -47,6 +47,6 @@ pub unsafe extern fn kstop() -> ! {
// Magic code for VMWare. Also a hard lock.
println!("Shutdown with cli hlt");
loop {
llvm_asm!("cli; hlt" : : : : "intel", "volatile");
asm!("cli; hlt");
}
}

View File

@@ -132,42 +132,42 @@ impl Context {
#[inline(never)]
#[naked]
pub unsafe fn switch_to(&mut self, next: &mut Context) {
llvm_asm!("fxsave64 [$0]" : : "r"(self.fx) : "memory" : "intel", "volatile");
asm!("fxsave64 [{}]", in(reg) (self.fx));
self.loadable = true;
if next.loadable {
llvm_asm!("fxrstor64 [$0]" : : "r"(next.fx) : "memory" : "intel", "volatile");
asm!("fxrstor64 [{}]", in(reg) (next.fx));
}else{
llvm_asm!("fninit" : : : "memory" : "intel", "volatile");
asm!("fninit");
}
llvm_asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile");
asm!("mov {}, cr3", out(reg) (self.cr3));
if next.cr3 != self.cr3 {
llvm_asm!("mov cr3, $0" : : "r"(next.cr3) : "memory" : "intel", "volatile");
asm!("mov cr3, {}", in(reg) (next.cr3));
}
llvm_asm!("pushfq ; pop $0" : "=r"(self.rflags) : : "memory" : "intel", "volatile");
llvm_asm!("push $0 ; popfq" : : "r"(next.rflags) : "memory" : "intel", "volatile");
asm!("pushfq ; pop {}", out(reg) (self.rflags));
asm!("push {} ; popfq", in(reg) (next.rflags));
llvm_asm!("mov $0, rbx" : "=r"(self.rbx) : : "memory" : "intel", "volatile");
llvm_asm!("mov rbx, $0" : : "r"(next.rbx) : "memory" : "intel", "volatile");
asm!("mov {}, rbx", out(reg) (self.rbx));
asm!("mov rbx, {}", in(reg) (next.rbx));
llvm_asm!("mov $0, r12" : "=r"(self.r12) : : "memory" : "intel", "volatile");
llvm_asm!("mov r12, $0" : : "r"(next.r12) : "memory" : "intel", "volatile");
asm!("mov {}, r12", out(reg) (self.r12));
asm!("mov r12, {}", in(reg) (next.r12));
llvm_asm!("mov $0, r13" : "=r"(self.r13) : : "memory" : "intel", "volatile");
llvm_asm!("mov r13, $0" : : "r"(next.r13) : "memory" : "intel", "volatile");
asm!("mov {}, r13", out(reg) (self.r13));
asm!("mov r13, {}", in(reg) (next.r13));
llvm_asm!("mov $0, r14" : "=r"(self.r14) : : "memory" : "intel", "volatile");
llvm_asm!("mov r14, $0" : : "r"(next.r14) : "memory" : "intel", "volatile");
asm!("mov {}, r14", out(reg) (self.r14));
asm!("mov r14, {}", in(reg) (next.r14));
llvm_asm!("mov $0, r15" : "=r"(self.r15) : : "memory" : "intel", "volatile");
llvm_asm!("mov r15, $0" : : "r"(next.r15) : "memory" : "intel", "volatile");
asm!("mov {}, r15", out(reg) (self.r15));
asm!("mov r15, {}", in(reg) (next.r15));
llvm_asm!("mov $0, rsp" : "=r"(self.rsp) : : "memory" : "intel", "volatile");
llvm_asm!("mov rsp, $0" : : "r"(next.rsp) : "memory" : "intel", "volatile");
asm!("mov {}, rsp", out(reg) (self.rsp));
asm!("mov rsp, {}", in(reg) (next.rsp));
llvm_asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile");
llvm_asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile");
asm!("mov {}, rbp", out(reg) (self.rbp));
asm!("mov rbp, {}", in(reg) (next.rbp));
// Unset global lock after loading registers but before switch
CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
@@ -199,7 +199,7 @@ unsafe extern fn signal_handler_wrapper() {
}
// Push scratch registers
llvm_asm!("push rax
asm!("push rax
push rcx
push rdx
push rdi
@@ -207,18 +207,17 @@ unsafe extern fn signal_handler_wrapper() {
push r8
push r9
push r10
push r11"
: : : : "intel", "volatile");
push r11");
// Get reference to stack variables
let rsp: usize;
llvm_asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
asm!("mov {}, rsp", out(reg) rsp);
// Call inner rust function
inner(&*(rsp as *const SignalHandlerStack));
// Pop scratch registers, error code, and return
llvm_asm!("pop r11
asm!("pop r11
pop r10
pop r9
pop r8
@@ -227,6 +226,5 @@ unsafe extern fn signal_handler_wrapper() {
pop rdx
pop rcx
pop rax
add rsp, 16"
: : : : "intel", "volatile");
add rsp, 16");
}

View File

@@ -41,7 +41,7 @@
#![deny(unreachable_patterns)]
#![feature(allocator_api)]
#![feature(llvm_asm)]
#![feature(asm)] // TODO: Relax requirements of most asm invocations
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(core_intrinsics)]

Submodule syscall updated: a0ea09ceb3...a7d066a3a2