diff --git a/src/arch/x86_64/graphical_debug/primitive.rs b/src/arch/x86_64/graphical_debug/primitive.rs index 37b831a..ccf6e8a 100644 --- a/src/arch/x86_64/graphical_debug/primitive.rs +++ b/src/arch/x86_64/graphical_debug/primitive.rs @@ -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") _, + ); } diff --git a/src/arch/x86_64/interrupt/exception.rs b/src/arch/x86_64/interrupt/exception.rs index 67f0987..18b4f06 100644 --- a/src/arch/x86_64/interrupt/exception.rs +++ b/src/arch/x86_64/interrupt/exception.rs @@ -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(); diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index 4357263..b061989 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -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::() // disregard Self - mem::size_of::() * 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; diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index a21b2bb..3767904 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -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 { diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs index 14eb9f4..f5bf75c 100644 --- a/src/arch/x86_64/interrupt/mod.rs +++ b/src/arch/x86_64/interrupt/mod.rs @@ -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)); } } diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index e6678fe..847d3af 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -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) diff --git a/src/arch/x86_64/interrupt/trace.rs b/src/arch/x86_64/interrupt/trace.rs index 459c8ed..f14d198 100644 --- a/src/arch/x86_64/interrupt/trace.rs +++ b/src/arch/x86_64/interrupt/trace.rs @@ -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 diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 6468893..4dbf6f1 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -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; +} diff --git a/src/arch/x86_64/pti.rs b/src/arch/x86_64/pti.rs index c5ca9a8..eb5841c 100644 --- a/src/arch/x86_64/pti.rs +++ b/src/arch/x86_64/pti.rs @@ -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")] diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index 6534ebc..5696997 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -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), + ); } diff --git a/src/arch/x86_64/stop.rs b/src/arch/x86_64/stop.rs index c87b9f0..1000866 100644 --- a/src/arch/x86_64/stop.rs +++ b/src/arch/x86_64/stop.rs @@ -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"); } } diff --git a/src/context/arch/x86_64.rs b/src/context/arch/x86_64.rs index 3415b39..9a68dce 100644 --- a/src/context/arch/x86_64.rs +++ b/src/context/arch/x86_64.rs @@ -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"); } diff --git a/src/lib.rs b/src/lib.rs index 70260c2..96bfcaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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)] diff --git a/syscall b/syscall index a0ea09c..a7d066a 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit a0ea09ceb3380b1d1e878bb18886e13742d34e8a +Subproject commit a7d066a3a2afec2e8e6b3e681ad2938eecc9d1d0