Nothing to see here, move along
at main 147 lines 4.6 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::proc::PROCESSES; 7use crate::proc::address_space::map_fb_page_inner; 8use crate::proc::context::CpuContext; 9use crate::syscall::{SyscallResult, try_syscall, validate_user_vaddr}; 10 11use x86_64::PhysAddr; 12use x86_64::structures::paging::{PhysFrame, Size4KiB}; 13 14pub fn sys_fb_info(ctx: &mut CpuContext) { 15 let cap_addr = ctx.rdi; 16 let pid = crate::arch::syscall::current_pid(); 17 18 let cap = { 19 let ptable = PROCESSES.lock(); 20 let pool = POOL.lock_after(&ptable); 21 try_syscall!( 22 ctx, 23 cnode::resolve_caller_validate(pid, cap_addr, ObjectTag::Framebuffer, Rights::READ, &ptable, &pool) 24 ) 25 }; 26 27 let fb_data = { 28 let pool = POOL.lock(); 29 match pool 30 .get(cap.object_id(), cap.generation()) 31 .and_then(|d| d.as_framebuffer()) 32 { 33 Ok(d) => *d, 34 Err(e) => { 35 ctx.rax = SyscallResult::error(e).raw(); 36 return; 37 } 38 } 39 }; 40 41 ctx.rax = ((fb_data.height() as u64) << 32) | (fb_data.width() as u64); 42 ctx.rsi = fb_data.pitch() as u64; 43 ctx.rdx = fb_data.bpp() as u64; 44 ctx.r8 = fb_data.byte_size(); 45} 46 47pub fn sys_fb_map(ctx: &mut CpuContext) { 48 let cap_addr = ctx.rdi; 49 let dest_vaddr = ctx.rsi; 50 let pid = crate::arch::syscall::current_pid(); 51 52 let _ = try_syscall!(ctx, validate_user_vaddr(dest_vaddr)); 53 54 match dest_vaddr & 0xFFF { 55 0 => {} 56 _ => { 57 ctx.rax = SyscallResult::error(KernelError::InvalidAddress).raw(); 58 return; 59 } 60 } 61 62 let ptable = PROCESSES.lock(); 63 let (cap, pml4_phys) = { 64 let pool = POOL.lock_after(&ptable); 65 match cnode::resolve_caller_validate(pid, cap_addr, ObjectTag::Framebuffer, Rights::WRITE, &ptable, &pool) { 66 Ok(c) => { 67 let pml4 = ptable.get(pid).map(|p| p.pml4_phys).ok_or(KernelError::InvalidObject); 68 match pml4 { 69 Ok(pml4_phys) => (c, pml4_phys), 70 Err(e) => { 71 ctx.rax = SyscallResult::error(e).raw(); 72 return; 73 } 74 } 75 } 76 Err(e) => { 77 ctx.rax = SyscallResult::error(e).raw(); 78 return; 79 } 80 } 81 }; 82 83 let fb_data = { 84 let pool = POOL.lock_after(&ptable); 85 match pool 86 .get(cap.object_id(), cap.generation()) 87 .and_then(|d| d.as_framebuffer()) 88 { 89 Ok(d) => *d, 90 Err(e) => { 91 ctx.rax = SyscallResult::error(e).raw(); 92 return; 93 } 94 } 95 }; 96 97 let page_count = fb_data.byte_size().div_ceil(4096) as usize; 98 99 match dest_vaddr.checked_add((page_count as u64) * 4096) { 100 Some(end) if end <= super::USER_ADDR_LIMIT => {} 101 _ => { 102 ctx.rax = SyscallResult::error(KernelError::InvalidAddress).raw(); 103 return; 104 } 105 } 106 107 let mut allocator = crate::mem::phys::BitmapFrameAllocator; 108 109 let result = (0..page_count).try_fold(0usize, |count, i| { 110 let phys = PhysAddr::new(fb_data.phys_addr() + (i as u64) * 4096); 111 let virt = x86_64::VirtAddr::new(dest_vaddr + (i as u64) * 4096); 112 let frame = PhysFrame::<Size4KiB>::containing_address(phys); 113 114 match map_fb_page_inner(pml4_phys, virt, frame, &mut allocator) { 115 Ok(()) => Ok(count + 1), 116 Err(_) => Err((KernelError::ResourceExhausted, count)), 117 } 118 }); 119 120 ctx.rax = match result { 121 Ok(n) => { 122 crate::show!(fb, 123 "pid {} mapped {} pages at virt {:#x} phys {:#x} {} bytes", 124 pid.raw(), 125 n, 126 dest_vaddr, 127 fb_data.phys_addr(), 128 fb_data.byte_size() 129 ); 130 SyscallResult::success(n as u64).raw() 131 } 132 Err((e, mapped)) => { 133 crate::show!(fb, error, 134 "pid {} failed after {} of {} pages {:?}", 135 pid.raw(), 136 mapped, 137 page_count, 138 e 139 ); 140 (0..mapped).for_each(|i| { 141 let virt = x86_64::VirtAddr::new(dest_vaddr + (i as u64) * 4096); 142 let _ = crate::proc::address_space::unmap_user_page(pml4_phys, virt); 143 }); 144 SyscallResult::error(e).raw() 145 } 146 }; 147}