mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-25 17:33:28 +04:00
Flush I/D cache after copying user code in page fault handler
* Now SMP works in real machine with no bugs!!!
This commit is contained in:
parent
444ce34859
commit
acd7ee945a
@ -42,6 +42,7 @@ impl<T: FrameAllocator> MemoryHandler for Delay<T> {
|
|||||||
let entry = pt.map(addr, target);
|
let entry = pt.map(addr, target);
|
||||||
attr.apply(entry);
|
attr.apply(entry);
|
||||||
pt.get_page_slice_mut(addr).copy_from_slice(data);
|
pt.get_page_slice_mut(addr).copy_from_slice(data);
|
||||||
|
pt.flush_cache_copy_user(addr, addr + data.len(), attr.execute);
|
||||||
} else {
|
} else {
|
||||||
// delay map
|
// delay map
|
||||||
self.map(pt, addr, attr);
|
self.map(pt, addr, attr);
|
||||||
@ -60,9 +61,11 @@ impl<T: FrameAllocator> MemoryHandler for Delay<T> {
|
|||||||
entry.update();
|
entry.update();
|
||||||
//init with zero for delay mmap mode
|
//init with zero for delay mmap mode
|
||||||
let data = pt.get_page_slice_mut(addr);
|
let data = pt.get_page_slice_mut(addr);
|
||||||
|
let len = data.len();
|
||||||
for x in data {
|
for x in data {
|
||||||
*x = 0;
|
*x = 0;
|
||||||
}
|
}
|
||||||
|
pt.flush_cache_copy_user(addr, addr + len, false);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
|
|||||||
let entry = pt.map(addr, target);
|
let entry = pt.map(addr, target);
|
||||||
attr.apply(entry);
|
attr.apply(entry);
|
||||||
pt.get_page_slice_mut(addr).copy_from_slice(data);
|
pt.get_page_slice_mut(addr).copy_from_slice(data);
|
||||||
|
pt.flush_cache_copy_user(addr, addr + data.len(), attr.execute);
|
||||||
} else {
|
} else {
|
||||||
// delay map
|
// delay map
|
||||||
self.map(pt, addr, attr);
|
self.map(pt, addr, attr);
|
||||||
@ -63,18 +64,20 @@ impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
|
|||||||
if entry.present() {
|
if entry.present() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let execute = entry.execute();
|
||||||
let frame = self.allocator.alloc().expect("failed to alloc frame");
|
let frame = self.allocator.alloc().expect("failed to alloc frame");
|
||||||
entry.set_target(frame);
|
entry.set_target(frame);
|
||||||
entry.set_present(true);
|
entry.set_present(true);
|
||||||
entry.update();
|
entry.update();
|
||||||
|
|
||||||
self.fill_data(pt, addr);
|
let read_size = self.fill_data(pt, addr);
|
||||||
|
pt.flush_cache_copy_user(addr, addr + read_size, execute);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Read, T: FrameAllocator> File<F, T> {
|
impl<F: Read, T: FrameAllocator> File<F, T> {
|
||||||
fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
|
fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> usize {
|
||||||
let data = pt.get_page_slice_mut(addr);
|
let data = pt.get_page_slice_mut(addr);
|
||||||
let file_offset = addr + self.file_start - self.mem_start;
|
let file_offset = addr + self.file_start - self.mem_start;
|
||||||
let read_size = (self.file_end as isize - file_offset as isize)
|
let read_size = (self.file_end as isize - file_offset as isize)
|
||||||
@ -84,6 +87,7 @@ impl<F: Read, T: FrameAllocator> File<F, T> {
|
|||||||
if read_size != PAGE_SIZE {
|
if read_size != PAGE_SIZE {
|
||||||
data[read_size..].iter_mut().for_each(|x| *x = 0);
|
data[read_size..].iter_mut().for_each(|x| *x = 0);
|
||||||
}
|
}
|
||||||
|
read_size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,9 @@ pub trait PageTable {
|
|||||||
/// Get a mutable reference of the content of a page of virtual address `addr`
|
/// Get a mutable reference of the content of a page of virtual address `addr`
|
||||||
fn get_page_slice_mut<'a>(&mut self, addr: VirtAddr) -> &'a mut [u8];
|
fn get_page_slice_mut<'a>(&mut self, addr: VirtAddr) -> &'a mut [u8];
|
||||||
|
|
||||||
|
/// When copied user data (in page fault handler),maybe need to flush I/D cache.
|
||||||
|
fn flush_cache_copy_user(&mut self, start: VirtAddr, end: VirtAddr, execute: bool);
|
||||||
|
|
||||||
/// Read data from virtual address `addr`
|
/// Read data from virtual address `addr`
|
||||||
/// Used for testing with mock
|
/// Used for testing with mock
|
||||||
fn read(&mut self, _addr: VirtAddr) -> u8 {
|
fn read(&mut self, _addr: VirtAddr) -> u8 {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::consts::SMP_CORES;
|
use crate::consts::SMP_CORES;
|
||||||
use crate::memory::{kernel_offset, phys_to_virt};
|
use crate::memory::{kernel_offset, phys_to_virt};
|
||||||
use aarch64::asm;
|
use aarch64::asm;
|
||||||
|
use core::{cmp, mem};
|
||||||
|
|
||||||
pub use super::board::{CPU_NUM, CPU_SPIN_TABLE};
|
pub use super::board::{CPU_NUM, CPU_SPIN_TABLE};
|
||||||
|
|
||||||
@ -16,14 +17,17 @@ pub unsafe fn start_others() {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
fn slave_startup();
|
fn slave_startup();
|
||||||
}
|
}
|
||||||
for i in 0..core::cmp::min(CPU_NUM, *SMP_CORES) {
|
for i in 0..cmp::min(CPU_NUM, *SMP_CORES) {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let release_addr = phys_to_virt(CPU_SPIN_TABLE[i]) as *mut usize;
|
let release_addr = phys_to_virt(CPU_SPIN_TABLE[i]) as *mut usize;
|
||||||
let entry_addr = kernel_offset(slave_startup as usize);
|
let entry_addr = kernel_offset(slave_startup as usize);
|
||||||
*release_addr = entry_addr;
|
*release_addr = entry_addr;
|
||||||
asm::flush_dcache_line(release_addr as usize);
|
asm::flush_dcache_range(
|
||||||
|
release_addr as usize,
|
||||||
|
release_addr as usize + mem::size_of::<usize>(),
|
||||||
|
);
|
||||||
asm::sev();
|
asm::sev();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Page table implementations for aarch64.
|
//! Page table implementations for aarch64.
|
||||||
|
|
||||||
use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt};
|
use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt};
|
||||||
|
use aarch64::asm::{flush_dcache_range, flush_icache_all};
|
||||||
use aarch64::asm::{tlb_invalidate, tlb_invalidate_all, ttbr_el1_read, ttbr_el1_write};
|
use aarch64::asm::{tlb_invalidate, tlb_invalidate_all, ttbr_el1_read, ttbr_el1_write};
|
||||||
use aarch64::paging::{
|
use aarch64::paging::{
|
||||||
frame::PhysFrame as Frame,
|
frame::PhysFrame as Frame,
|
||||||
@ -70,6 +71,15 @@ impl PageTable for PageTableImpl {
|
|||||||
let vaddr = phys_to_virt(frame.start_address().as_u64() as usize);
|
let vaddr = phys_to_virt(frame.start_address().as_u64() as usize);
|
||||||
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush_cache_copy_user(&mut self, start: usize, end: usize, execute: bool) {
|
||||||
|
if execute {
|
||||||
|
// clean D-cache to PoU to ensure new instructions has been written into memory
|
||||||
|
flush_dcache_range(start, end);
|
||||||
|
// invalidate I-cache to PoU to ensure old instructions has been flushed
|
||||||
|
flush_icache_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_to_page_table(frame: Frame) -> *mut Aarch64PageTable {
|
fn frame_to_page_table(frame: Frame) -> *mut Aarch64PageTable {
|
||||||
|
@ -58,6 +58,8 @@ impl PageTable for PageTableImpl {
|
|||||||
let vaddr = frame.to_kernel_unmapped().as_usize();
|
let vaddr = frame.to_kernel_unmapped().as_usize();
|
||||||
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush_cache_copy_user(&mut self, _start: usize, _end: usize, _execute: bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -66,6 +66,8 @@ impl PageTable for PageTableImpl {
|
|||||||
let vaddr = frame.start_address().as_usize() + PHYSICAL_MEMORY_OFFSET;
|
let vaddr = frame.start_address().as_usize() + PHYSICAL_MEMORY_OFFSET;
|
||||||
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush_cache_copy_user(&mut self, _start: usize, _end: usize, _execute: bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
|
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
|
||||||
|
@ -93,6 +93,8 @@ impl PageTable for PageTableImpl {
|
|||||||
let vaddr = phys_to_virt(frame.start_address().as_u64() as usize);
|
let vaddr = phys_to_virt(frame.start_address().as_u64() as usize);
|
||||||
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flush_cache_copy_user(&mut self, _start: usize, _end: usize, _execute: bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_to_page_table(frame: Frame) -> *mut x86PageTable {
|
fn frame_to_page_table(frame: Frame) -> *mut x86PageTable {
|
||||||
|
Loading…
Reference in New Issue
Block a user