Skip to content

Add x64 support and various fixes

Jimmy Brush requested to merge peachesrebar88/sel4-alloc:x64support into wip

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

Merge request reports