From afd82ba4bb78db554244cffb4d4b336e65f6ffc8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Thu, 25 Aug 2022 09:30:53 -0600 Subject: [PATCH] Save/restore aarch64 FPU regs --- src/context/arch/aarch64.rs | 65 ++++++++++--------------------------- 1 file changed, 17 insertions(+), 48 deletions(-) diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs index 8ccf9e33..eeb654bd 100644 --- a/src/context/arch/aarch64.rs +++ b/src/context/arch/aarch64.rs @@ -1,6 +1,7 @@ use alloc::sync::Arc; use core::arch::asm; use core::mem; +use core::ptr; use core::sync::atomic::{AtomicBool, Ordering}; use memoffset::offset_of; use spin::Once; @@ -30,7 +31,6 @@ pub struct Context { spsr_el1: usize, esr_el1: usize, fx_loadable: bool, - fx_address: usize, sp: usize, /* Stack Pointer (x31) */ lr: usize, /* Link Register (x30) */ fp: usize, /* Frame pointer Register (x29) */ @@ -67,7 +67,6 @@ impl Context { spsr_el1: 0, esr_el1: 0, fx_loadable: false, - fx_address: 0, sp: 0, lr: 0, fp: 0, @@ -135,44 +134,6 @@ impl Context { value } - pub fn get_fx_regs(&self) -> Option<FloatRegisters> { - if !self.fx_loadable { - return None; - } - let mut regs = unsafe { *(self.fx_address as *const FloatRegisters) }; - let mut new_st = regs.fp_simd_regs; - regs.fp_simd_regs = new_st; - Some(regs) - } - - pub fn set_fx_regs(&mut self, mut new: FloatRegisters) -> bool { - if !self.fx_loadable { - return false; - } - - { - let old = unsafe { &*(self.fx_address as *const FloatRegisters) }; - let old_st = new.fp_simd_regs; - let mut new_st = new.fp_simd_regs; - for (new_st, old_st) in new_st.iter_mut().zip(&old_st) { - *new_st = *old_st; - } - new.fp_simd_regs = new_st; - - // Make sure we don't use `old` from now on - } - - unsafe { - *(self.fx_address as *mut FloatRegisters) = new; - } - true - } - - pub fn set_fx(&mut self, address: usize) { - self.fx_address = address; - } - - pub fn dump(&self) { println!("elr_el1: 0x{:016x}", self.elr_el1); println!("sp_el0: 0x{:016x}", self.sp_el0); @@ -209,11 +170,23 @@ impl Context { impl super::Context { pub fn get_fx_regs(&self) -> FloatRegisters { - self.arch.get_fx_regs().expect("TODO: make get_fx_regs always valid") + if !self.arch.fx_loadable { + panic!("TODO: make get_fx_regs always work"); + } + + unsafe { + ptr::read(self.kfx.as_ptr() as *const FloatRegisters) + } } pub fn set_fx_regs(&mut self, mut new: FloatRegisters) { - assert!(self.arch.set_fx_regs(new), "TODO: make set_fx_regs always valid") + if !self.arch.fx_loadable { + panic!("TODO: make set_fx_regs always work"); + } + + unsafe { + ptr::write(self.kfx.as_mut_ptr() as *mut FloatRegisters, new); + } } } @@ -226,8 +199,7 @@ pub unsafe fn empty_cr3() -> rmm::PhysicalAddress { } pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) { - let mut float_regs = &mut *(prev.arch.fx_address as *mut FloatRegisters); - /*TODO: save float regs + let mut float_regs = &mut *(prev.kfx.as_mut_ptr() as *mut FloatRegisters); asm!( "stp q0, q1, [{0}, #16 * 0]", "stp q2, q3, [{0}, #16 * 2]", @@ -251,13 +223,11 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) { out(reg) float_regs.fpcr, out(reg) float_regs.fpsr ); - */ prev.arch.fx_loadable = true; if next.arch.fx_loadable { - let mut float_regs = &mut *(next.arch.fx_address as *mut FloatRegisters); - /*TODO: restore float registers + let mut float_regs = &mut *(next.kfx.as_mut_ptr() as *mut FloatRegisters); asm!( "ldp q0, q1, [{0}, #16 * 0]", "ldp q2, q3, [{0}, #16 * 2]", @@ -281,7 +251,6 @@ pub unsafe fn switch_to(prev: &mut super::Context, next: &mut super::Context) { in(reg) float_regs.fpcr, in(reg) float_regs.fpsr ); - */ } match next.addr_space { -- GitLab