Merge branch 'aarch64-stuff' into 'master'
Improve aarch64 code + memory management and crush some bugs See merge request redox-os/kernel!220
This commit is contained in:
+1
-1
Submodule rmm updated: 7aeb9f0ac8...e24e8485ba
@@ -1,5 +1,5 @@
|
||||
use rmm::Flusher;
|
||||
use crate::paging::{KernelMapper, Page, PageFlags, VirtualAddress, mapper::PageFlushAll, entry::EntryFlags};
|
||||
use crate::paging::{KernelMapper, Page, PageFlags, VirtualAddress, mapper::PageFlushAll};
|
||||
|
||||
#[cfg(not(feature="slab"))]
|
||||
pub use self::linked_list::Allocator;
|
||||
@@ -20,7 +20,7 @@ unsafe fn map_heap(mapper: &mut KernelMapper, offset: usize, size: usize) {
|
||||
let heap_start_page = Page::containing_address(VirtualAddress::new(offset));
|
||||
let heap_end_page = Page::containing_address(VirtualAddress::new(offset + size-1));
|
||||
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
|
||||
let result = mapper.map(page.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::GLOBAL.bits(), cfg!(not(feature = "pti"))))
|
||||
let result = mapper.map(page.start_address(), PageFlags::new().write(true).global(cfg!(not(feature = "pti"))))
|
||||
.expect("failed to map kernel heap");
|
||||
flush_all.consume(result);
|
||||
}
|
||||
|
||||
+30
-30
@@ -2,41 +2,41 @@
|
||||
// The lower 256 PML4 entries are reserved for userspace
|
||||
// Each PML4 entry references up to 512 GB of memory
|
||||
// The second from the top (510) PML4 is reserved for the kernel
|
||||
/// The size of a single PML4
|
||||
pub const PML4_SIZE: usize = 0x0000_0080_0000_0000;
|
||||
pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;
|
||||
/// The size of a single PML4
|
||||
pub const PML4_SIZE: usize = 0x0000_0080_0000_0000;
|
||||
pub const PML4_MASK: usize = 0x0000_ff80_0000_0000;
|
||||
|
||||
/// Offset of recursive paging (deprecated, but still reserved)
|
||||
pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize;
|
||||
pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Offset of recursive paging (deprecated, but still reserved)
|
||||
pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize;
|
||||
pub const RECURSIVE_PAGE_PML4: usize = (RECURSIVE_PAGE_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset of kernel
|
||||
pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Offset of kernel
|
||||
pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_PML4: usize = (KERNEL_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to kernel heap
|
||||
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of kernel heap
|
||||
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
|
||||
/// Offset to kernel heap
|
||||
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of kernel heap
|
||||
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
|
||||
|
||||
/// Offset of temporary mapping for misc kernel bring-up actions
|
||||
pub const KERNEL_TMP_MISC_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
|
||||
/// Offset of temporary mapping for misc kernel bring-up actions
|
||||
pub const KERNEL_TMP_MISC_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
|
||||
|
||||
/// Offset to kernel percpu variables
|
||||
pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_TMP_MISC_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_PERCPU_PML4: usize = (KERNEL_PERCPU_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of kernel percpu variables
|
||||
pub const KERNEL_PERCPU_SHIFT: u8 = 16; // 2^16 = 64 KiB
|
||||
pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
|
||||
/// Offset to kernel percpu variables
|
||||
pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_TMP_MISC_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_PERCPU_PML4: usize = (KERNEL_PERCPU_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of kernel percpu variables
|
||||
pub const KERNEL_PERCPU_SHIFT: u8 = 16; // 2^16 = 64 KiB
|
||||
pub const KERNEL_PERCPU_SIZE: usize = 1_usize << KERNEL_PERCPU_SHIFT;
|
||||
|
||||
/// Offset of physmap
|
||||
// This needs to match RMM's PHYS_OFFSET
|
||||
pub const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
|
||||
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Offset of physmap
|
||||
// This needs to match RMM's PHYS_OFFSET
|
||||
pub const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
|
||||
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user image
|
||||
pub const USER_OFFSET: usize = 0;
|
||||
/// Offset to user image
|
||||
pub const USER_OFFSET: usize = 0;
|
||||
|
||||
/// End offset of the user image, i.e. kernel start
|
||||
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
|
||||
/// End offset of the user image, i.e. kernel start
|
||||
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
|
||||
|
||||
@@ -4,9 +4,9 @@ use core::arch::asm;
|
||||
|
||||
bitflags! {
|
||||
pub struct MairEl1: u64 {
|
||||
const DEVICE_MEMORY = 0x00;
|
||||
const DEVICE_MEMORY = 0x00 << 16;
|
||||
const NORMAL_UNCACHED_MEMORY = 0x44 << 8;
|
||||
const NORMAL_WRITEBACK_MEMORY = 0xff << 16;
|
||||
const NORMAL_WRITEBACK_MEMORY = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ macro_rules! function {
|
||||
macro_rules! push_scratch {
|
||||
() => { "
|
||||
// Push scratch registers
|
||||
stp x18, x18, [sp, #-16]!
|
||||
str x18, [sp, #-16]!
|
||||
stp x16, x17, [sp, #-16]!
|
||||
stp x14, x15, [sp, #-16]!
|
||||
stp x12, x13, [sp, #-16]!
|
||||
@@ -266,7 +266,7 @@ macro_rules! pop_scratch {
|
||||
ldp x12, x13, [sp], #16
|
||||
ldp x14, x15, [sp], #16
|
||||
ldp x16, x17, [sp], #16
|
||||
ldp x18, x18, [sp], #16
|
||||
ldr x18, [sp], #16
|
||||
" };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
//! # Page table entry
|
||||
//! Some code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html)
|
||||
|
||||
use crate::memory::Frame;
|
||||
|
||||
use super::{PageFlags, PhysicalAddress, RmmA, RmmArch};
|
||||
|
||||
/// A page table entry
|
||||
#[derive(Debug)]
|
||||
pub struct Entry(u64);
|
||||
|
||||
/// A page descriptor
|
||||
#[derive(Debug)]
|
||||
pub struct PageDescriptor(u64);
|
||||
|
||||
bitflags! {
|
||||
pub struct TableDescriptorFlags: u64 {
|
||||
const PRESENT = 1 << 0;
|
||||
const VALID = 1 << 0;
|
||||
const TABLE = 1 << 1;
|
||||
const AF = 1 << 10; /* NOTE: TableDescriptors don't actually have an AF bit! */
|
||||
const PXNTABLE = 1 << 59;
|
||||
const UXNTABLE = 1 << 60;
|
||||
const APTABLE_0 = 1 << 61;
|
||||
const APTABLE_1 = 1 << 62;
|
||||
const SUBLEVEL_NO_EL0_ACCESS = (0 << 62) | (1 << 61);
|
||||
const SUBLEVEL_NO_WANY_ACCESS = (1 << 62) | (0 << 61);
|
||||
const SUBLEVEL_NO_WANY_NO_REL0 = (1 << 62) | (1 << 61);
|
||||
const NSTABLE = 1 << 63;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct PageDescriptorFlags: u64 {
|
||||
const PRESENT = 1 << 0;
|
||||
const VALID = 1 << 0;
|
||||
const PAGE = 1 << 1;
|
||||
const ATTR_INDEX_0 = 1 << 2;
|
||||
const ATTR_INDEX_1 = 1 << 3;
|
||||
const ATTR_INDEX_2 = 1 << 4;
|
||||
const NS = 1 << 5;
|
||||
const AP_1 = 1 << 6;
|
||||
const AP_2 = 1 << 7;
|
||||
const SH_0 = 1 << 8;
|
||||
const SH_1 = 1 << 9;
|
||||
const AF = 1 << 10;
|
||||
const NG = 1 << 11;
|
||||
const DBM = 1 << 51;
|
||||
const CONTIGUOUS = 1 << 52;
|
||||
const PXN = 1 << 53;
|
||||
const UXN = 1 << 54;
|
||||
}
|
||||
}
|
||||
|
||||
// These are 'virtual' flags that are used to minimise changes to the generic paging code.
|
||||
// These are translated to AArch64 specific Page and Table descriptors as and when needed.
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct EntryFlags: usize {
|
||||
const PRESENT = 1 << 0;
|
||||
const HUGE_PAGE = 1 << 1;
|
||||
const GLOBAL = 1 << 2;
|
||||
const NO_EXECUTE = 1 << 3;
|
||||
const USER_ACCESSIBLE = 1 << 4;
|
||||
const WRITABLE = 1 << 5;
|
||||
const TLS = 1 << 6;
|
||||
const AF = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
pub const ADDRESS_MASK: usize = 0x0000_ffff_ffff_f000;
|
||||
pub const COUNTER_MASK: u64 = 0x0008_0000_0000_0000;
|
||||
|
||||
impl Entry {
|
||||
/// Clear entry
|
||||
pub fn set_zero(&mut self) {
|
||||
self.0 = 0;
|
||||
}
|
||||
|
||||
/// Is the entry unused?
|
||||
pub fn is_unused(&self) -> bool {
|
||||
self.0 == (self.0 & COUNTER_MASK)
|
||||
}
|
||||
|
||||
/// Make the entry unused
|
||||
pub fn set_unused(&mut self) {
|
||||
self.0 &= COUNTER_MASK;
|
||||
}
|
||||
|
||||
/// Get the address this page references
|
||||
pub fn address(&self) -> PhysicalAddress {
|
||||
PhysicalAddress::new(self.0 as usize & ADDRESS_MASK)
|
||||
}
|
||||
|
||||
/// Get the current entry flags
|
||||
pub fn page_table_entry_flags(&self) -> TableDescriptorFlags {
|
||||
TableDescriptorFlags::from_bits_truncate(self.0)
|
||||
}
|
||||
|
||||
pub fn page_descriptor_entry_flags(&self) -> PageDescriptorFlags {
|
||||
PageDescriptorFlags::from_bits_truncate(self.0)
|
||||
}
|
||||
|
||||
/// Get the current entry flags
|
||||
pub fn flags(&self) -> PageFlags<RmmA> {
|
||||
unsafe { PageFlags::from_data((self.0 as usize & RmmA::ENTRY_FLAGS_MASK) & !(COUNTER_MASK as usize)) }
|
||||
}
|
||||
|
||||
/// Get the associated frame, if available, for a level 4, 3, or 2 page
|
||||
pub fn pointed_frame(&self) -> Option<Frame> {
|
||||
if self.page_table_entry_flags().contains(TableDescriptorFlags::VALID) {
|
||||
Some(Frame::containing_address(self.address()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the associated frame, if available, for a level 1 page
|
||||
pub fn pointed_frame_at_l1(&self) -> Option<Frame> {
|
||||
if self.page_descriptor_entry_flags().contains(PageDescriptorFlags::VALID) {
|
||||
Some(Frame::containing_address(self.address()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn page_table_entry_set(&mut self, frame: Frame, flags: TableDescriptorFlags) {
|
||||
debug_assert!(frame.start_address().data() & !ADDRESS_MASK == 0);
|
||||
// ODDNESS Alert: We need to set the AF bit - despite this being a TableDescriptor!!!
|
||||
// The Arm ARM says this bit (bit 10) is IGNORED in Table Descriptors so hopefully this is OK
|
||||
let access_flag = TableDescriptorFlags::AF;
|
||||
self.0 = (frame.start_address().data() as u64) | flags.bits() | access_flag.bits() | (self.0 & COUNTER_MASK);
|
||||
}
|
||||
|
||||
pub fn page_descriptor_entry_set(&mut self, frame: Frame, flags: PageDescriptorFlags) {
|
||||
debug_assert!(frame.start_address().data() & !ADDRESS_MASK == 0);
|
||||
let access_flag = PageDescriptorFlags::AF;
|
||||
self.0 = (frame.start_address().data() as u64) | flags.bits() | access_flag.bits() | (self.0 & COUNTER_MASK);
|
||||
}
|
||||
|
||||
pub fn set(&mut self, frame: Frame, flags: PageFlags<RmmA>) {
|
||||
debug_assert!(frame.start_address().data() & !ADDRESS_MASK == 0);
|
||||
self.0 = (frame.start_address().data() as u64) | (flags.data() as u64) | (self.0 & COUNTER_MASK);
|
||||
}
|
||||
|
||||
/// Get bit 51 in entry, used as 1 of 9 bits (in 9 entries) used as a counter for the page table
|
||||
pub fn counter_bits(&self) -> u64 {
|
||||
(self.0 & COUNTER_MASK) >> 51
|
||||
}
|
||||
|
||||
/// Set bit 51 in entry, used as 1 of 9 bits (in 9 entries) used as a counter for the page table
|
||||
pub fn set_counter_bits(&mut self, count: u64) {
|
||||
self.0 = (self.0 & !COUNTER_MASK) | ((count & 0x1) << 51);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ use core::{mem, ptr};
|
||||
|
||||
use crate::device::cpu::registers::{control_regs, tlb};
|
||||
|
||||
use self::entry::EntryFlags;
|
||||
use self::mapper::PageFlushAll;
|
||||
|
||||
pub use rmm::{
|
||||
@@ -21,7 +20,6 @@ pub use super::CurrentRmmArch as RmmA;
|
||||
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
|
||||
pub use crate::rmm::KernelMapper;
|
||||
|
||||
pub mod entry;
|
||||
pub mod mapper;
|
||||
|
||||
/// Number of entries per page table
|
||||
@@ -64,7 +62,7 @@ unsafe fn map_percpu(cpu_id: usize, mapper: &mut PageMapper) -> PageFlushAll<Rmm
|
||||
for page in Page::range_inclusive(start_page, end_page) {
|
||||
let result = mapper.map(
|
||||
page.start_address(),
|
||||
PageFlags::new().write(true).custom_flag(EntryFlags::GLOBAL.bits(), cfg!(not(feature = "pti"))),
|
||||
PageFlags::new().write(true).global(cfg!(not(feature = "pti"))),
|
||||
)
|
||||
.expect("failed to allocate page table frames while mapping percpu");
|
||||
flush_all.consume(result);
|
||||
|
||||
@@ -178,7 +178,6 @@ unsafe fn inner<A: Arch>(
|
||||
#[cfg(feature = "graphical_debug")]
|
||||
{
|
||||
use crate::devices::graphical_debug::FRAMEBUFFER;
|
||||
use super::paging::entry::EntryFlags;
|
||||
|
||||
let (phys, virt, size) = *FRAMEBUFFER.lock();
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ pub struct KernelArgs {
|
||||
|
||||
/// The entry to Rust, all things must be initialized
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
|
||||
pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! {
|
||||
let bootstrap = {
|
||||
let args = &*args_ptr;
|
||||
|
||||
@@ -113,15 +113,12 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
|
||||
info!("Bootstrap entry point: {:X}", {args.bootstrap_entry});
|
||||
|
||||
// Setup interrupt handlers
|
||||
extern "C" {
|
||||
fn exception_vector_base();
|
||||
}
|
||||
core::arch::asm!(
|
||||
"
|
||||
ldr x0, =exception_vector_base
|
||||
msr vbar_el1, x0
|
||||
ldr {tmp}, =exception_vector_base
|
||||
msr vbar_el1, {tmp}
|
||||
",
|
||||
out("x0") _,
|
||||
tmp = out(reg) _,
|
||||
);
|
||||
|
||||
/* NOT USED WITH UEFI
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use core::{mem, ptr};
|
||||
use x86::msr;
|
||||
|
||||
use self::entry::EntryFlags;
|
||||
use self::mapper::PageFlushAll;
|
||||
|
||||
pub use rmm::{
|
||||
@@ -84,7 +83,7 @@ unsafe fn map_percpu(cpu_id: usize, mapper: &mut PageMapper) -> PageFlushAll<Rmm
|
||||
for page in Page::range_inclusive(start_page, end_page) {
|
||||
let result = mapper.map(
|
||||
page.start_address(),
|
||||
PageFlags::new().write(true).custom_flag(EntryFlags::GLOBAL.bits(), cfg!(not(feature = "pti"))),
|
||||
PageFlags::new().write(true).global(cfg!(not(feature = "pti"))),
|
||||
)
|
||||
.expect("failed to allocate page table frames while mapping percpu");
|
||||
flush_all.consume(result);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
use core::{mem, ptr};
|
||||
use x86::msr;
|
||||
|
||||
use self::entry::EntryFlags;
|
||||
use self::mapper::PageFlushAll;
|
||||
|
||||
pub use rmm::{
|
||||
@@ -84,7 +83,7 @@ unsafe fn map_percpu(cpu_id: usize, mapper: &mut PageMapper) -> PageFlushAll<Rmm
|
||||
for page in Page::range_inclusive(start_page, end_page) {
|
||||
let result = mapper.map(
|
||||
page.start_address(),
|
||||
PageFlags::new().write(true).custom_flag(EntryFlags::GLOBAL.bits(), cfg!(not(feature = "pti"))),
|
||||
PageFlags::new().write(true).global(cfg!(not(feature = "pti"))),
|
||||
)
|
||||
.expect("failed to allocate page table frames while mapping percpu");
|
||||
flush_all.consume(result);
|
||||
|
||||
+5
-2
@@ -91,11 +91,12 @@ impl ContextList {
|
||||
let _ = context.set_addr_space(super::memory::new_addrspace()?);
|
||||
|
||||
let mut stack = vec![0; 65_536].into_boxed_slice();
|
||||
let offset = stack.len() - mem::size_of::<usize>();
|
||||
let mut offset = stack.len();
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
unsafe {
|
||||
let offset = stack.len() - mem::size_of::<usize>();
|
||||
// Space for return address on stack
|
||||
offset -= mem::size_of::<usize>();
|
||||
let func_ptr = stack.as_mut_ptr().add(offset);
|
||||
*(func_ptr as *mut usize) = func as usize;
|
||||
}
|
||||
@@ -105,6 +106,8 @@ impl ContextList {
|
||||
let context_id = context.id.into();
|
||||
context.arch.set_lr(func as usize);
|
||||
context.arch.set_context_handle();
|
||||
// Stack should be 16 byte aligned
|
||||
offset -= (stack.as_ptr() as usize + offset) % 16;
|
||||
}
|
||||
|
||||
context.arch.set_stack(stack.as_ptr() as usize + offset);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
use crate::interrupt::InterruptStack;
|
||||
use crate::memory::{allocate_frames_complex, deallocate_frames, Frame, PAGE_SIZE};
|
||||
use crate::paging::{PageFlags, PhysicalAddress, VirtualAddress, mapper::PageFlushAll};
|
||||
use crate::paging::entry::EntryFlags;
|
||||
use crate::context;
|
||||
use crate::context::memory::{Grant, Region};
|
||||
use crate::syscall::error::{Error, EFAULT, EINVAL, ENOMEM, EPERM, ESRCH, Result};
|
||||
use crate::syscall::flag::{PhysallocFlags, PartialAllocStrategy, PhysmapFlags, PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE, PHYSMAP_NO_CACHE};
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
use crate::paging::entry::EntryFlags;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
fn enforce_root() -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user