Browse Source

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

* riscv64: 添加flush tlb的ipi

* update triagebot
LoGin 11 months ago
parent
commit
70f159a398

+ 11 - 1
kernel/src/arch/riscv64/cpu.rs

@@ -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);

+ 34 - 2
kernel/src/arch/riscv64/interrupt/ipi.rs

@@ -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
+            }
+        }
+    }
 }

+ 70 - 5
kernel/src/arch/riscv64/mm/mod.rs

@@ -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> {

+ 4 - 0
kernel/src/mm/percpu.rs

@@ -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
     ///
     /// 该函数应该在内核初始化时调用一次。

+ 6 - 2
kernel/src/syscall/mod.rs

@@ -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]),

+ 23 - 0
triagebot.toml

@@ -74,6 +74,16 @@ trigger_files = [
     "kernel/src/filesystem",
 ]
 
+[autolabel."O-x86_64"]
+trigger_files = [
+    "kernel/src/arch/x86_64",
+]
+
+[autolabel."O-riscv64"]
+trigger_files = [
+    "kernel/src/arch/riscv64",
+]
+
 [autolabel."T-driver"]
 trigger_files = [
     "kernel/src/driver",
@@ -133,6 +143,16 @@ filesystem = [
     "@fslongjin"
 ]
 
+riscv64 = [
+    "@fslongjin"
+]
+
+x86_64 = [
+    "@fslongjin",
+    "@GnoCiYeH",
+    "@Chiichen",
+]
+
 # CI/CD
 infra-ci = [
     "@fslongjin"
@@ -148,3 +168,6 @@ bootstrap = [
 "/kernel/src/filesystem" =                               ["filesystem"]
 "/kernel/src/virt" =                                     ["virtulization"]
 "/kernel/src/arch/x86_64/kvm" =                          ["virtulization"]
+"/kernel/src/arch/x86_64"   =                            ["x86_64"]
+"/kernel/src/arch/riscv64"   =                           ["riscv64"]
+