Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 9.4 kB View raw
1use crate::arch::x86_64::idt::{ 2 ERROR_VECTOR, IPI_FUNC_CALL_VECTOR, IPI_HALT_VECTOR, IPI_RESCHEDULE_VECTOR, 3 IPI_TLB_SHOOTDOWN_VECTOR, IrqVector, SPURIOUS_VECTOR, TIMER_VECTOR, 4}; 5use crate::cap::cnode; 6use crate::cap::object::{IoPort, IrqSource, ObjectTag, PortRange}; 7use crate::cap::pool::POOL; 8use crate::cap::table::Rights; 9use crate::error::KernelError; 10use crate::irq; 11use crate::proc::PROCESSES; 12use crate::proc::context::CpuContext; 13use crate::syscall::{SyscallResult, try_syscall}; 14use crate::types::Pid; 15use lancer_core::object_layout::IrqHandlerObject; 16 17pub(crate) fn is_reserved_vector(v: IrqVector) -> bool { 18 matches!( 19 v.raw(), 20 TIMER_VECTOR_RAW 21 | ERROR_VECTOR_RAW 22 | SPURIOUS_VECTOR_RAW 23 | IPI_RESCHEDULE_RAW 24 | IPI_TLB_SHOOTDOWN_RAW 25 | IPI_HALT_RAW 26 | IPI_FUNC_CALL_RAW 27 ) 28} 29 30const TIMER_VECTOR_RAW: u8 = TIMER_VECTOR.raw(); 31const ERROR_VECTOR_RAW: u8 = ERROR_VECTOR.raw(); 32const SPURIOUS_VECTOR_RAW: u8 = SPURIOUS_VECTOR.raw(); 33const IPI_RESCHEDULE_RAW: u8 = IPI_RESCHEDULE_VECTOR.raw(); 34const IPI_TLB_SHOOTDOWN_RAW: u8 = IPI_TLB_SHOOTDOWN_VECTOR.raw(); 35const IPI_HALT_RAW: u8 = IPI_HALT_VECTOR.raw(); 36const IPI_FUNC_CALL_RAW: u8 = IPI_FUNC_CALL_VECTOR.raw(); 37 38fn decode_irq_source(obj: &IrqHandlerObject) -> IrqSource { 39 match obj.source_kind { 40 1 => IrqSource::Msix { 41 device_table_idx: obj.source_data as u8, 42 entry_idx: (obj.source_data >> 8) as u16, 43 }, 44 _ => IrqSource::Ioapic { 45 gsi: crate::arch::ioapic::Gsi::new(obj.source_data), 46 }, 47 } 48} 49 50fn port_range_from_obj(obj: &IrqHandlerObject) -> Option<PortRange> { 51 PortRange::new(obj.port_base, obj.port_count) 52} 53 54pub fn sys_irq_bind(ctx: &mut CpuContext) { 55 let irq_cap_addr = ctx.rdi; 56 let notif_cap_addr = ctx.rsi; 57 let bit = 58 match crate::types::NotificationBit::new(try_syscall!(ctx, super::u8_from_reg(ctx.rdx))) { 59 Some(b) => b, 60 None => { 61 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 62 return; 63 } 64 }; 65 let pid = crate::arch::syscall::current_pid(); 66 67 let ptable = PROCESSES.lock(); 68 let pool = POOL.lock_after(&ptable); 69 70 let irq_cap = try_syscall!( 71 ctx, 72 cnode::resolve_caller_validate( 73 pid, 74 irq_cap_addr, 75 ObjectTag::IrqHandler, 76 Rights::WRITE, 77 &ptable, 78 &pool 79 ) 80 ); 81 82 let (vector, source) = 83 match pool.read_as::<IrqHandlerObject>(irq_cap.phys(), irq_cap.generation()) { 84 Ok(h) => match IrqVector::try_new(h.vector) { 85 Some(v) => (v, decode_irq_source(h)), 86 None => { 87 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 88 return; 89 } 90 }, 91 Err(e) => { 92 ctx.rax = SyscallResult::error(e).raw(); 93 return; 94 } 95 }; 96 97 let notif_cap = try_syscall!( 98 ctx, 99 cnode::resolve_caller_validate( 100 pid, 101 notif_cap_addr, 102 ObjectTag::Notification, 103 Rights::WRITE, 104 &ptable, 105 &pool 106 ) 107 ); 108 109 let notif_id = notif_cap.phys(); 110 let notif_gen = notif_cap.generation(); 111 112 drop(pool); 113 drop(ptable); 114 115 ctx.rax = match irq::bind(vector, source, notif_id, notif_gen, bit) { 116 Ok(()) => SyscallResult::ok().raw(), 117 Err(e) => SyscallResult::error(e).raw(), 118 }; 119} 120 121pub fn sys_irq_ack(ctx: &mut CpuContext) { 122 let irq_cap_addr = ctx.rdi; 123 let pid = crate::arch::syscall::current_pid(); 124 125 let ptable = PROCESSES.lock(); 126 let irq_cap = { 127 let pool = POOL.lock_after(&ptable); 128 try_syscall!( 129 ctx, 130 cnode::resolve_caller_validate( 131 pid, 132 irq_cap_addr, 133 ObjectTag::IrqHandler, 134 Rights::WRITE, 135 &ptable, 136 &pool 137 ) 138 ) 139 }; 140 141 let source = { 142 let pool = POOL.lock_after(&ptable); 143 match pool.read_as::<IrqHandlerObject>(irq_cap.phys(), irq_cap.generation()) { 144 Ok(h) => decode_irq_source(h), 145 Err(e) => { 146 ctx.rax = SyscallResult::error(e).raw(); 147 return; 148 } 149 } 150 }; 151 152 drop(ptable); 153 154 match source { 155 IrqSource::Ioapic { gsi } => crate::arch::ioapic::unmask_irq(gsi), 156 IrqSource::Msix { 157 device_table_idx, 158 entry_idx, 159 } => { 160 let _ = crate::pci::msix::unmask_entry(device_table_idx, entry_idx); 161 } 162 } 163 164 ctx.rax = SyscallResult::ok().raw(); 165} 166 167pub fn sys_io_in8(ctx: &mut CpuContext) { 168 let irq_cap_addr = ctx.rdi; 169 let port = IoPort::new(try_syscall!(ctx, super::u16_from_reg(ctx.rsi))); 170 let pid = crate::arch::syscall::current_pid(); 171 172 let ptable = PROCESSES.lock(); 173 let irq_cap = { 174 let pool = POOL.lock_after(&ptable); 175 try_syscall!( 176 ctx, 177 cnode::resolve_caller_validate( 178 pid, 179 irq_cap_addr, 180 ObjectTag::IrqHandler, 181 Rights::READ, 182 &ptable, 183 &pool 184 ) 185 ) 186 }; 187 188 { 189 let pool = POOL.lock_after(&ptable); 190 match pool.read_as::<IrqHandlerObject>(irq_cap.phys(), irq_cap.generation()) { 191 Ok(h) => match port_range_from_obj(h) { 192 Some(pr) if pr.contains(port) => {} 193 _ => { 194 ctx.rax = SyscallResult::error(KernelError::PermissionDenied).raw(); 195 return; 196 } 197 }, 198 Err(e) => { 199 ctx.rax = SyscallResult::error(e).raw(); 200 return; 201 } 202 } 203 } 204 205 drop(ptable); 206 207 let val: u8 = unsafe { x86_64::instructions::port::Port::new(port.raw()).read() }; 208 ctx.rax = SyscallResult::success(val as u64).raw(); 209} 210 211pub fn sys_io_out8(ctx: &mut CpuContext) { 212 let irq_cap_addr = ctx.rdi; 213 let port = IoPort::new(try_syscall!(ctx, super::u16_from_reg(ctx.rsi))); 214 let val = try_syscall!(ctx, super::u8_from_reg(ctx.rdx)); 215 let pid = crate::arch::syscall::current_pid(); 216 217 let ptable = PROCESSES.lock(); 218 let irq_cap = { 219 let pool = POOL.lock_after(&ptable); 220 try_syscall!( 221 ctx, 222 cnode::resolve_caller_validate( 223 pid, 224 irq_cap_addr, 225 ObjectTag::IrqHandler, 226 Rights::WRITE, 227 &ptable, 228 &pool 229 ) 230 ) 231 }; 232 233 { 234 let pool = POOL.lock_after(&ptable); 235 match pool.read_as::<IrqHandlerObject>(irq_cap.phys(), irq_cap.generation()) { 236 Ok(h) => match port_range_from_obj(h) { 237 Some(pr) if pr.contains(port) => {} 238 _ => { 239 ctx.rax = SyscallResult::error(KernelError::PermissionDenied).raw(); 240 return; 241 } 242 }, 243 Err(e) => { 244 ctx.rax = SyscallResult::error(e).raw(); 245 return; 246 } 247 } 248 } 249 250 drop(ptable); 251 252 unsafe { x86_64::instructions::port::Port::new(port.raw()).write(val) }; 253 ctx.rax = SyscallResult::ok().raw(); 254} 255 256pub fn sys_irq_configure(ctx: &mut CpuContext) { 257 let pid = crate::arch::syscall::current_pid(); 258 259 if pid != Pid::new(0) { 260 ctx.rax = SyscallResult::error(KernelError::PermissionDenied).raw(); 261 return; 262 } 263 264 let irq_addr = ctx.rdi; 265 let gsi = crate::arch::ioapic::Gsi::new(try_syscall!(ctx, super::u32_from_reg(ctx.rsi))); 266 let vector = match IrqVector::try_new(try_syscall!(ctx, super::u8_from_reg(ctx.rdx))) { 267 Some(v) => v, 268 None => { 269 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 270 return; 271 } 272 }; 273 let port_base = try_syscall!(ctx, super::u16_from_reg(ctx.r10)); 274 let port_count = try_syscall!(ctx, super::u16_from_reg(ctx.r8)); 275 276 if is_reserved_vector(vector) { 277 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 278 return; 279 } 280 281 let _port_range = match PortRange::new(port_base, port_count) { 282 Some(pr) => pr, 283 None => { 284 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 285 return; 286 } 287 }; 288 289 let ptable = PROCESSES.lock(); 290 let cap = { 291 let pool = POOL.lock_after(&ptable); 292 try_syscall!( 293 ctx, 294 cnode::resolve_caller_validate( 295 pid, 296 irq_addr, 297 ObjectTag::IrqHandler, 298 Rights::WRITE, 299 &ptable, 300 &pool, 301 ) 302 ) 303 }; 304 305 let mut pool = POOL.lock_after(&ptable); 306 ctx.rax = match pool.write_as::<IrqHandlerObject>(cap.phys(), cap.generation()) { 307 Ok(h) => { 308 h.vector = vector.raw(); 309 h.source_kind = 0; 310 h.source_data = gsi.raw(); 311 h.port_base = port_base; 312 h.port_count = port_count; 313 SyscallResult::ok().raw() 314 } 315 Err(e) => SyscallResult::error(e).raw(), 316 }; 317}