Add x64 support and various fixes
x64 support:
- Add architecture-specific code
- Teach Hier about 48-bit virtual addresses
- Teach bootstrap about x64
- Fix 48-bit virtual address handling: Addresses are sign-extended (8000'00000000 must be encoded as FFFF8000'00000000)
Various fixes:
- Use current versions of sel4 libraries
- Fix order of HIER_LEVELS level_sizes (Larger pages get mapped in higher level page tables)
- Use new bootinfo method for untyped info (issue #2 (closed))
- Remove use of Allocatable::object_type (issue #2 (closed))
- Refactor page mapping to use walk_table_range
- Refactor change_protection to be in Hier
- Fix calls to MAP_PAGE to use root page table (closes #3 (closed))
- Call MAP_FNS to map new page tables (closes #4 (closed))
- Give vspace root in Hier during bootstrap
- Fix walking a range of vaddrs in hier
- Fix bump allocator to update watermark
- Calculate bytes used correctly in utspace
- Make change_protection update metadata and check return value
- Bootstrap image pages into mapping metadata
- Use page remap operation to change vm protection (closes #7 (closed))
- Update to intrusive-collections v0.6.2 (fixes build break on rust nightly)
- Track reservation bytes instead of pages
- Fix adding memory to frame allocator
- Fix freeing of cptr in bitmap allocator
Additional features:
- Bootstrap a stack guard page
To test, follow directions for hello-world, with the following changes.
Add to Cargo.toml:
[dependencies]
sel4-sys = { version = "0.0.28", path = "../sel4-sys" }
sel4-start = { version = "0.0.28", path = "../sel4-start" }
sel4-alloc = { version = "0.0.18", path = "../sel4-alloc" }
sel4 = { version = "0.0.12", path = "../rust-sel4" }
Create Xargo.toml:
[target.x86_64-sel4-robigalia.dependencies]
collections = {}
Change main.rs to:
#![no_std]
extern crate sel4_start;
extern crate sel4_sys;
extern crate sel4_alloc;
extern crate sel4;
use sel4_sys::*;
use sel4::*;
use sel4_start::BOOTINFO;
use sel4_alloc::*;
extern { static _stack_bottom : u8; }
fn main() {
println!("\n\nRust, say hello to seL4! :)\n");
unsafe { println!("{:?}", *BOOTINFO) };
unsafe { sel4_start::switch_to_scratch(); };
let mut total_untyped_memory : usize = 0;
println!("\nAvailable physical memory:");
for untyped in unsafe { (*BOOTINFO).untyped_descs() } {
let mut size: usize = 1 << untyped.sizeBits;
if untyped.isDevice != 1 {
total_untyped_memory += size;
println!("{:16x} to {:16x} {:8} KB", untyped.paddr, untyped.paddr + size, size / 1024);
}
}
println!("Total memory: {:10} KB", total_untyped_memory / 1024);
println!("\n********** Bootstraping an alloc from BOOTINFO\n");
let alloc = unsafe { bootstrap::bootstrap_allocators(&*BOOTINFO) };
println!("\n{:?}", alloc.cspace());
println!("\n{:?}", alloc.utspace());
println!("\n{:?}", alloc.vspace());
println!("\n********** Creating a frame allocator\n");
let mut framealloc = FrameAllocator::new();
let untyped1_size_bits = unsafe { (&*BOOTINFO).untyped_descs()[1].sizeBits };
let numpages = (1 << untyped1_size_bits) / 4096;
println!("\n********** Allocating slots in cspace for {} frames in second untyped region\n", numpages);
let window_token = alloc.cspace().allocate_slots(numpages, &alloc).unwrap();
println!("{:?}", alloc.cspace());
let window = *window_token;
println!("{:?}", window);
println!("\n********** Giving frame allocator the second untyped\n");
framealloc.add_memory(unsafe { (&*BOOTINFO).untyped.start + 1 },
window,
alloc.cspace().slots_info(&window_token).unwrap(),
untyped1_size_bits);
println!("\n********** Creating a reservation\n");
let rsvp = alloc.vspace()
.reserve_at_vaddr(0xF70000000000, 0x1000, &alloc)
.unwrap();
println!("Reservation {:x} to {:x}", rsvp.start_vaddr(), rsvp.end_vaddr());
println!("{:?}", alloc.vspace());
println!("\n********** Allocating a page from frame allocator\n");
let page = framealloc.get_frame().unwrap();
println!("\n********** Mapping the page read/write\n");
alloc.vspace()
.map_at_vaddr(&[page.cptr()],
rsvp.start_vaddr(),
12,
&rsvp,
seL4_CapRights::new(0, 1, 1), // grant, read, write
seL4_X86_VMAttributes::WriteBack,
&alloc);
println!("{:?}", alloc.vspace());
println!("\n********** Changing protection to read-only\n");
alloc.vspace()
.change_protection(rsvp.start_vaddr(),
rsvp.end_vaddr() - rsvp.start_vaddr(),
seL4_CapRights::new(0,1,0),
seL4_X86_VMAttributes::WriteBack,
&alloc);
println!("{:?}", alloc.vspace());
println!("\n*********** Reading from {:x}\n", rsvp.start_vaddr());
let touch_me = unsafe { core::slice::from_raw_parts_mut(rsvp.start_vaddr() as *mut u64, 1) };
println!("Value at {:x}: {}", unsafe { &touch_me[0] as *const u64 as usize }, touch_me[0]);
println!("\n*********** Unmapping page\n");
alloc.vspace()
.unmap(rsvp.start_vaddr(), rsvp.end_vaddr()-rsvp.start_vaddr(), None);
println!("{:?}", alloc.vspace());
println!("\n********** Unreserving space\n");
alloc.vspace().unreserve(rsvp, &alloc);
println!("{:?}", alloc.vspace());
println!("\n********** Returning page to page allocator\n");
unsafe { framealloc.return_frame(page) };
println!("\n********** Allocating slots for bitmap allocator\n");
let window_token2 = alloc.cspace().allocate_slots(10, &alloc).unwrap();
println!("{:?}", alloc.cspace());
println!("\n********** Creating bitmap allocator\n");
let bitmapalloc = cspace::BitmapAllocator::new(*window_token2, *alloc.cspace().slots_info(&window_token).unwrap()).unwrap();
println!("{:?}", bitmapalloc);
println!("\n********** Allocating from bitmap\n");
let bmslot = bitmapalloc.allocate_slot(&alloc).unwrap();
println!("{:?}", bmslot);
println!("{:?}", bitmapalloc);
println!("\n********** Returning slot to bitmap\n");
bitmapalloc.free_slot(bmslot, &alloc);
println!("{:?}", bitmapalloc);
println!("\n********** Touching bottom of stack (should page fault)\n");
let touch_me2 = unsafe { core::slice::from_raw_parts_mut( ::core::mem::transmute::<_, usize>(&_stack_bottom) as *mut u64, 80*25) };
println!("Writing to {:x}", unsafe { &touch_me2[0] as *const u64 as usize });
touch_me2[0] = 1234;
}
Edited by Jimmy Brush