aarch64: clone: Introduce kernel and user space specific mods

At present these are done 'wholesale' without any regard for x86_64.
That needs to change eventually.
This commit is contained in:
Robin Randhawa
2021-01-18 21:50:19 +00:00
parent c188a60871
commit fd0336692d
3 changed files with 43 additions and 28 deletions

View File

@@ -14,6 +14,7 @@ pub struct Context {
elr_el1: usize,
sp_el0: usize,
ttbr0_el1: usize, /* Pointer to U4 translation table for this Context */
ttbr1_el1: usize, /* Pointer to P4 translation table for this Context */
tpidr_el0: usize, /* Pointer to TLS region for this Context */
tpidrro_el0: usize, /* Pointer to TLS (read-only) region for this Context */
rflags: usize,
@@ -53,6 +54,7 @@ impl Context {
elr_el1: 0,
sp_el0: 0,
ttbr0_el1: 0,
ttbr1_el1: 0,
tpidr_el0: 0,
tpidrro_el0: 0,
rflags: 0, /* spsr_el1 */
@@ -92,10 +94,14 @@ impl Context {
pub fn set_fx(&mut self, _address: usize) {
}
pub fn set_page_table(&mut self, address: usize) {
pub fn set_page_utable(&mut self, address: usize) {
self.ttbr0_el1 = address;
}
pub fn set_page_ktable(&mut self, address: usize) {
self.ttbr1_el1 = address;
}
pub fn set_stack(&mut self, address: usize) {
self.sp = address;
}

View File

@@ -96,7 +96,8 @@ impl ContextList {
context.arch.set_context_handle();
}
context.arch.set_page_table(unsafe { ActivePageTable::new(PageTableType::User).address() });
context.arch.set_page_utable(unsafe { ActivePageTable::new(PageTableType::User).address() });
context.arch.set_page_ktable(unsafe { ActivePageTable::new(PageTableType::Kernel).address() });
context.arch.set_fx(fx.as_ptr() as usize);
context.arch.set_stack(stack.as_ptr() as usize + offset);
context.kfx = Some(fx);

View File

@@ -343,31 +343,39 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
context.arch = arch;
let mut active_table = unsafe { ActivePageTable::new(PageTableType::User) };
let mut active_utable = unsafe { ActivePageTable::new(PageTableType::User) };
let mut active_ktable = unsafe { ActivePageTable::new(PageTableType::Kernel) };
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::USER_TMP_MISC_OFFSET)));
let mut temporary_upage = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::USER_TMP_MISC_OFFSET)));
let mut temporary_kpage = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::KERNEL_TMP_MISC_OFFSET)));
let mut new_table = {
let mut new_utable = {
let frame = allocate_frames(1).expect("no more frames in syscall::clone new_table");
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
InactivePageTable::new(frame, &mut active_utable, &mut temporary_upage)
};
context.arch.set_page_table(unsafe { new_table.address() });
let mut new_ktable = {
let frame = allocate_frames(1).expect("no more frames in syscall::clone new_table");
InactivePageTable::new(frame, &mut active_ktable, &mut temporary_kpage)
};
context.arch.set_page_utable(unsafe { new_utable.address() });
context.arch.set_page_ktable(unsafe { new_ktable.address() });
// Copy kernel image mapping
{
let frame = active_table.p4()[crate::KERNEL_PML4].pointed_frame().expect("kernel image not mapped");
let flags = active_table.p4()[crate::KERNEL_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_ktable.p4()[crate::KERNEL_PML4].pointed_frame().expect("kernel image not mapped");
let flags = active_ktable.p4()[crate::KERNEL_PML4].flags();
active_ktable.with(&mut new_ktable, &mut temporary_kpage, |mapper| {
mapper.p4_mut()[crate::KERNEL_PML4].set(frame, flags);
});
}
// Copy kernel heap mapping
{
let frame = active_table.p4()[crate::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped");
let flags = active_table.p4()[crate::KERNEL_HEAP_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_ktable.p4()[crate::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped");
let flags = active_ktable.p4()[crate::KERNEL_HEAP_PML4].flags();
active_ktable.with(&mut new_ktable, &mut temporary_kpage, |mapper| {
mapper.p4_mut()[crate::KERNEL_HEAP_PML4].set(frame, flags);
});
}
@@ -389,9 +397,9 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
if flags.contains(CLONE_VM) {
// Copy user image mapping, if found
if ! image.is_empty() {
let frame = active_table.p4()[crate::USER_PML4].pointed_frame().expect("user image not mapped");
let flags = active_table.p4()[crate::USER_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_PML4].pointed_frame().expect("user image not mapped");
let flags = active_utable.p4()[crate::USER_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_PML4].set(frame, flags);
});
}
@@ -437,7 +445,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
for memory_shared in image.iter_mut() {
memory_shared.with(|memory| {
let start = VirtualAddress::new(memory.start_address().data() - crate::USER_TMP_OFFSET + crate::USER_OFFSET);
memory.move_to(start, &mut new_table, &mut temporary_page);
memory.move_to(start, &mut new_utable, &mut temporary_upage);
});
}
context.image = image;
@@ -449,7 +457,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
for mut grant in old_grants.inner.into_iter() {
let start = VirtualAddress::new(grant.start_address().data() + crate::USER_GRANT_OFFSET - crate::USER_TMP_GRANT_OFFSET);
grant.move_to(start, &mut new_table, &mut temporary_page);
grant.move_to(start, &mut new_utable, &mut temporary_upage);
grants.insert(grant);
}
}
@@ -459,14 +467,14 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// Setup user stack
if let Some(stack_shared) = stack_opt {
if flags.contains(CLONE_STACK) {
let frame = active_table.p4()[crate::USER_STACK_PML4].pointed_frame().expect("user stack not mapped");
let flags = active_table.p4()[crate::USER_STACK_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_STACK_PML4].pointed_frame().expect("user stack not mapped");
let flags = active_utable.p4()[crate::USER_STACK_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_STACK_PML4].set(frame, flags);
});
} else {
stack_shared.with(|stack| {
stack.move_to(VirtualAddress::new(crate::USER_STACK_OFFSET), &mut new_table, &mut temporary_page);
stack.move_to(VirtualAddress::new(crate::USER_STACK_OFFSET), &mut new_utable, &mut temporary_upage);
});
}
context.stack = Some(stack_shared);
@@ -474,7 +482,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// Setup user sigstack
if let Some(mut sigstack) = sigstack_opt {
sigstack.move_to(VirtualAddress::new(crate::USER_SIGSTACK_OFFSET), &mut new_table, &mut temporary_page);
sigstack.move_to(VirtualAddress::new(crate::USER_SIGSTACK_OFFSET), &mut new_utable, &mut temporary_upage);
context.sigstack = Some(sigstack);
}
@@ -491,9 +499,9 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
if let Some(mut tls) = tls_opt {
// Copy TLS mapping
{
let frame = active_table.p4()[crate::USER_TLS_PML4].pointed_frame().expect("user tls not mapped");
let flags = active_table.p4()[crate::USER_TLS_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_TLS_PML4].pointed_frame().expect("user tls not mapped");
let flags = active_utable.p4()[crate::USER_TLS_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_TLS_PML4].set(frame, flags);
});
}
@@ -501,7 +509,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// TODO: Make sure size is not greater than USER_TLS_SIZE
let tls_addr = crate::USER_TLS_OFFSET + context.id.into() * crate::USER_TLS_SIZE;
//println!("{}: Copy TLS: address 0x{:x}, size 0x{:x}", context.id.into(), tls_addr, tls.mem.size());
tls.mem.move_to(VirtualAddress::new(tls_addr), &mut new_table, &mut temporary_page);
tls.mem.move_to(VirtualAddress::new(tls_addr), &mut new_utable, &mut temporary_upage);
unsafe {
*(tcb_addr as *mut usize) = tls.mem.start_address().data() + tls.mem.size();
}
@@ -516,7 +524,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
}
}
tcb.move_to(VirtualAddress::new(tcb_addr), &mut new_table, &mut temporary_page);
tcb.move_to(VirtualAddress::new(tcb_addr), &mut new_utable, &mut temporary_upage);
context.image.push(tcb.to_shared());
context.name = name;