Modify the behavior of mapping segment vmo

This commit is contained in:
Chen Chengjun
2024-04-03 15:28:15 +08:00
committed by Tate, Hongliang Tian
parent 33c8727a13
commit afc4bf7520

View File

@ -27,7 +27,7 @@ use crate::{
vm::{ vm::{
perms::VmPerms, perms::VmPerms,
vmar::Vmar, vmar::Vmar,
vmo::{Vmo, VmoFlags, VmoOptions, VmoRightsOp}, vmo::{Vmo, VmoOptions, VmoRightsOp},
}, },
}; };
@ -198,8 +198,14 @@ pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar<Full>, elf_file: &Dentry) ->
.map_err(|_| Error::with_message(Errno::ENOEXEC, "parse program header type fails"))?; .map_err(|_| Error::with_message(Errno::ENOEXEC, "parse program header type fails"))?;
if type_ == program::Type::Load { if type_ == program::Type::Load {
check_segment_align(program_header)?; check_segment_align(program_header)?;
let vmo = init_segment_vmo(program_header, elf_file)?; let (vmo, anonymous_map_size) = init_segment_vmo(program_header, elf_file)?;
map_segment_vmo(program_header, vmo, root_vmar, base_addr)?; map_segment_vmo(
program_header,
vmo,
anonymous_map_size,
root_vmar,
base_addr,
)?;
} }
} }
Ok(base_addr) Ok(base_addr)
@ -234,6 +240,7 @@ fn base_map_addr(elf: &Elf, root_vmar: &Vmar<Full>) -> Result<Vaddr> {
fn map_segment_vmo( fn map_segment_vmo(
program_header: &ProgramHeader64, program_header: &ProgramHeader64,
vmo: Vmo, vmo: Vmo,
anonymous_map_size: usize,
root_vmar: &Vmar<Full>, root_vmar: &Vmar<Full>,
base_addr: Vaddr, base_addr: Vaddr,
) -> Result<()> { ) -> Result<()> {
@ -245,15 +252,28 @@ fn map_segment_vmo(
program_header.mem_size, program_header.mem_size,
perms perms
); );
let vmo_size = vmo.size();
let mut vm_map_options = root_vmar.new_map(vmo, perms)?.can_overwrite(true); let mut vm_map_options = root_vmar.new_map(vmo, perms)?.can_overwrite(true);
let offset = base_addr + offset; let offset = base_addr + offset;
vm_map_options = vm_map_options.offset(offset); vm_map_options = vm_map_options.offset(offset);
let map_addr = vm_map_options.build()?; let map_addr = vm_map_options.build()?;
if anonymous_map_size > 0 {
let anonymous_vmo = {
let options: VmoOptions<Rights> = VmoOptions::new(anonymous_map_size);
options.alloc()?
};
let mut anonymous_map_options =
root_vmar.new_map(anonymous_vmo, perms)?.can_overwrite(true);
anonymous_map_options = anonymous_map_options.offset(offset + vmo_size);
let anonymous_map_addr = anonymous_map_options.build()?;
}
Ok(()) Ok(())
} }
/// create vmo for each segment /// Create VMO for each segment. Return the segment VMO and the size of
fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<Vmo> { /// additional anonymous mapping it needs.
fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<(Vmo, usize)> {
trace!( trace!(
"mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}", "mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}",
program_header.virtual_addr, program_header.virtual_addr,
@ -277,6 +297,11 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu
"executable has no page cache", "executable has no page cache",
))? ))?
}; };
let vmo_size = {
let vmap_start = virtual_addr.align_down(PAGE_SIZE);
let vmap_end = (virtual_addr + program_header.mem_size as usize).align_up(PAGE_SIZE);
vmap_end - vmap_start
};
let segment_vmo = { let segment_vmo = {
let parent_range = { let parent_range = {
@ -284,20 +309,14 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu
let end = (file_offset + program_header.file_size as usize).align_up(PAGE_SIZE); let end = (file_offset + program_header.file_size as usize).align_up(PAGE_SIZE);
start..end start..end
}; };
let vmo_size = {
let vmap_start = virtual_addr.align_down(PAGE_SIZE);
let vmap_end = (virtual_addr + program_header.mem_size as usize).align_up(PAGE_SIZE);
vmap_end - vmap_start
};
debug_assert!(vmo_size >= (program_header.file_size as usize).align_up(PAGE_SIZE)); debug_assert!(vmo_size >= (program_header.file_size as usize).align_up(PAGE_SIZE));
let segment_vmo = page_cache_vmo page_cache_vmo.new_cow_child(parent_range)?.alloc()?
.new_cow_child(parent_range)? };
.flags(VmoFlags::RESIZABLE)
.alloc()?; let anonymous_map_size: usize = if vmo_size > segment_vmo.size() {
if vmo_size > segment_vmo.size() { vmo_size - segment_vmo.size()
segment_vmo.resize(vmo_size)?; } else {
}; 0
segment_vmo
}; };
// Write zero as paddings. There are head padding and tail padding. // Write zero as paddings. There are head padding and tail padding.
@ -319,7 +338,7 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu
let buffer = vec![0u8; (segment_vmo_size - tail_padding_offset) % PAGE_SIZE]; let buffer = vec![0u8; (segment_vmo_size - tail_padding_offset) % PAGE_SIZE];
segment_vmo.write_bytes(tail_padding_offset, &buffer)?; segment_vmo.write_bytes(tail_padding_offset, &buffer)?;
} }
Ok(segment_vmo.to_dyn()) Ok((segment_vmo.to_dyn(), anonymous_map_size))
} }
fn parse_segment_perm(flags: xmas_elf::program::Flags) -> VmPerm { fn parse_segment_perm(flags: xmas_elf::program::Flags) -> VmPerm {