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

feat(mm): 简单实现fat文件系统的文件映射 #840

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
80ca935
20240524 3:40
MemoryShore May 23, 2024
d1d0aca
20240527 0010
MemoryShore May 26, 2024
33e9f0b
修复mmap未延迟分配内存的问题
MemoryShore May 27, 2024
8eb687c
Merge branch 'patch-add-file-mapping' into patch-fix-mmap
MemoryShore May 28, 2024
9261cb7
Revert "Merge branch 'patch-add-file-mapping' into patch-fix-mmap"
MemoryShore May 28, 2024
aff3316
20240528 1800
MemoryShore May 28, 2024
653180e
Revert "Revert "Merge branch 'patch-add-file-mapping' into patch-fix-…
MemoryShore May 28, 2024
c4149d8
Merge branch 'patch-fix-mmap-revert' into patch-add-file-mapping
MemoryShore May 28, 2024
91222a3
Merge branch 'master' into patch-add-file-mapping
MemoryShore May 28, 2024
4e9f577
update-20240529-0347
MemoryShore May 28, 2024
95c37e4
update 20240604 0233
MemoryShore Jun 3, 2024
f1ad5b3
update 20240606 1800
MemoryShore Jun 6, 2024
d7211d0
update 20240607 0200
MemoryShore Jun 6, 2024
62ec0e0
update 20240617 1747
MemoryShore Jun 17, 2024
3ac055a
重写页面保护标志的构造逻辑
MemoryShore Jun 18, 2024
7fd7c6e
update20240620 1726
MemoryShore Jun 20, 2024
d2a37ed
Merge remote-tracking branch 'origin' into patch-add-file-mapping
MemoryShore Jun 23, 2024
00183e0
添加Riscv64的protection_map
MemoryShore Jun 23, 2024
5ef4037
简单实现fat文件系统的文件映射,添加msync系统调用
MemoryShore Jun 24, 2024
98c9be5
trait FileSystem增加统一接口
MemoryShore Jun 25, 2024
d5b5718
MountFS实现文件映射相关接口
MemoryShore Jun 25, 2024
eee564d
格式化代码
MemoryShore Jun 25, 2024
b5aca56
Merge branch 'master' into patch-add-file-mapping
MemoryShore Jun 29, 2024
34c585e
pagecache存储方式由HashMap改为XArray
MemoryShore Jul 2, 2024
90644bf
Merge branch 'master' into patch-add-file-mapping
MemoryShore Jul 16, 2024
2558777
使用读写锁包装Page结构体
MemoryShore Jul 24, 2024
c9e790b
PageCache由存放物理地址改为直接存放页面
MemoryShore Jul 24, 2024
8f338fb
优化protection_map的初始化方式
MemoryShore Jul 24, 2024
a6ff58c
添加shrink_list方法释放页面
MemoryShore Jul 26, 2024
535b702
Merge branch 'master' into patch-add-file-mapping
MemoryShore Jul 26, 2024
9ba2fa3
添加页面回收机制
MemoryShore Jul 28, 2024
38f4df0
Merge branch 'master' into patch-add-file-mapping
MemoryShore Jul 28, 2024
d7e76ec
添加页面回收内核线程
MemoryShore Jul 30, 2024
2f6b28d
缺页中断使用的锁修改为irq_save; 添加脏页回写机制
MemoryShore Aug 6, 2024
732a6d7
优化代码结构,添加部分注释
MemoryShore Aug 10, 2024
cc19c94
Merge branch 'master' into patch-add-file-mapping
MemoryShore Aug 19, 2024
b5aea85
优化PageCache的创建
MemoryShore Aug 22, 2024
d6a5341
Merge branch 'master' into patch-add-file-mapping
MemoryShore Aug 28, 2024
d8cde6e
修复合并错误
MemoryShore Aug 28, 2024
e13cf39
修复do_cow_page死锁问题
MemoryShore Aug 28, 2024
94f1324
将PageFaultMessage中的地址对齐
MemoryShore Aug 28, 2024
a0f5d51
debug改为false
MemoryShore Aug 29, 2024
4bdb08d
访问非法地址时发送信号终止进程
MemoryShore Aug 29, 2024
22d8bff
修复重复插入反向vma表的错误
MemoryShore Sep 2, 2024
6cc5803
添加test_filemap文件映射测试程序
MemoryShore Sep 2, 2024
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
3 changes: 2 additions & 1 deletion kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ wait_queue_macros = { path = "crates/wait_queue_macros" }
paste = "=1.0.14"
slabmalloc = { path = "crates/rust-slabmalloc" }
log = "0.4.21"

xarray = "0.1.0"
lru = "0.12.3"

# target为x86_64时,使用下面的依赖
[target.'cfg(target_arch = "x86_64")'.dependencies]
Expand Down
74 changes: 70 additions & 4 deletions kernel/src/arch/riscv64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::{
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
},
kernel_mapper::KernelMapper,
page::{PageEntry, PageFlags, PAGE_1G_SHIFT},
page::{EntryFlags, PageEntry, PAGE_1G_SHIFT},
ucontext::UserMapper,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags,
},
smp::cpu::ProcessorId,
};
Expand Down Expand Up @@ -256,8 +256,74 @@ impl MemoryManagementArch for RiscV64MMArch {
) -> bool {
true
}

const PAGE_NONE: usize = Self::ENTRY_FLAG_GLOBAL | Self::ENTRY_FLAG_READONLY;

const PAGE_READ: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY;

const PAGE_WRITE: usize =
PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_WRITEABLE;

const PAGE_EXEC: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_EXEC;

const PAGE_READ_EXEC: usize =
PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_EXEC;

const PAGE_WRITE_EXEC: usize = PAGE_ENTRY_BASE
| Self::ENTRY_FLAG_READONLY
| Self::ENTRY_FLAG_EXEC
| Self::ENTRY_FLAG_WRITEABLE;

const PAGE_COPY: usize = Self::PAGE_READ;
const PAGE_COPY_EXEC: usize = Self::PAGE_READ_EXEC;
const PAGE_SHARED: usize = Self::PAGE_WRITE;
const PAGE_SHARED_EXEC: usize = Self::PAGE_WRITE_EXEC;

const PAGE_COPY_NOEXEC: usize = 0;
const PAGE_READONLY: usize = 0;
const PAGE_READONLY_EXEC: usize = 0;

const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
}

const fn protection_map() -> [EntryFlags<MMArch>; 16] {
let mut map = [0; 16];
map[VmFlags::VM_NONE.bits()] = MMArch::PAGE_NONE;
map[VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
map[VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY;
map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_COPY;
map[VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_COPY_EXEC;
map[VmFlags::VM_SHARED.bits()] = MMArch::PAGE_NONE;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_SHARED;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_SHARED;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
MMArch::PAGE_SHARED_EXEC;
map[VmFlags::VM_SHARED.bits()
| VmFlags::VM_EXEC.bits()
| VmFlags::VM_WRITE.bits()
| VmFlags::VM_READ.bits()] = MMArch::PAGE_SHARED_EXEC;
let mut ret = [unsafe { EntryFlags::from_data(0) }; 16];
let mut index = 0;
while index < 16 {
ret[index] = unsafe { EntryFlags::from_data(map[index]) };
index += 1;
}
ret
}

const PAGE_ENTRY_BASE: usize = RiscV64MMArch::ENTRY_FLAG_PRESENT
| RiscV64MMArch::ENTRY_FLAG_ACCESSED
| RiscV64MMArch::ENTRY_FLAG_USER;

impl VirtAddr {
/// 判断虚拟地址是否合法
#[inline(always)]
Expand All @@ -270,8 +336,8 @@ impl VirtAddr {
}

/// 获取内核地址默认的页面标志
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> EntryFlags<A> {
EntryFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
.set_user(false)
.set_execute(true)
}
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/arch/x86_64/kvm/vmx/ept.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::arch::mm::LockedFrameAllocator;
use crate::arch::mm::PageMapper;
use crate::arch::MMArch;
use crate::mm::page::PageFlags;
use crate::mm::page::EntryFlags;
use crate::mm::{PageTableKind, PhysAddr, VirtAddr};
use crate::smp::core::smp_get_processor_id;
use crate::smp::cpu::AtomicProcessorId;
Expand Down Expand Up @@ -92,7 +92,7 @@ impl EptMapper {
&mut self,
gpa: u64,
hpa: u64,
flags: PageFlags<MMArch>,
flags: EntryFlags<MMArch>,
) -> Result<(), SystemError> {
if self.readonly {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/arch/x86_64/kvm/vmx/mmu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
arch::kvm::vmx::ept::EptMapper,
libs::mutex::Mutex,
mm::{page::PageFlags, syscall::ProtFlags},
mm::{page::EntryFlags, syscall::ProtFlags},
virt::kvm::host_mem::{__gfn_to_pfn, kvm_vcpu_gfn_to_memslot, PAGE_MASK, PAGE_SHIFT},
};
use bitfield_struct::bitfield;
Expand Down Expand Up @@ -218,7 +218,7 @@ pub fn __direct_map(
}
// 把gpa映射到hpa
let mut ept_mapper = EptMapper::lock();
let page_flags = PageFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
let page_flags = EntryFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
unsafe {
assert!(ept_mapper.walk(gpa, pfn << PAGE_SHIFT, page_flags).is_ok());
}
Expand Down
50 changes: 34 additions & 16 deletions kernel/src/arch/x86_64/mm/fault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ use x86::{bits64::rflags::RFlags, controlregs::Cr4};
use crate::{
arch::{
interrupt::{trap::X86PfErrorCode, TrapFrame},
ipc::signal::{SigCode, Signal},
mm::{MemoryManagementArch, X86_64MMArch},
CurrentIrqArch, MMArch,
},
exception::InterruptArch,
ipc::signal_types::{SigInfo, SigType},
mm::{
fault::{FaultFlags, PageFaultHandler, PageFaultMessage},
ucontext::{AddressSpace, LockedVMA},
VirtAddr, VmFaultReason, VmFlags,
},
process::ProcessManager,
};

use super::LockedFrameAllocator;
Expand All @@ -28,7 +31,7 @@ pub type PageMapper =

impl X86_64MMArch {
pub fn vma_access_error(vma: Arc<LockedVMA>, error_code: X86PfErrorCode) -> bool {
let vm_flags = *vma.lock().vm_flags();
let vm_flags = *vma.lock_irqsave().vm_flags();
let foreign = false;
if error_code.contains(X86PfErrorCode::X86_PF_PK) {
return true;
Expand Down Expand Up @@ -223,20 +226,30 @@ impl X86_64MMArch {
}

let current_address_space: Arc<AddressSpace> = AddressSpace::current().unwrap();
let mut space_guard = current_address_space.write();
let mut space_guard = current_address_space.write_irqsave();
let mut fault;
loop {
let vma = space_guard.mappings.find_nearest(address);
// let vma = space_guard.mappings.contains(address);

let vma = vma.unwrap_or_else(|| {
panic!(
"can not find nearest vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
)
});
let guard = vma.lock();
let vma = match vma {
Some(vma) => vma,
None => {
log::error!(
"can not find nearest vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
);
let pid = ProcessManager::current_pid();
let mut info =
SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
Signal::SIGSEGV
.send_signal_info(Some(&mut info), pid)
.expect("failed to send SIGSEGV to process");
return;
}
};
let guard = vma.lock_irqsave();
let region = *guard.region();
let vm_flags = *guard.vm_flags();
drop(guard);
Expand All @@ -253,11 +266,18 @@ impl X86_64MMArch {
)
});
} else {
panic!(
log::error!(
"No mapped vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
)
);
let pid = ProcessManager::current_pid();
let mut info =
SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
Signal::SIGSEGV
.send_signal_info(Some(&mut info), pid)
.expect("failed to send SIGSEGV to process");
return;
}
}

Expand All @@ -269,11 +289,9 @@ impl X86_64MMArch {
);
}
let mapper = &mut space_guard.user_mapper.utable;
let message = PageFaultMessage::new(vma.clone(), address, flags, mapper);

fault = PageFaultHandler::handle_mm_fault(
PageFaultMessage::new(vma.clone(), address, flags),
mapper,
);
fault = PageFaultHandler::handle_mm_fault(message);

if fault.contains(VmFaultReason::VM_FAULT_COMPLETED) {
return;
Expand Down
99 changes: 93 additions & 6 deletions kernel/src/arch/x86_64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ use crate::{
};

use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::{PageEntry, PageFlags, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags};

use system_error::SystemError;

Expand Down Expand Up @@ -326,6 +326,93 @@ impl MemoryManagementArch for X86_64MMArch {
}
pkru::pkru_allows_pkey(pkru::vma_pkey(vma), write)
}

const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();

const PAGE_NONE: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_ACCESSED | Self::ENTRY_FLAG_GLOBAL;

const PAGE_SHARED: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_READWRITE
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;

const PAGE_SHARED_EXEC: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_READWRITE
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED;

const PAGE_COPY_NOEXEC: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;

const PAGE_COPY_EXEC: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;

const PAGE_COPY: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;

const PAGE_READONLY: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;

const PAGE_READONLY_EXEC: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;

const PAGE_READ: usize = 0;
const PAGE_READ_EXEC: usize = 0;
const PAGE_WRITE: usize = 0;
const PAGE_WRITE_EXEC: usize = 0;
const PAGE_EXEC: usize = 0;
}

/// 获取保护标志的映射表
///
///
/// ## 返回值
/// - `[usize; 16]`: 长度为16的映射表
const fn protection_map() -> [EntryFlags<MMArch>; 16] {
let mut map = [unsafe { EntryFlags::from_data(0) }; 16];
unsafe {
map[VmFlags::VM_NONE.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
map[VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY);
map[VmFlags::VM_WRITE.bits()] = EntryFlags::from_data(MMArch::PAGE_COPY);
map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY);
map[VmFlags::VM_EXEC.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
map[VmFlags::VM_SHARED.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
map[VmFlags::VM_SHARED.bits()
| VmFlags::VM_EXEC.bits()
| VmFlags::VM_WRITE.bits()
| VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
}
// if X86_64MMArch::is_xd_reserved() {
// map.iter_mut().for_each(|x| *x &= !Self::ENTRY_FLAG_NO_EXEC)
// }
map
}

impl X86_64MMArch {
Expand Down Expand Up @@ -650,17 +737,17 @@ impl FrameAllocator for LockedFrameAllocator {
}

/// 获取内核地址默认的页面标志
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> EntryFlags<A> {
let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.unwrap();

if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
// Remap kernel code execute
return PageFlags::new().set_execute(true).set_write(true);
return EntryFlags::new().set_execute(true).set_write(true);
} else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
// Remap kernel rodata read only
return PageFlags::new().set_execute(true);
return EntryFlags::new().set_execute(true);
} else {
return PageFlags::new().set_write(true).set_execute(true);
return EntryFlags::new().set_write(true).set_execute(true);
}
}

Expand Down
4 changes: 2 additions & 2 deletions kernel/src/arch/x86_64/mm/pkru.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const PKEY_MASK: usize = 1 << 32 | 1 << 33 | 1 << 34 | 1 << 35;
/// ## 返回值
/// - `u16`: vma的protection_key
pub fn vma_pkey(vma: Arc<LockedVMA>) -> u16 {
let guard = vma.lock();
((guard.vm_flags().bits() & PKEY_MASK as u64) >> VM_PKEY_SHIFT) as u16
let guard = vma.lock_irqsave();
((guard.vm_flags().bits() & PKEY_MASK) >> VM_PKEY_SHIFT) as u16
}

// TODO pkru实现参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/pkru.h
Expand Down
Loading
Loading