kernel/sched/loader/
load.rs1use crate::lib::addr::VirtAddr;
7use crate::mm::mm_error::MmResult;
8use crate::mm::pmm::FRAME_SIZE;
9use crate::mm::vmm::Vmm;
10use crate::mm::vmm::address_space::AddressSpace;
11use crate::mm::vmm::traits::VmmPaging;
12use crate::mm::vmm::vma::VmaFlags;
13use crate::sched::loader::defs::phdrs::ElfPhdr;
14use crate::state::kstate::KSTATE;
15
16pub fn map_phdrs_and_copy_elf(addr_space: &mut AddressSpace, phdrs: &[ElfPhdr], elf: &[u8]) -> MmResult<()> {
19 for phdr in phdrs {
20 if phdr.p_type != ElfPhdr::PT_LOAD {
21 continue;
22 }
23
24 let vaddr_start = VirtAddr::new(phdr.p_vaddr).align_down(FRAME_SIZE);
25 let vaddr_end = VirtAddr::new(phdr.p_vaddr + phdr.p_memsz).align_up(FRAME_SIZE);
26 let size = vaddr_end.as_u64() - vaddr_start.as_u64();
27
28 let mut vma_flags = VmaFlags::USER;
29 if phdr.p_flags & ElfPhdr::PF_R != 0 { vma_flags |= VmaFlags::READ; }
30 if phdr.p_flags & ElfPhdr::PF_W != 0 { vma_flags |= VmaFlags::WRITE; }
31 if phdr.p_flags & ElfPhdr::PF_X != 0 { vma_flags |= VmaFlags::EXEC; }
32
33 let mut pmm = unsafe { KSTATE.mm.pmm().lock() };
35
36 Vmm::map_region(
37 &mut pmm,
38 addr_space,
39 vaddr_start,
40 size,
41 vma_flags
42 )?;
43
44 drop(pmm);
45
46 unsafe { copy_segment_data(addr_space, phdr, elf) };
49 }
50 Ok(())
51}
52
53unsafe fn copy_segment_data(addr_space: &AddressSpace, phdr: &ElfPhdr, elf: &[u8]) {
61 let mut copied = 0u64;
62
63 while copied < phdr.p_filesz {
64 let dst_vaddr = phdr.p_vaddr + copied;
65 let page_base = VirtAddr::new(dst_vaddr).align_down(FRAME_SIZE);
66 let offset_in_page = dst_vaddr - page_base.as_u64();
67
68 let phys = Vmm::translate(addr_space.page_ptr(), page_base).unwrap();
69 let remaining_space_in_page = FRAME_SIZE - offset_in_page;
70 let remaining_to_copy = phdr.p_filesz - copied;
71 let chunk = remaining_space_in_page.min(remaining_to_copy);
72
73 unsafe {
74 let src = elf.as_ptr().add((phdr.p_offset + copied) as usize);
75 core::ptr::copy_nonoverlapping(
76 src,
77 phys.as_mut_hhdm_ptr::<u8>().add(offset_in_page as usize),
78 chunk as usize
79 );
80 }
81
82 copied += chunk;
83 }
84}
85
86pub fn setup_user_stack(addr_space: &mut AddressSpace) -> MmResult<VirtAddr> {
88 let stack_size = FRAME_SIZE * 4; let stack_top = crate::mm::layout::USER_STACK_TOP;
90 let stack_bottom = stack_top - stack_size;
91
92 let mut pmm = unsafe { KSTATE.mm.pmm().lock() };
94
95 Vmm::map_region(
97 &mut pmm,
98 addr_space,
99 stack_bottom,
100 stack_size,
101 VmaFlags::USER | VmaFlags::READ | VmaFlags::WRITE
102 )?;
103
104 Ok(stack_top)
105}