Nothing to see here, move along
at main 200 lines 7.4 kB view raw
1use lancer_core::object_tag::ObjectTag; 2 3use super::object::{ 4 CNodeData, EndpointData, FrameObjectData, IrqHandlerData, IrqSource, NotificationData, 5 ObjectData, PortRange, SchedContextData, 6}; 7use super::pool::ObjectPool; 8use super::table::{CapRef, Rights}; 9use crate::error::KernelError; 10use crate::types::{Generation, ObjectId, Priority}; 11use x86_64::PhysAddr; 12 13const MAX_RETYPE_COUNT: u32 = 64; 14 15fn make_object_data( 16 tag: ObjectTag, 17 frame_phys: Option<PhysAddr>, 18 size_bits: u8, 19) -> Result<ObjectData, KernelError> { 20 match tag { 21 ObjectTag::Endpoint => Ok(ObjectData::Endpoint(EndpointData::new())), 22 ObjectTag::Notification => Ok(ObjectData::Notification(NotificationData::new())), 23 ObjectTag::Frame => { 24 let phys = frame_phys.ok_or(KernelError::InvalidParameter)?; 25 Ok(ObjectData::Frame(FrameObjectData::new_from_untyped(phys))) 26 } 27 ObjectTag::CNode => { 28 let phys = frame_phys.ok_or(KernelError::InvalidParameter)?; 29 let frame_count = lancer_core::cnode::frames_for_cnode(size_bits); 30 Ok(ObjectData::CNode(CNodeData { 31 slots_phys: phys, 32 size_bits, 33 frame_count, 34 })) 35 } 36 ObjectTag::SchedContext => Ok(ObjectData::SchedContext(SchedContextData::new( 37 0, 38 0, 39 Priority::IDLE, 40 ))), 41 ObjectTag::IrqHandler => Ok(ObjectData::IrqHandler(IrqHandlerData { 42 vector: crate::arch::x86_64::idt::IrqVector::new(32), 43 source: IrqSource::Ioapic { 44 gsi: crate::arch::ioapic::Gsi::new(0), 45 }, 46 port_range: match PortRange::new(0, 1) { 47 Some(pr) => pr, 48 None => return Err(KernelError::InvalidParameter), 49 }, 50 })), 51 ObjectTag::Untyped 52 | ObjectTag::Process 53 | ObjectTag::Framebuffer 54 | ObjectTag::PciDevice 55 | ObjectTag::MemoryRegion => Err(KernelError::InvalidType), 56 57 } 58} 59 60#[allow(clippy::too_many_arguments)] 61pub fn kernel_retype( 62 pool: &mut ObjectPool, 63 untyped_id: ObjectId, 64 untyped_gen: Generation, 65 obj_tag: ObjectTag, 66 size_bits: u8, 67 dest_cnode_id: ObjectId, 68 dest_cnode_gen: Generation, 69 dest_addr: u64, 70 dest_depth: u8, 71 count: u32, 72) -> Result<(), KernelError> { 73 match count > MAX_RETYPE_COUNT { 74 true => return Err(KernelError::InvalidParameter), 75 false => {} 76 } 77 78 let untyped_data = pool.get(untyped_id, untyped_gen)?; 79 let untyped = untyped_data.as_untyped()?; 80 let phys_base = untyped.phys_base; 81 82 let result = match obj_tag { 83 ObjectTag::Frame => { 84 untyped.state 85 .try_retype(ObjectTag::Frame, size_bits, count) 86 .map_err(retype_to_kernel_error)? 87 } 88 _ => { 89 make_object_data(obj_tag, None, size_bits)?; 90 let (obj_size, obj_align) = lancer_core::untyped::object_layout(obj_tag, size_bits) 91 .map_err(retype_to_kernel_error)?; 92 untyped.state 93 .try_allocate_raw(obj_size, obj_align, count) 94 .map_err(retype_to_kernel_error)? 95 } 96 }; 97 98 let mut allocated: crate::static_vec::StaticVec<(ObjectId, Generation), { MAX_RETYPE_COUNT as usize }> = 99 crate::static_vec::StaticVec::new(); 100 101 let rollback_result = (0..count).try_for_each(|i| { 102 let obj_phys = phys_base.as_u64() + result.start_offset() as u64 103 + (i as u64) * result.stride() as u64; 104 105 let phys_for_data = match obj_tag { 106 ObjectTag::Frame | ObjectTag::CNode => Some(PhysAddr::new(obj_phys)), 107 _ => None, 108 }; 109 110 if obj_tag == ObjectTag::CNode { 111 let slot_count = 1usize << size_bits; 112 let hhdm = crate::mem::addr::hhdm_offset(); 113 let base_ptr = (obj_phys + hhdm) as *mut u8; 114 let byte_count = slot_count * core::mem::size_of::<super::table::CapSlot>(); 115 unsafe { core::ptr::write_bytes(base_ptr, 0, byte_count) }; 116 } 117 118 let data = make_object_data(obj_tag, phys_for_data, size_bits)?; 119 120 let kern_result = pool 121 .allocate(data) 122 .map_err(|_| KernelError::PoolExhausted)?; 123 let (obj_id, obj_gen) = kern_result; 124 125 let cap = CapRef::new(obj_tag, obj_id, Rights::ALL, obj_gen); 126 let slot_addr = dest_addr + i as u64; 127 match super::cnode::resolve_and_insert( 128 pool, 129 dest_cnode_id, 130 dest_cnode_gen, 131 slot_addr, 132 dest_depth, 133 cap, 134 ) { 135 Ok(()) => { 136 let _ = allocated.push((obj_id, obj_gen)); 137 Ok(()) 138 } 139 Err(e) => { 140 let _ = pool.free(obj_id, obj_gen); 141 Err(e) 142 } 143 } 144 }); 145 146 match rollback_result { 147 Ok(()) => { 148 let untyped_mut = pool.get_mut(untyped_id, untyped_gen)?; 149 let ut = untyped_mut.as_untyped_mut()?; 150 ut.state.commit_retype(&result); 151 152 match obj_tag { 153 ObjectTag::Frame => { 154 (0..count).for_each(|i| { 155 let frame_phys = phys_base.as_u64() 156 + result.start_offset() as u64 157 + (i as u64) * result.stride() as u64; 158 let frame_idx = (frame_phys / 4096) as usize; 159 crate::mem::phys::BitmapFrameAllocator::mark_used(frame_idx); 160 }); 161 } 162 ObjectTag::CNode => { 163 let frame_count = lancer_core::cnode::frames_for_cnode(size_bits) as u32; 164 (0..count).for_each(|i| { 165 let cnode_phys = phys_base.as_u64() 166 + result.start_offset() as u64 167 + (i as u64) * result.stride() as u64; 168 (0..frame_count).for_each(|f| { 169 let frame_idx = ((cnode_phys + f as u64 * 4096) / 4096) as usize; 170 crate::mem::phys::BitmapFrameAllocator::mark_used(frame_idx); 171 }); 172 }); 173 } 174 _ => {} 175 } 176 Ok(()) 177 } 178 Err(e) => { 179 allocated.as_slice().iter().enumerate().for_each(|(i, &(id, generation))| { 180 let slot_addr = dest_addr + i as u64; 181 let _ = super::cnode::resolve_and_clear( 182 pool, dest_cnode_id, dest_cnode_gen, slot_addr, dest_depth, 183 ); 184 let _ = pool.free(id, generation); 185 }); 186 Err(e) 187 } 188 } 189} 190 191fn retype_to_kernel_error(e: lancer_core::untyped::RetypeError) -> KernelError { 192 match e { 193 lancer_core::untyped::RetypeError::InsufficientSpace => KernelError::ResourceExhausted, 194 lancer_core::untyped::RetypeError::DeviceRejectsNonFrame => KernelError::InvalidType, 195 lancer_core::untyped::RetypeError::ZeroCount => KernelError::InvalidParameter, 196 lancer_core::untyped::RetypeError::Overflow => KernelError::InvalidParameter, 197 lancer_core::untyped::RetypeError::InvalidSizeBits => KernelError::InvalidParameter, 198 lancer_core::untyped::RetypeError::InvalidType => KernelError::InvalidType, 199 } 200}