riscv64: 添加flush tlb的ipi (#636)

* riscv64: 添加flush tlb的ipi

* update triagebot
This commit is contained in:
LoGin
2024-03-21 21:35:39 +08:00
committed by GitHub
parent b4eb05a17f
commit 70f159a398
6 changed files with 148 additions and 10 deletions

View File

@ -1,4 +1,5 @@
use alloc::vec::Vec;
use sbi_rt::HartMask;
use crate::{
init::boot_params,
@ -10,6 +11,9 @@ use crate::{
/// 栈对齐
pub(super) const STACK_ALIGN: usize = 16;
/// RISC-V的XLEN也就是寄存器的位宽
pub const RISCV_XLEN: usize = core::mem::size_of::<usize>() * 8;
/// 获取当前cpu的id
#[inline]
pub fn current_cpu_id() -> ProcessorId {
@ -21,7 +25,13 @@ pub fn current_cpu_id() -> ProcessorId {
unsafe { (*ptr).current_cpu() }
}
impl Into<HartMask> for ProcessorId {
fn into(self) -> HartMask {
let base = self.data() as usize / RISCV_XLEN;
let offset = self.data() as usize & (RISCV_XLEN - 1);
HartMask::from_mask_base(offset, base)
}
}
/// 重置cpu
pub unsafe fn cpu_reset() -> ! {
sbi_rt::system_reset(sbi_rt::WarmReboot, sbi_rt::NoReason);

View File

@ -1,6 +1,38 @@
use crate::exception::ipi::{IpiKind, IpiTarget};
use sbi_rt::HartMask;
use crate::{
arch::mm::RiscV64MMArch,
exception::ipi::{IpiKind, IpiTarget},
smp::core::smp_get_processor_id,
};
#[inline(always)]
pub fn send_ipi(kind: IpiKind, target: IpiTarget) {
unimplemented!("RiscV64 send_ipi")
let mask = Into::into(target);
match kind {
IpiKind::KickCpu => todo!(),
IpiKind::FlushTLB => RiscV64MMArch::remote_invalidate_all_with_mask(mask).ok(),
IpiKind::SpecVector(_) => todo!(),
};
}
impl Into<HartMask> for IpiTarget {
fn into(self) -> HartMask {
match self {
IpiTarget::All => HartMask::from_mask_base(usize::MAX, 0),
IpiTarget::Other => {
let data = usize::MAX & (!(1 << smp_get_processor_id().data()));
let mask = HartMask::from_mask_base(data, 0);
mask
}
IpiTarget::Specified(cpu_id) => {
let mask = Into::into(cpu_id);
mask
}
IpiTarget::Current => {
let mask = Into::into(smp_get_processor_id());
mask
}
}
}
}

View File

@ -1,17 +1,23 @@
use acpi::address;
use riscv::register::satp;
use sbi_rt::{HartMask, SbiRet};
use system_error::SystemError;
use crate::{
arch::MMArch,
kdebug,
libs::spinlock::SpinLock,
mm::{
allocator::{
buddy::BuddyAllocator,
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
},
page::PageFlags,
kernel_mapper::KernelMapper,
page::{PageEntry, PageFlags},
ucontext::UserMapper,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
},
smp::cpu::ProcessorId,
};
use self::init::riscv_mm_init;
@ -38,7 +44,47 @@ pub struct RiscV64MMArch;
impl RiscV64MMArch {
pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
/// 使远程cpu的TLB中指定地址范围的页失效
pub fn remote_invalidate_page(
cpu: ProcessorId,
address: VirtAddr,
size: usize,
) -> Result<(), SbiRet> {
let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size);
if r.is_ok() {
return Ok(());
} else {
return Err(r);
}
}
/// 使指定远程cpu的TLB中所有范围的页失效
pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> {
let r = Self::remote_invalidate_page(
cpu,
VirtAddr::new(0),
1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT,
);
return r;
}
pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> {
let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT);
if r.is_ok() {
return Ok(());
} else {
return Err(r);
}
}
}
/// 内核空间起始地址在顶层页表中的索引
const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET
& ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1))
>> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT);
impl MemoryManagementArch for RiscV64MMArch {
const PAGE_SHIFT: usize = 12;
@ -117,16 +163,35 @@ impl MemoryManagementArch for RiscV64MMArch {
satp::set(satp::Mode::Sv39, 0, ppn);
}
fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool {
fn virt_is_valid(virt: VirtAddr) -> bool {
virt.is_canonical()
}
fn initial_page_table() -> crate::mm::PhysAddr {
fn initial_page_table() -> PhysAddr {
todo!()
}
fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> {
todo!()
fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe {
PageMapper::create(PageTableKind::User, LockedFrameAllocator)
.ok_or(SystemError::ENOMEM)?
};
let current_ktable: KernelMapper = KernelMapper::lock();
let copy_mapping = |pml4_entry_no| unsafe {
let entry: PageEntry<RiscV64MMArch> = current_ktable
.table()
.entry(pml4_entry_no)
.unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no));
new_umapper.table().set_entry(pml4_entry_no, entry)
};
// 复制内核的映射
for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 {
copy_mapping(pml4_entry_no);
}
return Ok(crate::mm::ucontext::UserMapper::new(new_umapper));
}
unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {

View File

@ -20,7 +20,11 @@ const CPU_NUM: AtomicU32 = AtomicU32::new(PerCpu::MAX_CPU_NUM);
pub struct PerCpu;
impl PerCpu {
#[cfg(target_arch = "x86_64")]
pub const MAX_CPU_NUM: u32 = 128;
#[cfg(target_arch = "riscv64")]
pub const MAX_CPU_NUM: u32 = 64;
/// # 初始化PerCpu
///
/// 该函数应该在内核初始化时调用一次。

View File

@ -6,7 +6,6 @@ use core::{
use crate::{
arch::{ipc::signal::SigSet, syscall::nr::*},
driver::base::device::device_number::DeviceNumber,
filesystem::vfs::syscall::PosixStatx,
libs::{futex::constant::FutexFlag, rand::GRandFlags},
mm::syscall::MremapFlags,
@ -21,7 +20,6 @@ use crate::{
use num_traits::FromPrimitive;
use system_error::SystemError;
use uefi::proto::debug;
use crate::{
arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch},
@ -99,6 +97,7 @@ impl Syscall {
Self::open(path, flags, mode, true)
}
#[cfg(target_arch = "x86_64")]
SYS_RENAME => {
let oldname: *const u8 = args[0] as *const u8;
let newname: *const u8 = args[1] as *const u8;
@ -111,6 +110,7 @@ impl Syscall {
)
}
#[cfg(target_arch = "x86_64")]
SYS_RENAMEAT => {
let oldfd = args[0] as i32;
let oldname: *const u8 = args[1] as *const u8;
@ -637,6 +637,8 @@ impl Syscall {
#[cfg(target_arch = "x86_64")]
SYS_MKNOD => {
use crate::driver::base::device::device_number::DeviceNumber;
let path = args[0];
let flags = args[1];
let dev_t = args[2];
@ -715,6 +717,7 @@ impl Syscall {
Self::do_statx(fd, path, flags, mask, kstat)
}
#[cfg(target_arch = "x86_64")]
SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32),
SYS_EPOLL_CREATE1 => Self::epoll_create1(args[0]),
@ -725,6 +728,7 @@ impl Syscall {
VirtAddr::new(args[3]),
),
#[cfg(target_arch = "x86_64")]
SYS_EPOLL_WAIT => Self::epoll_wait(
args[0] as i32,
VirtAddr::new(args[1]),