fix: invalidate TLB on syscall CoW
This commit is contained in:
parent
b97db3a0c4
commit
2b160343b7
@ -4,10 +4,10 @@ use crate::arch::machine;
|
||||
use crate::debug::Level;
|
||||
use crate::dev::irq::{IntController, IrqContext};
|
||||
use crate::mem;
|
||||
use crate::proc::{sched, Thread};
|
||||
use crate::proc::{sched, Process, Thread};
|
||||
use crate::syscall;
|
||||
use cortex_a::registers::{ESR_EL1, FAR_EL1};
|
||||
use libsys::{abi::SystemCall, signal::Signal};
|
||||
use libsys::{abi::SystemCall, signal::Signal, error::Errno};
|
||||
use tock_registers::interfaces::Readable;
|
||||
|
||||
/// Trapped SIMD/FP functionality
|
||||
@ -93,24 +93,21 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
if iss & (1 << 6) != 0 && far < mem::KERNEL_OFFSET && sched::is_ready() {
|
||||
let thread = Thread::current();
|
||||
let proc = thread.owner().unwrap();
|
||||
let asid = proc.asid();
|
||||
|
||||
if proc
|
||||
.manipulate_space(|space| space.try_cow_copy(far))
|
||||
.is_err()
|
||||
{
|
||||
let res = proc.manipulate_space(|space| {
|
||||
space.try_cow_copy(far)?;
|
||||
Process::invalidate_asid(asid);
|
||||
Result::<(), Errno>::Ok(())
|
||||
});
|
||||
|
||||
if res.is_err() {
|
||||
// Kill program
|
||||
errorln!("Data abort from {:#x}", exc.elr_el1);
|
||||
dump_data_abort(Level::Error, esr, far as u64);
|
||||
proc.enter_fault_signal(thread, Signal::SegmentationFault);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
use cortex_a::registers::TTBR0_EL1;
|
||||
let ttbr = TTBR0_EL1.get() as usize;
|
||||
let asid = (ttbr >> 48) & 0xFF;
|
||||
asm!("tlbi aside1, {}", in(reg) (asid << 48));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use crate::mem::{
|
||||
use crate::proc::{
|
||||
wait::Wait, Context, ProcessIo, Thread, ThreadRef, ThreadState, PROCESSES, SCHED, Tid,
|
||||
};
|
||||
use crate::sync::IrqSafeSpinLock;
|
||||
use crate::sync::{IrqSafeSpinLock};
|
||||
use alloc::{rc::Rc, vec::Vec};
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use libsys::{
|
||||
@ -217,6 +217,7 @@ impl Process {
|
||||
|
||||
let space_phys = lock.space.as_mut().unwrap().address_phys();
|
||||
let ttbr0 = space_phys | ((lock.id.asid() as usize) << 48);
|
||||
debugln!("New user thread for {:?}, asid={:#x}", lock.id, lock.id.asid());
|
||||
|
||||
let thread = Thread::new_user(lock.id, entry, stack, arg, ttbr0)?;
|
||||
let tid = thread.id();
|
||||
@ -236,6 +237,7 @@ impl Process {
|
||||
let dst_space = src_inner.space.as_mut().unwrap().fork()?;
|
||||
let dst_space_phys = (dst_space as *mut _ as usize) - mem::KERNEL_OFFSET;
|
||||
let dst_ttbr0 = dst_space_phys | ((dst_id.asid() as usize) << 48);
|
||||
debugln!("New TTBR0 for {:?}, asid={:#x}", dst_id, dst_id.asid());
|
||||
|
||||
let mut threads = Vec::new();
|
||||
let tid = Thread::fork(Some(dst_id), frame, dst_ttbr0)?.id();
|
||||
@ -288,7 +290,7 @@ impl Process {
|
||||
if let Some(space) = lock.space.take() {
|
||||
unsafe {
|
||||
Space::release(space);
|
||||
asm!("tlbi aside1, {}", in(reg) ((lock.id.asid() as usize) << 48));
|
||||
Process::invalidate_asid((lock.id.asid() as usize) << 48);
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,6 +462,21 @@ impl Process {
|
||||
Ok(base + offset)
|
||||
}
|
||||
|
||||
pub fn asid(&self) -> usize {
|
||||
(self.id().asid() as usize) << 48
|
||||
}
|
||||
|
||||
pub fn invalidate_tlb(&self) {
|
||||
Process::invalidate_asid(self.asid());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn invalidate_asid(asid: usize) {
|
||||
unsafe {
|
||||
asm!("tlbi aside1, {}", in(reg) asid);
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a new program into current process address space
|
||||
pub fn execve<F: FnOnce(&mut Space) -> Result<usize, Errno>>(
|
||||
loader: F,
|
||||
@ -525,7 +542,7 @@ impl Process {
|
||||
// TODO drop old context
|
||||
let ctx = thread.ctx.get();
|
||||
let asid = (process_lock.id.asid() as usize) << 48;
|
||||
asm!("tlbi aside1, {}", in(reg) asid);
|
||||
Process::invalidate_asid(asid);
|
||||
|
||||
ctx.write(Context::user(
|
||||
entry,
|
||||
|
@ -122,6 +122,7 @@ pub fn validate_ptr(base: usize, len: usize, write: bool) -> Result<(), Errno> {
|
||||
}
|
||||
|
||||
let process = Process::current();
|
||||
let asid = process.asid();
|
||||
|
||||
for i in (base / mem::PAGE_SIZE)..((base + len + mem::PAGE_SIZE - 1) / mem::PAGE_SIZE) {
|
||||
if !is_el0_accessible(i * mem::PAGE_SIZE, write) {
|
||||
@ -129,7 +130,9 @@ pub fn validate_ptr(base: usize, len: usize, write: bool) -> Result<(), Errno> {
|
||||
// a write access
|
||||
let res = if write {
|
||||
process.manipulate_space(|space| {
|
||||
space.try_cow_copy(i * mem::PAGE_SIZE)
|
||||
space.try_cow_copy(i * mem::PAGE_SIZE)?;
|
||||
Process::invalidate_asid(asid);
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
Err(Errno::DoesNotExist)
|
||||
|
Loading…
x
Reference in New Issue
Block a user