Nothing to see here, move along
at main 184 lines 5.3 kB view raw
1use crate::cap::cnode; 2use crate::cap::object::ObjectTag; 3use crate::cap::pool::POOL; 4use crate::cap::table::Rights; 5use crate::error::KernelError; 6use crate::pci::DEVICE_TABLE; 7use crate::proc::PROCESSES; 8use crate::proc::context::CpuContext; 9use lancer_core::object_layout::PciDeviceObject; 10 11use super::{SyscallResult, USER_ADDR_LIMIT, try_syscall, validate_user_vaddr}; 12 13pub fn sys_dma_alloc(ctx: &mut CpuContext) { 14 let cap_addr = ctx.rdi; 15 let page_count = ctx.rsi; 16 let user_vaddr = ctx.rdx; 17 let pid = crate::arch::syscall::current_pid(); 18 19 if user_vaddr & 0xFFF != 0 { 20 ctx.rax = SyscallResult::error(KernelError::InvalidAddress).raw(); 21 return; 22 } 23 24 let _ = try_syscall!(ctx, validate_user_vaddr(user_vaddr)); 25 26 match page_count 27 .checked_mul(4096) 28 .and_then(|sz| user_vaddr.checked_add(sz)) 29 { 30 Some(end) if end <= USER_ADDR_LIMIT => {} 31 _ => { 32 ctx.rax = SyscallResult::error(KernelError::InvalidAddress).raw(); 33 return; 34 } 35 } 36 37 let (cap, pml4_phys) = { 38 let ptable = PROCESSES.lock(); 39 let pool = POOL.lock_after(&ptable); 40 match cnode::resolve_caller_validate( 41 pid, 42 cap_addr, 43 ObjectTag::PciDevice, 44 Rights::WRITE, 45 &ptable, 46 &pool, 47 ) { 48 Ok(c) => { 49 let pml4 = ptable 50 .exec(pid) 51 .map(|e| e.pml4_phys) 52 .ok_or(KernelError::InvalidObject); 53 match pml4 { 54 Ok(pml4_phys) => (c, pml4_phys), 55 Err(e) => { 56 ctx.rax = SyscallResult::error(e).raw(); 57 return; 58 } 59 } 60 } 61 Err(e) => { 62 ctx.rax = SyscallResult::error(e).raw(); 63 return; 64 } 65 } 66 }; 67 68 let device_table_idx = { 69 let pool = POOL.lock(); 70 match pool.read_as::<PciDeviceObject>(cap.phys(), cap.generation()) { 71 Ok(d) => d.device_table_idx, 72 Err(e) => { 73 ctx.rax = SyscallResult::error(e).raw(); 74 return; 75 } 76 } 77 }; 78 79 let (bus, devfn) = { 80 let dev_table = DEVICE_TABLE.lock(); 81 match dev_table.get(device_table_idx as usize) { 82 Some(d) => (d.bus, d.devfn()), 83 None => { 84 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 85 return; 86 } 87 } 88 }; 89 90 if !crate::iommu::is_available() { 91 ctx.rax = SyscallResult::error(KernelError::NotInitialized).raw(); 92 return; 93 } 94 95 let hhdm_offset = crate::mem::addr::hhdm_offset(); 96 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 97 98 ctx.rax = match crate::iommu::dma_alloc( 99 bus, 100 devfn, 101 page_count, 102 user_vaddr, 103 pml4_phys, 104 pid, 105 &mut allocator, 106 hhdm_offset, 107 ) { 108 Ok(iova) => SyscallResult::success(iova).raw(), 109 Err(e) => SyscallResult::error(e).raw(), 110 }; 111} 112 113pub fn sys_dma_free(ctx: &mut CpuContext) { 114 let cap_addr = ctx.rdi; 115 let iova = ctx.rsi; 116 let page_count = ctx.rdx; 117 let pid = crate::arch::syscall::current_pid(); 118 119 if iova & 0xFFF != 0 { 120 ctx.rax = SyscallResult::error(KernelError::InvalidAddress).raw(); 121 return; 122 } 123 124 let (cap, pml4_phys) = { 125 let ptable = PROCESSES.lock(); 126 let pool = POOL.lock_after(&ptable); 127 match cnode::resolve_caller_validate( 128 pid, 129 cap_addr, 130 ObjectTag::PciDevice, 131 Rights::WRITE, 132 &ptable, 133 &pool, 134 ) { 135 Ok(c) => { 136 let pml4 = ptable 137 .exec(pid) 138 .map(|e| e.pml4_phys) 139 .ok_or(KernelError::InvalidObject); 140 match pml4 { 141 Ok(pml4_phys) => (c, pml4_phys), 142 Err(e) => { 143 ctx.rax = SyscallResult::error(e).raw(); 144 return; 145 } 146 } 147 } 148 Err(e) => { 149 ctx.rax = SyscallResult::error(e).raw(); 150 return; 151 } 152 } 153 }; 154 155 let device_table_idx = { 156 let pool = POOL.lock(); 157 match pool.read_as::<PciDeviceObject>(cap.phys(), cap.generation()) { 158 Ok(d) => d.device_table_idx, 159 Err(e) => { 160 ctx.rax = SyscallResult::error(e).raw(); 161 return; 162 } 163 } 164 }; 165 166 let (bus, devfn) = { 167 let dev_table = DEVICE_TABLE.lock(); 168 match dev_table.get(device_table_idx as usize) { 169 Some(d) => (d.bus, d.devfn()), 170 None => { 171 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 172 return; 173 } 174 } 175 }; 176 177 let hhdm_offset = crate::mem::addr::hhdm_offset(); 178 179 ctx.rax = 180 match crate::iommu::dma_free(bus, devfn, iova, page_count, pml4_phys, pid, hhdm_offset) { 181 Ok(()) => SyscallResult::ok().raw(), 182 Err(e) => SyscallResult::error(e).raw(), 183 }; 184}