feat: implement PS/2 keyboard & shell, dynamic heap (malloc/new), Zero-Copy SHM, and SMP multicore initialization
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/* opencoreC - Keyboard Interrupt ISR Trampoline (Vector 33 / 0x21) */
|
||||
.global keyboard_isr_entry
|
||||
.extern keyboard_interrupt_handler
|
||||
|
||||
.section .text
|
||||
keyboard_isr_entry:
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
call keyboard_interrupt_handler
|
||||
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
iretq
|
||||
@@ -52,6 +52,7 @@ static mut IDT: [IdtEntry; 256] = [IdtEntry::missing(); 256];
|
||||
extern "C" {
|
||||
fn default_isr_stub();
|
||||
fn timer_isr_entry();
|
||||
fn keyboard_isr_entry();
|
||||
}
|
||||
|
||||
// Global assembly ISR stub for default exception handling
|
||||
@@ -92,6 +93,10 @@ pub unsafe fn init() {
|
||||
let timer_addr = timer_isr_entry as *const () as usize as u64;
|
||||
(*idt_ptr.add(32)).set_handler(timer_addr, 0, 0);
|
||||
|
||||
// Set Keyboard Interrupt (Vector 33 / 0x21)
|
||||
let kbd_addr = keyboard_isr_entry as *const () as usize as u64;
|
||||
(*idt_ptr.add(33)).set_handler(kbd_addr, 0, 0);
|
||||
|
||||
let descriptor = IdtDescriptor {
|
||||
limit: (size_of::<[IdtEntry; 256]>() - 1) as u16,
|
||||
base: idt_ptr as u64,
|
||||
@@ -108,10 +113,7 @@ pub extern "C" fn raw_exception_handler(stack_ptr: *const u64) {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn timer_interrupt_handler(saved_rsp: u64) -> u64 {
|
||||
unsafe {
|
||||
// Send End of Interrupt to controller
|
||||
send_eoi();
|
||||
|
||||
// Perform preemptive scheduling quantum check
|
||||
let sched = &mut *core::ptr::addr_of_mut!(SCHEDULER);
|
||||
sched.preempt(saved_rsp)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
pub mod gdt;
|
||||
pub mod idt;
|
||||
pub mod syscall;
|
||||
pub mod smp;
|
||||
|
||||
pub unsafe fn init() {
|
||||
gdt::init();
|
||||
idt::init();
|
||||
syscall::init();
|
||||
smp::init();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//! Symmetric Multiprocessing (SMP) Subsystem & AP Initialization
|
||||
|
||||
use crate::limine_requests::{SMP_REQUEST, LimineSmpInfo};
|
||||
use crate::kprintln;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
pub static CORES_ONLINE: AtomicUsize = AtomicUsize::new(1); // BSP is core 0
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ap_startup(info: *const LimineSmpInfo) -> ! {
|
||||
unsafe {
|
||||
let cpu_id = (*info).processor_id;
|
||||
let lapic_id = (*info).lapic_id;
|
||||
|
||||
// Initialize CPU Architecture for this AP
|
||||
super::gdt::init();
|
||||
super::idt::init();
|
||||
super::syscall::init();
|
||||
|
||||
CORES_ONLINE.fetch_add(1, Ordering::SeqCst);
|
||||
kprintln!("[SMP] CPU Core [{}] (LAPIC ID: {}) is ONLINE and entering scheduler.", cpu_id, lapic_id);
|
||||
|
||||
// Enter AP idle / scheduling loop
|
||||
loop {
|
||||
core::arch::asm!("sti; hlt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init() {
|
||||
let smp_resp = SMP_REQUEST.response;
|
||||
if smp_resp.is_null() {
|
||||
kprintln!("[SMP] Limine SMP response not found. Running on single core (BSP).");
|
||||
return;
|
||||
}
|
||||
|
||||
let cpu_count = (*smp_resp).cpu_count;
|
||||
let bsp_lapic_id = (*smp_resp).bsp_lapic_id;
|
||||
|
||||
kprintln!("[SMP] Detected {} CPU Core(s) (BSP LAPIC ID: {})", cpu_count, bsp_lapic_id);
|
||||
|
||||
// Boot all Application Processors (APs)
|
||||
for i in 0..cpu_count {
|
||||
let cpu_info = *(*smp_resp).cpus.add(i as usize);
|
||||
if (*cpu_info).lapic_id != bsp_lapic_id {
|
||||
// Write our entry trampoline to wake up the AP
|
||||
let info_mut = cpu_info as *mut LimineSmpInfo;
|
||||
(*info_mut).goto_address = Some(ap_startup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
use crate::ipc::endpoint::EP_MANAGER;
|
||||
use crate::ipc::fastpath::{CAP_KERNEL_CONTROL, handle_fastpath_call};
|
||||
use crate::sched::SCHEDULER;
|
||||
use crate::mm::vmm::VMM;
|
||||
use crate::drivers::keyboard::KEY_BUFFER;
|
||||
use crate::kprintln;
|
||||
|
||||
const IA32_EFER: u32 = 0xC0000080;
|
||||
@@ -66,9 +68,10 @@ pub struct SyscallRegisters {
|
||||
/// Dispatcher called directly from syscall_entry assembly trampoline
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
|
||||
let current_tid = unsafe {
|
||||
let (current_tid, caller_pml4) = unsafe {
|
||||
let sched = &mut *core::ptr::addr_of_mut!(SCHEDULER);
|
||||
sched.get_current_mut().id
|
||||
let curr = sched.get_current_mut();
|
||||
(curr.id, curr.pml4_paddr)
|
||||
};
|
||||
|
||||
match regs.rax {
|
||||
@@ -87,7 +90,6 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
|
||||
regs.rdx = out0;
|
||||
regs.r8 = out1;
|
||||
} else {
|
||||
// Inter-Process Rendezvous IPC Call
|
||||
unsafe {
|
||||
let ep_mgr = &mut *core::ptr::addr_of_mut!(EP_MANAGER);
|
||||
match ep_mgr.ipc_call(dest_cap, opcode, [arg0, arg1, arg2, arg3], current_tid) {
|
||||
@@ -126,6 +128,43 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// SYS_MEM_SHARE = 4 (Zero-Copy Shared Memory)
|
||||
4 => {
|
||||
let target_tid = regs.rdi;
|
||||
let src_vaddr = regs.rsi;
|
||||
let size = regs.rdx as usize;
|
||||
let target_vaddr = regs.r8;
|
||||
|
||||
unsafe {
|
||||
let sched = &mut *core::ptr::addr_of_mut!(SCHEDULER);
|
||||
if let Some(target_th) = sched.get_thread_mut(target_tid) {
|
||||
let target_pml4 = target_th.pml4_paddr;
|
||||
let vmm = &mut *core::ptr::addr_of_mut!(VMM);
|
||||
match vmm.share_memory_pages(caller_pml4, src_vaddr, size, target_pml4, target_vaddr) {
|
||||
Ok(mapped_addr) => {
|
||||
kprintln!("[SHM] Shared {} bytes from TID {} ({:#x}) to TID {} ({:#x})",
|
||||
size, current_tid, src_vaddr, target_tid, mapped_addr);
|
||||
regs.rax = mapped_addr;
|
||||
}
|
||||
Err(_) => regs.rax = (-3i64) as u64,
|
||||
}
|
||||
} else {
|
||||
regs.rax = (-7i64) as u64; // SYS_ERR_NOT_FOUND
|
||||
}
|
||||
}
|
||||
}
|
||||
// SYS_MEM_ALLOC = 5 (Dynamic Heap Page Allocation)
|
||||
5 => {
|
||||
let size = regs.rdi as usize;
|
||||
unsafe {
|
||||
let vmm = &mut *core::ptr::addr_of_mut!(VMM);
|
||||
if let Some(vaddr) = vmm.allocate_user_pages(caller_pml4, size) {
|
||||
regs.rax = vaddr;
|
||||
} else {
|
||||
regs.rax = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// SYS_THREAD_YIELD = 7
|
||||
7 => {
|
||||
unsafe {
|
||||
@@ -148,6 +187,17 @@ pub extern "C" fn kernel_syscall_dispatcher(regs: &mut SyscallRegisters) {
|
||||
}
|
||||
regs.rax = (-1i64) as u64;
|
||||
}
|
||||
// SYS_KEY_READ = 10 (PS/2 Keyboard non-blocking read)
|
||||
10 => {
|
||||
unsafe {
|
||||
let kbuf = &mut *core::ptr::addr_of_mut!(KEY_BUFFER);
|
||||
if let Some(ch) = kbuf.pop() {
|
||||
regs.rax = ch as u64;
|
||||
} else {
|
||||
regs.rax = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
regs.rax = (-1i64) as u64; // SYS_ERR_INVALID_ARG
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
//! PS/2 Keyboard Controller Driver (IRQ 1 / Vector 33)
|
||||
|
||||
use crate::drivers::timer::send_eoi;
|
||||
use crate::kprintln;
|
||||
|
||||
const PS2_DATA_PORT: u16 = 0x60;
|
||||
|
||||
const BUFFER_CAPACITY: usize = 64;
|
||||
|
||||
pub struct KeyboardBuffer {
|
||||
buffer: [u8; BUFFER_CAPACITY],
|
||||
head: usize,
|
||||
tail: usize,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
pub static mut KEY_BUFFER: KeyboardBuffer = KeyboardBuffer {
|
||||
buffer: [0; BUFFER_CAPACITY],
|
||||
head: 0,
|
||||
tail: 0,
|
||||
count: 0,
|
||||
};
|
||||
|
||||
impl KeyboardBuffer {
|
||||
pub fn push(&mut self, ch: u8) {
|
||||
if self.count < BUFFER_CAPACITY {
|
||||
self.buffer[self.head] = ch;
|
||||
self.head = (self.head + 1) % BUFFER_CAPACITY;
|
||||
self.count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<u8> {
|
||||
if self.count > 0 {
|
||||
let ch = self.buffer[self.tail];
|
||||
self.tail = (self.tail + 1) % BUFFER_CAPACITY;
|
||||
self.count -= 1;
|
||||
Some(ch)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scancode Set 1 standard ASCII map for 0x00..0x58
|
||||
static SCANCODE_MAP: [u8; 91] = [
|
||||
0, 27, b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'-', b'=', 8, /* Backspace */
|
||||
b'\t', b'q', b'w', b'e', b'r', b't', b'y', b'u', b'i', b'o', b'p', b'[', b']', b'\n', /* Enter */
|
||||
0, /* Ctrl */
|
||||
b'a', b's', b'd', b'f', b'g', b'h', b'j', b'k', b'l', b';', b'\'', b'`',
|
||||
0, /* Left Shift */
|
||||
b'\\', b'z', b'x', b'c', b'v', b'b', b'n', b'm', b',', b'.', b'/',
|
||||
0, /* Right Shift */
|
||||
b'*', 0, /* Alt */
|
||||
b' ', /* Space */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-F10 */
|
||||
0, 0, /* NumLock, ScrollLock */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
];
|
||||
|
||||
#[inline]
|
||||
unsafe fn inb(port: u16) -> u8 {
|
||||
let mut val: u8;
|
||||
core::arch::asm!("in al, dx", in("dx") port, out("al") val, options(nomem, nostack, preserves_flags));
|
||||
val
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
kprintln!("[KEYBOARD] PS/2 Keyboard Driver Initialized.");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn keyboard_interrupt_handler() {
|
||||
unsafe {
|
||||
let scancode = inb(PS2_DATA_PORT);
|
||||
|
||||
// Process only key-down events (bit 7 clear)
|
||||
if (scancode as usize) < SCANCODE_MAP.len() {
|
||||
let ascii = SCANCODE_MAP[scancode as usize];
|
||||
if ascii != 0 {
|
||||
let buf = &mut *core::ptr::addr_of_mut!(KEY_BUFFER);
|
||||
buf.push(ascii);
|
||||
}
|
||||
}
|
||||
|
||||
send_eoi();
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod serial;
|
||||
pub mod timer;
|
||||
pub mod keyboard;
|
||||
|
||||
@@ -53,8 +53,8 @@ unsafe fn remap_pic() {
|
||||
outb(PIC2_DATA, 0x01);
|
||||
io_wait();
|
||||
|
||||
// Mask all IRQs except IRQ 0 (Timer)
|
||||
outb(PIC1_DATA, 0xFE); // Enable only IRQ0 (bit 0 = 0)
|
||||
// Mask all IRQs except IRQ 0 (Timer) and IRQ 1 (Keyboard)
|
||||
outb(PIC1_DATA, 0xFC); // Enable IRQ0 and IRQ1
|
||||
outb(PIC2_DATA, 0xFF); // Disable all on Slave
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,33 @@ pub struct LimineModuleRequest {
|
||||
}
|
||||
unsafe impl Sync for LimineModuleRequest {}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct LimineSmpInfo {
|
||||
pub processor_id: u32,
|
||||
pub lapic_id: u32,
|
||||
pub _reserved: u64,
|
||||
pub goto_address: Option<extern "C" fn(*const LimineSmpInfo) -> !>,
|
||||
pub extra_argument: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct LimineSmpResponse {
|
||||
pub revision: u64,
|
||||
pub flags: u32,
|
||||
pub bsp_lapic_id: u32,
|
||||
pub cpu_count: u64,
|
||||
pub cpus: *const *const LimineSmpInfo,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct LimineSmpRequest {
|
||||
pub id: [u64; 4],
|
||||
pub revision: u64,
|
||||
pub response: *const LimineSmpResponse,
|
||||
pub flags: u64,
|
||||
}
|
||||
unsafe impl Sync for LimineSmpRequest {}
|
||||
|
||||
/* Constants for Limine Request Identifiers */
|
||||
#[used]
|
||||
#[link_section = ".limine_requests"]
|
||||
@@ -149,6 +176,15 @@ pub static MODULE_REQUEST: LimineModuleRequest = LimineModuleRequest {
|
||||
internal_modules: core::ptr::null(),
|
||||
};
|
||||
|
||||
#[used]
|
||||
#[link_section = ".limine_requests"]
|
||||
pub static SMP_REQUEST: LimineSmpRequest = LimineSmpRequest {
|
||||
id: [0xc7b1dd30df4c8b88, 0x0a82e883a194f07b, 0x95a105da0e6d6305, 0xa5951e16b0f99bc7],
|
||||
revision: 0,
|
||||
response: core::ptr::null(),
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
/// Get HHDM direct map virtual offset
|
||||
pub fn get_hhdm_offset() -> Option<u64> {
|
||||
unsafe {
|
||||
|
||||
+79
-8
@@ -1,6 +1,6 @@
|
||||
//! Virtual Memory Manager (VMM) & 4-Level Paging (x86_64)
|
||||
|
||||
use super::pfa::PFA;
|
||||
use super::pfa::{PFA, PAGE_SIZE};
|
||||
|
||||
pub const PAGE_PRESENT: u64 = 1 << 0;
|
||||
pub const PAGE_WRITABLE: u64 = 1 << 1;
|
||||
@@ -19,13 +19,18 @@ pub struct PageTable {
|
||||
|
||||
pub struct VirtualMemoryManager {
|
||||
hhdm_offset: u64,
|
||||
next_user_heap_vaddr: u64,
|
||||
}
|
||||
|
||||
pub static mut VMM: VirtualMemoryManager = VirtualMemoryManager { hhdm_offset: 0 };
|
||||
pub static mut VMM: VirtualMemoryManager = VirtualMemoryManager {
|
||||
hhdm_offset: 0,
|
||||
next_user_heap_vaddr: 0x00000000_20000000,
|
||||
};
|
||||
|
||||
impl VirtualMemoryManager {
|
||||
pub fn init(&mut self, hhdm: u64) {
|
||||
self.hhdm_offset = hhdm;
|
||||
self.next_user_heap_vaddr = 0x00000000_20000000;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -66,6 +71,78 @@ impl VirtualMemoryManager {
|
||||
Some(user_pml4_paddr)
|
||||
}
|
||||
|
||||
/// Dynamically allocate virtual user pages backed by physical RAM
|
||||
pub unsafe fn allocate_user_pages(&mut self, pml4_paddr: u64, size_bytes: usize) -> Option<u64> {
|
||||
let page_count = (size_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
let vaddr_start = self.next_user_heap_vaddr;
|
||||
self.next_user_heap_vaddr += (page_count * PAGE_SIZE) as u64;
|
||||
|
||||
let pfa_ptr = core::ptr::addr_of_mut!(PFA);
|
||||
|
||||
for i in 0..page_count {
|
||||
let page_vaddr = vaddr_start + (i * PAGE_SIZE) as u64;
|
||||
let page_paddr = (*pfa_ptr).alloc_frame()?;
|
||||
self.map_page(pml4_paddr, page_vaddr, page_paddr, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER).ok()?;
|
||||
}
|
||||
|
||||
Some(vaddr_start)
|
||||
}
|
||||
|
||||
/// Translate virtual address to physical address in given PML4
|
||||
pub unsafe fn virt_to_phys(&self, pml4_paddr: u64, vaddr: u64) -> Option<u64> {
|
||||
let pml4_idx = ((vaddr >> 39) & 0x1FF) as usize;
|
||||
let pdpt_idx = ((vaddr >> 30) & 0x1FF) as usize;
|
||||
let pd_idx = ((vaddr >> 21) & 0x1FF) as usize;
|
||||
let pt_idx = ((vaddr >> 12) & 0x1FF) as usize;
|
||||
|
||||
let pml4 = self.phys_to_virt::<PageTable>(pml4_paddr);
|
||||
let pdpt_entry = (*pml4).entries[pml4_idx];
|
||||
if (pdpt_entry & PAGE_PRESENT) == 0 { return None; }
|
||||
|
||||
let pdpt = self.phys_to_virt::<PageTable>(pdpt_entry & PAGE_MASK);
|
||||
let pd_entry = (*pdpt).entries[pdpt_idx];
|
||||
if (pd_entry & PAGE_PRESENT) == 0 { return None; }
|
||||
|
||||
let pd = self.phys_to_virt::<PageTable>(pd_entry & PAGE_MASK);
|
||||
let pt_entry = (*pd).entries[pd_idx];
|
||||
if (pt_entry & PAGE_PRESENT) == 0 { return None; }
|
||||
|
||||
let pt = self.phys_to_virt::<PageTable>(pt_entry & PAGE_MASK);
|
||||
let page_entry = (*pt).entries[pt_idx];
|
||||
if (page_entry & PAGE_PRESENT) == 0 { return None; }
|
||||
|
||||
Some((page_entry & PAGE_MASK) | (vaddr & 0xFFF))
|
||||
}
|
||||
|
||||
/// Zero-copy share physical frames from src_pml4 to target_pml4
|
||||
pub unsafe fn share_memory_pages(
|
||||
&mut self,
|
||||
src_pml4: u64,
|
||||
src_vaddr: u64,
|
||||
size_bytes: usize,
|
||||
target_pml4: u64,
|
||||
target_vaddr_hint: u64,
|
||||
) -> Result<u64, ()> {
|
||||
let page_count = (size_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
let target_base = if target_vaddr_hint != 0 {
|
||||
target_vaddr_hint
|
||||
} else {
|
||||
let v = self.next_user_heap_vaddr;
|
||||
self.next_user_heap_vaddr += (page_count * PAGE_SIZE) as u64;
|
||||
v
|
||||
};
|
||||
|
||||
for i in 0..page_count {
|
||||
let src_page_vaddr = src_vaddr + (i * PAGE_SIZE) as u64;
|
||||
let target_page_vaddr = target_base + (i * PAGE_SIZE) as u64;
|
||||
|
||||
let phys_frame = self.virt_to_phys(src_pml4, src_page_vaddr).ok_or(())? & PAGE_MASK;
|
||||
self.map_page(target_pml4, target_page_vaddr, phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER)?;
|
||||
}
|
||||
|
||||
Ok(target_base)
|
||||
}
|
||||
|
||||
/// Map a single 4KiB page into the specified PML4
|
||||
pub unsafe fn map_page(
|
||||
&self,
|
||||
@@ -81,22 +158,17 @@ impl VirtualMemoryManager {
|
||||
|
||||
let pml4 = self.phys_to_virt::<PageTable>(pml4_paddr);
|
||||
|
||||
// 1. Traverse / allocate PDPT
|
||||
let pdpt_paddr = self.get_or_alloc_table(&mut (*pml4).entries[pml4_idx], flags)?;
|
||||
let pdpt = self.phys_to_virt::<PageTable>(pdpt_paddr);
|
||||
|
||||
// 2. Traverse / allocate PD
|
||||
let pd_paddr = self.get_or_alloc_table(&mut (*pdpt).entries[pdpt_idx], flags)?;
|
||||
let pd = self.phys_to_virt::<PageTable>(pd_paddr);
|
||||
|
||||
// 3. Traverse / allocate PT
|
||||
let pt_paddr = self.get_or_alloc_table(&mut (*pd).entries[pd_idx], flags)?;
|
||||
let pt = self.phys_to_virt::<PageTable>(pt_paddr);
|
||||
|
||||
// 4. Map the physical page in the PT
|
||||
(*pt).entries[pt_idx] = (paddr & PAGE_MASK) | flags | PAGE_PRESENT;
|
||||
|
||||
// Invalidate TLB for this virtual address if current address space
|
||||
if (self.read_cr3() & PAGE_MASK) == pml4_paddr {
|
||||
core::arch::asm!("invlpg [{0}]", in(reg) vaddr, options(nostack, preserves_flags));
|
||||
}
|
||||
@@ -106,7 +178,6 @@ impl VirtualMemoryManager {
|
||||
|
||||
unsafe fn get_or_alloc_table(&self, entry: &mut u64, inherit_flags: u64) -> Result<u64, ()> {
|
||||
if (*entry & PAGE_PRESENT) != 0 {
|
||||
// Update permissions if user access required
|
||||
if (inherit_flags & PAGE_USER) != 0 {
|
||||
*entry |= PAGE_USER;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user