Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

riscv64: 添加flush tlb的ipi #636

Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
riscv64: 添加flush tlb的ipi
fslongjin committed Mar 21, 2024
commit 67c1075292f033d1c039a77085540c8149ef5964
12 changes: 11 additions & 1 deletion kernel/src/arch/riscv64/cpu.rs
Original file line number Diff line number Diff line change
@@ -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);
36 changes: 34 additions & 2 deletions kernel/src/arch/riscv64/interrupt/ipi.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}
75 changes: 70 additions & 5 deletions kernel/src/arch/riscv64/mm/mod.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 4 additions & 0 deletions kernel/src/mm/percpu.rs
Original file line number Diff line number Diff line change
@@ -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
///
/// 该函数应该在内核初始化时调用一次。
7 changes: 6 additions & 1 deletion kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@ use core::{

use crate::{
arch::{ipc::signal::SigSet, syscall::nr::*},
driver::base::device::device_number::DeviceNumber,
libs::{futex::constant::FutexFlag, rand::GRandFlags},
mm::syscall::MremapFlags,
net::syscall::MsgHdr,
@@ -97,6 +96,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;
@@ -109,6 +109,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;
@@ -635,6 +636,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];
@@ -703,6 +706,7 @@ impl Syscall {
Self::stat(path, kstat)
}

#[cfg(target_arch = "x86_64")]
SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32),
SYS_EPOLL_CREATE1 => Self::epoll_create1(args[0]),

@@ -713,6 +717,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]),