1a17651b1SMemoryShore use core::{ 2a17651b1SMemoryShore intrinsics::{likely, unlikely}, 3a17651b1SMemoryShore panic, 4a17651b1SMemoryShore }; 5a17651b1SMemoryShore 6a17651b1SMemoryShore use alloc::sync::Arc; 7*2eab6dd7S曾俊 use log::error; 8a17651b1SMemoryShore use x86::{bits64::rflags::RFlags, controlregs::Cr4}; 9a17651b1SMemoryShore 10a17651b1SMemoryShore use crate::{ 11a17651b1SMemoryShore arch::{ 12a17651b1SMemoryShore interrupt::{trap::X86PfErrorCode, TrapFrame}, 13a17651b1SMemoryShore mm::{MemoryManagementArch, X86_64MMArch}, 14a17651b1SMemoryShore CurrentIrqArch, MMArch, 15a17651b1SMemoryShore }, 16a17651b1SMemoryShore exception::InterruptArch, 17a17651b1SMemoryShore mm::{ 18a17651b1SMemoryShore fault::{FaultFlags, PageFaultHandler, PageFaultMessage}, 19a17651b1SMemoryShore ucontext::{AddressSpace, LockedVMA}, 20a17651b1SMemoryShore VirtAddr, VmFaultReason, VmFlags, 21a17651b1SMemoryShore }, 22a17651b1SMemoryShore }; 23a17651b1SMemoryShore 24a17651b1SMemoryShore use super::LockedFrameAllocator; 25a17651b1SMemoryShore 26a17651b1SMemoryShore pub type PageMapper = 27a17651b1SMemoryShore crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>; 28a17651b1SMemoryShore 29a17651b1SMemoryShore impl X86_64MMArch { 30a17651b1SMemoryShore pub fn vma_access_error(vma: Arc<LockedVMA>, error_code: X86PfErrorCode) -> bool { 31a17651b1SMemoryShore let vm_flags = *vma.lock().vm_flags(); 32a17651b1SMemoryShore let foreign = false; 33a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_PK) { 34a17651b1SMemoryShore return true; 35a17651b1SMemoryShore } 36a17651b1SMemoryShore 37a17651b1SMemoryShore if unlikely(error_code.contains(X86PfErrorCode::X86_PF_SGX)) { 38a17651b1SMemoryShore return true; 39a17651b1SMemoryShore } 40a17651b1SMemoryShore 41a17651b1SMemoryShore if !Self::vma_access_permitted( 42a17651b1SMemoryShore vma.clone(), 43a17651b1SMemoryShore error_code.contains(X86PfErrorCode::X86_PF_WRITE), 44a17651b1SMemoryShore error_code.contains(X86PfErrorCode::X86_PF_INSTR), 45a17651b1SMemoryShore foreign, 46a17651b1SMemoryShore ) { 47a17651b1SMemoryShore return true; 48a17651b1SMemoryShore } 49a17651b1SMemoryShore 50a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_WRITE) { 51a17651b1SMemoryShore if unlikely(!vm_flags.contains(VmFlags::VM_WRITE)) { 52a17651b1SMemoryShore return true; 53a17651b1SMemoryShore } 54a17651b1SMemoryShore return false; 55a17651b1SMemoryShore } 56a17651b1SMemoryShore 57a17651b1SMemoryShore if unlikely(error_code.contains(X86PfErrorCode::X86_PF_PROT)) { 58a17651b1SMemoryShore return true; 59a17651b1SMemoryShore } 60a17651b1SMemoryShore 61a17651b1SMemoryShore if unlikely(!vma.is_accessible()) { 62a17651b1SMemoryShore return true; 63a17651b1SMemoryShore } 64a17651b1SMemoryShore false 65a17651b1SMemoryShore } 66a17651b1SMemoryShore 67a17651b1SMemoryShore pub fn show_fault_oops( 68a17651b1SMemoryShore regs: &'static TrapFrame, 69a17651b1SMemoryShore error_code: X86PfErrorCode, 70a17651b1SMemoryShore address: VirtAddr, 71a17651b1SMemoryShore ) { 72a17651b1SMemoryShore let mapper = 73a17651b1SMemoryShore unsafe { PageMapper::current(crate::mm::PageTableKind::User, LockedFrameAllocator) }; 74a17651b1SMemoryShore if let Some(entry) = mapper.get_entry(address, 0) { 75a17651b1SMemoryShore if entry.present() { 76a17651b1SMemoryShore if !entry.flags().has_execute() { 77*2eab6dd7S曾俊 error!("kernel tried to execute NX-protected page - exploit attempt?"); 78a17651b1SMemoryShore } else if mapper.table().phys().data() & MMArch::ENTRY_FLAG_USER != 0 79a17651b1SMemoryShore && unsafe { x86::controlregs::cr4().contains(Cr4::CR4_ENABLE_SMEP) } 80a17651b1SMemoryShore { 81*2eab6dd7S曾俊 error!("unable to execute userspace code (SMEP?)"); 82a17651b1SMemoryShore } 83a17651b1SMemoryShore } 84a17651b1SMemoryShore } 85a17651b1SMemoryShore if address.data() < X86_64MMArch::PAGE_SIZE && !regs.is_from_user() { 86*2eab6dd7S曾俊 error!( 87a17651b1SMemoryShore "BUG: kernel NULL pointer dereference, address: {:#x}", 88a17651b1SMemoryShore address.data() 89a17651b1SMemoryShore ); 90a17651b1SMemoryShore } else { 91*2eab6dd7S曾俊 error!( 92a17651b1SMemoryShore "BUG: unable to handle page fault for address: {:#x}", 93a17651b1SMemoryShore address.data() 94a17651b1SMemoryShore ); 95a17651b1SMemoryShore } 96a17651b1SMemoryShore 97*2eab6dd7S曾俊 error!( 98a17651b1SMemoryShore "#PF: {} {} in {} mode\n", 99a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_USER) { 100a17651b1SMemoryShore "user" 101a17651b1SMemoryShore } else { 102a17651b1SMemoryShore "supervisor" 103a17651b1SMemoryShore }, 104a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_INSTR) { 105a17651b1SMemoryShore "instruction fetch" 106a17651b1SMemoryShore } else if error_code.contains(X86PfErrorCode::X86_PF_WRITE) { 107a17651b1SMemoryShore "write access" 108a17651b1SMemoryShore } else { 109a17651b1SMemoryShore "read access" 110a17651b1SMemoryShore }, 111a17651b1SMemoryShore if regs.is_from_user() { 112a17651b1SMemoryShore "user" 113a17651b1SMemoryShore } else { 114a17651b1SMemoryShore "kernel" 115a17651b1SMemoryShore } 116a17651b1SMemoryShore ); 117*2eab6dd7S曾俊 error!( 118a17651b1SMemoryShore "#PF: error_code({:#04x}) - {}\n", 119a17651b1SMemoryShore error_code, 120a17651b1SMemoryShore if !error_code.contains(X86PfErrorCode::X86_PF_PROT) { 121a17651b1SMemoryShore "not-present page" 122a17651b1SMemoryShore } else if error_code.contains(X86PfErrorCode::X86_PF_RSVD) { 123a17651b1SMemoryShore "reserved bit violation" 124a17651b1SMemoryShore } else if error_code.contains(X86PfErrorCode::X86_PF_PK) { 125a17651b1SMemoryShore "protection keys violation" 126a17651b1SMemoryShore } else { 127a17651b1SMemoryShore "permissions violation" 128a17651b1SMemoryShore } 129a17651b1SMemoryShore ); 130a17651b1SMemoryShore } 131a17651b1SMemoryShore 132a17651b1SMemoryShore pub fn page_fault_oops( 133a17651b1SMemoryShore regs: &'static TrapFrame, 134a17651b1SMemoryShore error_code: X86PfErrorCode, 135a17651b1SMemoryShore address: VirtAddr, 136a17651b1SMemoryShore ) { 137a17651b1SMemoryShore if regs.is_from_user() { 138a17651b1SMemoryShore Self::show_fault_oops(regs, error_code, address); 139a17651b1SMemoryShore } 140a17651b1SMemoryShore panic!() 141a17651b1SMemoryShore } 142a17651b1SMemoryShore 143a17651b1SMemoryShore /// 内核态缺页异常处理 144a17651b1SMemoryShore /// ## 参数 145a17651b1SMemoryShore /// 146a17651b1SMemoryShore /// - `regs`: 中断栈帧 147a17651b1SMemoryShore /// - `error_code`: 错误标志 148a17651b1SMemoryShore /// - `address`: 发生缺页异常的虚拟地址 149a17651b1SMemoryShore pub fn do_kern_addr_fault( 150a17651b1SMemoryShore _regs: &'static TrapFrame, 151a17651b1SMemoryShore error_code: X86PfErrorCode, 152a17651b1SMemoryShore address: VirtAddr, 153a17651b1SMemoryShore ) { 154a17651b1SMemoryShore panic!( 155a17651b1SMemoryShore "do_kern_addr_fault has not yet been implemented, 156a17651b1SMemoryShore fault address: {:#x}, 157a17651b1SMemoryShore error_code: {:#b}, 158a17651b1SMemoryShore pid: {}\n", 159a17651b1SMemoryShore address.data(), 160a17651b1SMemoryShore error_code, 161a17651b1SMemoryShore crate::process::ProcessManager::current_pid().data() 162a17651b1SMemoryShore ); 163a17651b1SMemoryShore //TODO https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/mm/fault.c#do_kern_addr_fault 164a17651b1SMemoryShore } 165a17651b1SMemoryShore 166a17651b1SMemoryShore /// 用户态缺页异常处理 167a17651b1SMemoryShore /// ## 参数 168a17651b1SMemoryShore /// 169a17651b1SMemoryShore /// - `regs`: 中断栈帧 170a17651b1SMemoryShore /// - `error_code`: 错误标志 171a17651b1SMemoryShore /// - `address`: 发生缺页异常的虚拟地址 172a17651b1SMemoryShore pub unsafe fn do_user_addr_fault( 173a17651b1SMemoryShore regs: &'static TrapFrame, 174a17651b1SMemoryShore error_code: X86PfErrorCode, 175a17651b1SMemoryShore address: VirtAddr, 176a17651b1SMemoryShore ) { 177a17651b1SMemoryShore let rflags = RFlags::from_bits_truncate(regs.rflags); 178a17651b1SMemoryShore let mut flags: FaultFlags = FaultFlags::FAULT_FLAG_ALLOW_RETRY 179a17651b1SMemoryShore | FaultFlags::FAULT_FLAG_KILLABLE 180a17651b1SMemoryShore | FaultFlags::FAULT_FLAG_INTERRUPTIBLE; 181a17651b1SMemoryShore 182a17651b1SMemoryShore if error_code & (X86PfErrorCode::X86_PF_USER | X86PfErrorCode::X86_PF_INSTR) 183a17651b1SMemoryShore == X86PfErrorCode::X86_PF_INSTR 184a17651b1SMemoryShore { 185a17651b1SMemoryShore Self::page_fault_oops(regs, error_code, address); 186a17651b1SMemoryShore } 187a17651b1SMemoryShore 188a17651b1SMemoryShore let feature = x86::cpuid::CpuId::new() 189a17651b1SMemoryShore .get_extended_feature_info() 190a17651b1SMemoryShore .unwrap(); 191a17651b1SMemoryShore if unlikely( 192a17651b1SMemoryShore feature.has_smap() 193a17651b1SMemoryShore && !error_code.contains(X86PfErrorCode::X86_PF_USER) 194a17651b1SMemoryShore && rflags.contains(RFlags::FLAGS_AC), 195a17651b1SMemoryShore ) { 196a17651b1SMemoryShore Self::page_fault_oops(regs, error_code, address); 197a17651b1SMemoryShore } 198a17651b1SMemoryShore 199a17651b1SMemoryShore if unlikely(error_code.contains(X86PfErrorCode::X86_PF_RSVD)) { 200a17651b1SMemoryShore // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/mm/fault.c#pgtable_bad 201a17651b1SMemoryShore panic!( 202a17651b1SMemoryShore "Reserved bits are never expected to be set, error_code: {:#b}, address: {:#x}", 203a17651b1SMemoryShore error_code, 204a17651b1SMemoryShore address.data() 205a17651b1SMemoryShore ); 206a17651b1SMemoryShore } 207a17651b1SMemoryShore 208a17651b1SMemoryShore if regs.is_from_user() { 209a17651b1SMemoryShore unsafe { CurrentIrqArch::interrupt_enable() }; 210a17651b1SMemoryShore flags |= FaultFlags::FAULT_FLAG_USER; 211a17651b1SMemoryShore } else if rflags.contains(RFlags::FLAGS_IF) { 212a17651b1SMemoryShore unsafe { CurrentIrqArch::interrupt_enable() }; 213a17651b1SMemoryShore } 214a17651b1SMemoryShore 215a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_SHSTK) { 216a17651b1SMemoryShore flags |= FaultFlags::FAULT_FLAG_WRITE; 217a17651b1SMemoryShore } 218a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_WRITE) { 219a17651b1SMemoryShore flags |= FaultFlags::FAULT_FLAG_WRITE; 220a17651b1SMemoryShore } 221a17651b1SMemoryShore if error_code.contains(X86PfErrorCode::X86_PF_INSTR) { 222a17651b1SMemoryShore flags |= FaultFlags::FAULT_FLAG_INSTRUCTION; 223a17651b1SMemoryShore } 224a17651b1SMemoryShore 225a17651b1SMemoryShore let current_address_space: Arc<AddressSpace> = AddressSpace::current().unwrap(); 226a17651b1SMemoryShore let mut space_guard = current_address_space.write(); 227a17651b1SMemoryShore let mut fault; 228a17651b1SMemoryShore loop { 229a17651b1SMemoryShore let vma = space_guard.mappings.find_nearest(address); 230a17651b1SMemoryShore // let vma = space_guard.mappings.contains(address); 231a17651b1SMemoryShore 232a17651b1SMemoryShore let vma = vma.unwrap_or_else(|| { 233a17651b1SMemoryShore panic!( 234a17651b1SMemoryShore "can not find nearest vma, error_code: {:#b}, address: {:#x}", 235a17651b1SMemoryShore error_code, 236a17651b1SMemoryShore address.data(), 237a17651b1SMemoryShore ) 238a17651b1SMemoryShore }); 239a17651b1SMemoryShore let guard = vma.lock(); 240a17651b1SMemoryShore let region = *guard.region(); 241a17651b1SMemoryShore let vm_flags = *guard.vm_flags(); 242a17651b1SMemoryShore drop(guard); 243a17651b1SMemoryShore 244a17651b1SMemoryShore if !region.contains(address) { 245a17651b1SMemoryShore if vm_flags.contains(VmFlags::VM_GROWSDOWN) { 246a17651b1SMemoryShore space_guard 247a17651b1SMemoryShore .extend_stack(region.start() - address) 248a17651b1SMemoryShore .unwrap_or_else(|_| { 249a17651b1SMemoryShore panic!( 250a17651b1SMemoryShore "user stack extend failed, error_code: {:#b}, address: {:#x}", 251a17651b1SMemoryShore error_code, 252a17651b1SMemoryShore address.data(), 253a17651b1SMemoryShore ) 254a17651b1SMemoryShore }); 255a17651b1SMemoryShore } else { 256a17651b1SMemoryShore panic!( 257a17651b1SMemoryShore "No mapped vma, error_code: {:#b}, address: {:#x}", 258a17651b1SMemoryShore error_code, 259a17651b1SMemoryShore address.data(), 260a17651b1SMemoryShore ) 261a17651b1SMemoryShore } 262a17651b1SMemoryShore } 263a17651b1SMemoryShore 264a17651b1SMemoryShore if unlikely(Self::vma_access_error(vma.clone(), error_code)) { 265a17651b1SMemoryShore panic!( 266a17651b1SMemoryShore "vma access error, error_code: {:#b}, address: {:#x}", 267a17651b1SMemoryShore error_code, 268a17651b1SMemoryShore address.data(), 269a17651b1SMemoryShore ); 270a17651b1SMemoryShore } 271a17651b1SMemoryShore let mapper = &mut space_guard.user_mapper.utable; 272a17651b1SMemoryShore 273a17651b1SMemoryShore fault = PageFaultHandler::handle_mm_fault( 274a17651b1SMemoryShore PageFaultMessage::new(vma.clone(), address, flags), 275a17651b1SMemoryShore mapper, 276a17651b1SMemoryShore ); 277a17651b1SMemoryShore 278a17651b1SMemoryShore if fault.contains(VmFaultReason::VM_FAULT_COMPLETED) { 279a17651b1SMemoryShore return; 280a17651b1SMemoryShore } 281a17651b1SMemoryShore 282a17651b1SMemoryShore if unlikely(fault.contains(VmFaultReason::VM_FAULT_RETRY)) { 283a17651b1SMemoryShore flags |= FaultFlags::FAULT_FLAG_TRIED; 284a17651b1SMemoryShore } else { 285a17651b1SMemoryShore break; 286a17651b1SMemoryShore } 287a17651b1SMemoryShore } 288a17651b1SMemoryShore 289a17651b1SMemoryShore let vm_fault_error = VmFaultReason::VM_FAULT_OOM 290a17651b1SMemoryShore | VmFaultReason::VM_FAULT_SIGBUS 291a17651b1SMemoryShore | VmFaultReason::VM_FAULT_SIGSEGV 292a17651b1SMemoryShore | VmFaultReason::VM_FAULT_HWPOISON 293a17651b1SMemoryShore | VmFaultReason::VM_FAULT_HWPOISON_LARGE 294a17651b1SMemoryShore | VmFaultReason::VM_FAULT_FALLBACK; 295a17651b1SMemoryShore 296a17651b1SMemoryShore if likely(!fault.contains(vm_fault_error)) { 297a17651b1SMemoryShore panic!("fault error: {:?}", fault) 298a17651b1SMemoryShore } 299a17651b1SMemoryShore } 300a17651b1SMemoryShore } 301