From b20a71113cf63838aadfb9418faf93ffbb15ff85 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Wed, 24 Aug 2022 13:24:37 -0600 Subject: [PATCH] Implement aarch64 switch_to_inner using naked function --- src/context/arch/aarch64.rs | 228 ++++++++++++++++++++++-------------- src/context/arch/x86_64.rs | 1 + 2 files changed, 140 insertions(+), 89 deletions(-) diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs index 205841ba..d8777891 100644 --- a/src/context/arch/aarch64.rs +++ b/src/context/arch/aarch64.rs @@ -2,6 +2,7 @@ use alloc::sync::Arc; use core::arch::asm; use core::mem; use core::sync::atomic::{AtomicBool, Ordering}; +use memoffset::offset_of; use spin::Once; use crate::{push_scratch, pop_scratch}; @@ -307,104 +308,153 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) { } } - switch_to_inner(&mut prev.arch, &mut next.arch); + switch_to_inner(&mut prev.arch, &mut next.arch) } -#[inline(never)] -unsafe extern "C" fn switch_to_inner(prev: &mut Context, next: &mut Context) { - //TODO: use one asm block like x86 - asm!("mov {0}, x8", out(reg) prev.x8); - asm!("mov x8, {0}", in(reg) next.x8); - - asm!("mov {0}, x9", out(reg) prev.x9); - asm!("mov x9, {0}", in(reg) next.x9); - - asm!("mov {0}, x10", out(reg) prev.x10); - asm!("mov x10, {0}", in(reg) next.x10); - - asm!("mov {0}, x11", out(reg) prev.x11); - asm!("mov x11, {0}", in(reg) next.x11); - - asm!("mov {0}, x12", out(reg) prev.x12); - asm!("mov x12, {0}", in(reg) next.x12); - - asm!("mov {0}, x13", out(reg) prev.x13); - asm!("mov x13, {0}", in(reg) next.x13); - - asm!("mov {0}, x14", out(reg) prev.x14); - asm!("mov x14, {0}", in(reg) next.x14); - - asm!("mov {0}, x15", out(reg) prev.x15); - asm!("mov x15, {0}", in(reg) next.x15); - - asm!("mov {0}, x16", out(reg) prev.x16); - asm!("mov x16, {0}", in(reg) next.x16); - - asm!("mov {0}, x17", out(reg) prev.x17); - asm!("mov x17, {0}", in(reg) next.x17); - - asm!("mov {0}, x18", out(reg) prev.x18); - asm!("mov x18, {0}", in(reg) next.x18); - - asm!("mov {0}, x19", out(reg) prev.x19); - asm!("mov x19, {0}", in(reg) next.x19); - - asm!("mov {0}, x20", out(reg) prev.x20); - asm!("mov x20, {0}", in(reg) next.x20); - - asm!("mov {0}, x21", out(reg) prev.x21); - asm!("mov x21, {0}", in(reg) next.x21); - - asm!("mov {0}, x22", out(reg) prev.x22); - asm!("mov x22, {0}", in(reg) next.x22); - - asm!("mov {0}, x23", out(reg) prev.x23); - asm!("mov x23, {0}", in(reg) next.x23); - - asm!("mov {0}, x24", out(reg) prev.x24); - asm!("mov x24, {0}", in(reg) next.x24); - - asm!("mov {0}, x25", out(reg) prev.x25); - asm!("mov x25, {0}", in(reg) next.x25); - - asm!("mov {0}, x26", out(reg) prev.x26); - asm!("mov x26, {0}", in(reg) next.x26); - - asm!("mov {0}, x27", out(reg) prev.x27); - asm!("mov x27, {0}", in(reg) next.x27); - - asm!("mov {0}, x28", out(reg) prev.x28); - asm!("mov x28, {0}", in(reg) next.x28); - - asm!("mov {0}, x29", out(reg) prev.fp); - asm!("mov x29, {0}", in(reg) next.fp); - - asm!("mov {0}, x30", out(reg) prev.lr); - asm!("mov x30, {0}", in(reg) next.lr); - - asm!("mrs {0}, elr_el1", out(reg) prev.elr_el1); - asm!("msr elr_el1, {0}", in(reg) next.elr_el1); +#[naked] +unsafe extern "C" fn switch_to_inner(_prev: &mut Context, _next: &mut Context) { + core::arch::asm!( + " + str x8, [x0, #{off_x8}] + ldr x8, [x1, #{off_x8}] - asm!("mrs {0}, sp_el0", out(reg) prev.sp_el0); - asm!("msr sp_el0, {0}", in(reg) next.sp_el0); + str x9, [x0, #{off_x9}] + ldr x9, [x1, #{off_x9}] - asm!("mrs {0}, tpidr_el0", out(reg) prev.tpidr_el0); - asm!("msr tpidr_el0, {0}", in(reg) next.tpidr_el0); + str x10, [x0, #{off_x10}] + ldr x10, [x1, #{off_x10}] - asm!("mrs {0}, tpidrro_el0", out(reg) prev.tpidrro_el0); - asm!("msr tpidrro_el0, {0}", in(reg) next.tpidrro_el0); + str x11, [x0, #{off_x11}] + ldr x11, [x1, #{off_x11}] - asm!("mrs {0}, spsr_el1", out(reg) prev.spsr_el1); - asm!("msr spsr_el1, {0}", in(reg) next.spsr_el1); + str x12, [x0, #{off_x12}] + ldr x12, [x1, #{off_x12}] - asm!("mrs {0}, esr_el1", out(reg) prev.esr_el1); - asm!("msr esr_el1, {0}", in(reg) next.esr_el1); + str x13, [x0, #{off_x13}] + ldr x13, [x1, #{off_x13}] - asm!("mov {0}, sp", out(reg) prev.sp); - asm!("mov sp, {0}", in(reg) next.sp); + str x14, [x0, #{off_x14}] + ldr x14, [x1, #{off_x14}] - // Jump to switch hook - asm!("b {switch_hook}", switch_hook = sym crate::context::switch_finish_hook); + str x15, [x0, #{off_x15}] + ldr x15, [x1, #{off_x15}] + + str x16, [x0, #{off_x16}] + ldr x16, [x1, #{off_x16}] + + str x17, [x0, #{off_x17}] + ldr x17, [x1, #{off_x17}] + + str x18, [x0, #{off_x18}] + ldr x18, [x1, #{off_x18}] + + str x19, [x0, #{off_x19}] + ldr x19, [x1, #{off_x19}] + + str x20, [x0, #{off_x20}] + ldr x20, [x1, #{off_x20}] + + str x21, [x0, #{off_x21}] + ldr x21, [x1, #{off_x21}] + + str x22, [x0, #{off_x22}] + ldr x22, [x1, #{off_x22}] + + str x23, [x0, #{off_x23}] + ldr x23, [x1, #{off_x23}] + + str x24, [x0, #{off_x24}] + ldr x24, [x1, #{off_x24}] + + str x25, [x0, #{off_x25}] + ldr x25, [x1, #{off_x25}] + + str x26, [x0, #{off_x26}] + ldr x26, [x1, #{off_x26}] + + str x27, [x0, #{off_x27}] + ldr x27, [x1, #{off_x27}] + + str x28, [x0, #{off_x28}] + ldr x28, [x1, #{off_x28}] + + str x29, [x0, #{off_x29}] + ldr x29, [x1, #{off_x29}] + + str x30, [x0, #{off_x30}] + ldr x30, [x1, #{off_x30}] + + mrs x2, elr_el1 + str x2, [x0, #{off_elr_el1}] + ldr x2, [x1, #{off_elr_el1}] + msr elr_el1, x2 + + mrs x2, sp_el0 + str x2, [x0, #{off_sp_el0}] + ldr x2, [x1, #{off_sp_el0}] + msr sp_el0, x2 + + mrs x2, tpidr_el0 + str x2, [x0, #{off_tpidr_el0}] + ldr x2, [x1, #{off_tpidr_el0}] + msr tpidr_el0, x2 + + mrs x2, tpidrro_el0 + str x2, [x0, #{off_tpidrro_el0}] + ldr x2, [x1, #{off_tpidrro_el0}] + msr tpidrro_el0, x2 + + mrs x2, spsr_el1 + str x2, [x0, #{off_spsr_el1}] + ldr x2, [x1, #{off_spsr_el1}] + msr spsr_el1, x2 + + mrs x2, esr_el1 + str x2, [x0, #{off_esr_el1}] + ldr x2, [x1, #{off_esr_el1}] + msr esr_el1, x2 + + mov x2, sp + str x2, [x0, #{off_sp}] + ldr x2, [x1, #{off_sp}] + mov sp, x2 + + b {switch_hook} + ", + off_x8 = const(offset_of!(Context, x8)), + off_x9 = const(offset_of!(Context, x9)), + off_x10 = const(offset_of!(Context, x10)), + off_x11 = const(offset_of!(Context, x11)), + off_x12 = const(offset_of!(Context, x12)), + off_x13 = const(offset_of!(Context, x13)), + off_x14 = const(offset_of!(Context, x14)), + off_x15 = const(offset_of!(Context, x15)), + off_x16 = const(offset_of!(Context, x16)), + off_x17 = const(offset_of!(Context, x17)), + off_x18 = const(offset_of!(Context, x18)), + off_x19 = const(offset_of!(Context, x19)), + off_x20 = const(offset_of!(Context, x20)), + off_x21 = const(offset_of!(Context, x21)), + off_x22 = const(offset_of!(Context, x22)), + off_x23 = const(offset_of!(Context, x23)), + off_x24 = const(offset_of!(Context, x24)), + off_x25 = const(offset_of!(Context, x25)), + off_x26 = const(offset_of!(Context, x26)), + off_x27 = const(offset_of!(Context, x27)), + off_x28 = const(offset_of!(Context, x28)), + off_x29 = const(offset_of!(Context, fp)), + off_x30 = const(offset_of!(Context, lr)), + off_elr_el1 = const(offset_of!(Context, elr_el1)), + off_sp_el0 = const(offset_of!(Context, sp_el0)), + off_tpidr_el0 = const(offset_of!(Context, tpidr_el0)), + off_tpidrro_el0 = const(offset_of!(Context, tpidrro_el0)), + off_spsr_el1 = const(offset_of!(Context, spsr_el1)), + off_esr_el1 = const(offset_of!(Context, esr_el1)), + off_sp = const(offset_of!(Context, sp)), + + switch_hook = sym crate::context::switch_finish_hook, + options(noreturn), + ); } #[allow(dead_code)] diff --git a/src/context/arch/x86_64.rs b/src/context/arch/x86_64.rs index 629179bc..22fcaf11 100644 --- a/src/context/arch/x86_64.rs +++ b/src/context/arch/x86_64.rs @@ -180,6 +180,7 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) { RmmA::set_table(TableKind::User, empty_cr3()); } } + switch_to_inner(&mut prev.arch, &mut next.arch) } -- GitLab