@@ -10,7 +10,7 @@ pub mod sdf;
1010pub mod sel4;
1111pub mod util;
1212
13- use sel4:: { BootInfo , Config } ;
13+ use sel4:: Config ;
1414use std:: cmp:: min;
1515use std:: fmt;
1616
@@ -288,6 +288,7 @@ impl DisjointMemoryRegion {
288288pub struct KernelAllocation {
289289 pub untyped_cap_address : u64 , // FIXME: possibly this is an object, not an int?
290290 pub phys_addr : u64 ,
291+ pub size : u64 ,
291292}
292293
293294pub struct UntypedAllocator {
@@ -343,16 +344,12 @@ pub struct ObjectAllocator {
343344}
344345
345346impl ObjectAllocator {
346- pub fn new ( kernel_boot_info : & BootInfo ) -> ObjectAllocator {
347- let mut untyped = Vec :: new ( ) ;
348- for ut in kernel_boot_info. untyped_objects . iter ( ) {
349- if ut. is_device {
350- // Kernel allocator can only allocate out of normal memory
351- // device memory can't be used for kernel objects
352- continue ;
353- }
354- untyped. push ( UntypedAllocator :: new ( * ut, 0 , vec ! [ ] ) ) ;
355- }
347+ pub fn new ( untyped_pool : Vec < & UntypedObject > ) -> ObjectAllocator {
348+ let mut untyped: Vec < UntypedAllocator > = untyped_pool
349+ . into_iter ( )
350+ . map ( |ut| UntypedAllocator :: new ( * ut, 0 , vec ! [ ] ) )
351+ . collect ( ) ;
352+ untyped. sort_by ( |a, b| a. untyped_object . base ( ) . cmp ( & b. untyped_object . base ( ) ) ) ;
356353
357354 ObjectAllocator {
358355 allocation_idx : 0 ,
@@ -367,15 +364,17 @@ impl ObjectAllocator {
367364 pub fn alloc_n ( & mut self , size : u64 , count : u64 ) -> KernelAllocation {
368365 assert ! ( util:: is_power_of_two( size) ) ;
369366 assert ! ( count > 0 ) ;
367+ let mem_size = count * size;
370368 for ut in & mut self . untyped {
371369 // See if this fits
372370 let start = util:: round_up ( ut. base ( ) + ut. allocation_point , size) ;
373- if start + ( count * size ) <= ut. end ( ) {
374- ut. allocation_point = ( start - ut. base ( ) ) + ( count * size ) ;
371+ if start + mem_size <= ut. end ( ) {
372+ ut. allocation_point = ( start - ut. base ( ) ) + mem_size ;
375373 self . allocation_idx += 1 ;
376374 let allocation = KernelAllocation {
377375 untyped_cap_address : ut. untyped_object . cap ,
378376 phys_addr : start,
377+ size : mem_size,
379378 } ;
380379 ut. allocations . push ( allocation) ;
381380 return allocation;
@@ -384,4 +383,97 @@ impl ObjectAllocator {
384383
385384 panic ! ( "Can't alloc of size {}, count: {} - no space" , size, count) ;
386385 }
386+
387+ pub fn reserve ( & mut self , alloc : ( & UntypedObject , u64 ) ) {
388+ for ut in & mut self . untyped {
389+ if * alloc. 0 == ut. untyped_object {
390+ if ut. base ( ) <= alloc. 1 && alloc. 1 <= ut. end ( ) {
391+ ut. allocation_point = alloc. 1 - ut. base ( ) ;
392+ return ;
393+ } else {
394+ panic ! (
395+ "Allocation {:?} ({:x}) not in untyped region {:?}" ,
396+ alloc. 0 , alloc. 1 , ut. untyped_object
397+ ) ;
398+ }
399+ }
400+ }
401+
402+ panic ! (
403+ "Allocation {:?} ({:x}) not in any device untyped" ,
404+ alloc. 0 , alloc. 1
405+ ) ;
406+ }
407+
408+ pub fn find_fixed (
409+ & mut self ,
410+ phys_addr : u64 ,
411+ size : u64 ,
412+ ) -> Option < ( Option < Vec < KernelAllocation > > , KernelAllocation ) > {
413+ for ut in & mut self . untyped {
414+ /* Find the right untyped */
415+ if phys_addr >= ut. base ( ) && phys_addr < ut. end ( ) {
416+ if phys_addr < ut. base ( ) + ut. allocation_point {
417+ panic ! ( "Error: physical address {:x} is below watermark" , phys_addr) ;
418+ }
419+
420+ let space_left = ut. end ( ) - ( ut. base ( ) + ut. allocation_point ) ;
421+ if space_left < size {
422+ panic ! (
423+ "Error: allocation for physical address {:x}
424+ is too large ({:x}) for untyped" ,
425+ phys_addr, size
426+ ) ;
427+ }
428+
429+ let mut watermark = ut. base ( ) + ut. allocation_point ;
430+ let mut allocations: Option < Vec < KernelAllocation > > ;
431+
432+ if phys_addr != watermark {
433+ allocations = Some ( Vec :: new ( ) ) ;
434+ /* If the watermark isn't at the right place, we need to pad */
435+ let mut padding_required = phys_addr - watermark;
436+ // We are restricted in how much we can pad:
437+ // 1: Untyped objects must be power-of-two sized.
438+ // 2: Untyped objects must be aligned to their size.
439+ let mut padding_sizes = Vec :: new ( ) ;
440+ // We have two potential approaches for how we pad.
441+ // 1: Use largest objects possible respecting alignment
442+ // and size restrictions.
443+ // 2: Use a fixed size object multiple times. This will
444+ // create more objects, but as same sized objects can be
445+ // create in a batch, required fewer invocations.
446+ // For now we choose #1
447+ while padding_required > 0 {
448+ let wm_lsb = util:: lsb ( watermark) ;
449+ let sz_msb = util:: msb ( padding_required) ;
450+ let pad_object_size = 1 << min ( wm_lsb, sz_msb) ;
451+ padding_sizes. push ( pad_object_size) ;
452+
453+ allocations. as_mut ( ) . unwrap ( ) . push ( KernelAllocation {
454+ untyped_cap_address : ut. untyped_object . cap ,
455+ phys_addr : watermark,
456+ size : pad_object_size,
457+ } ) ;
458+
459+ watermark += pad_object_size;
460+ padding_required -= pad_object_size;
461+ }
462+ } else {
463+ allocations = None ;
464+ }
465+
466+ let obj = KernelAllocation {
467+ untyped_cap_address : ut. untyped_object . cap ,
468+ phys_addr : watermark,
469+ size,
470+ } ;
471+
472+ ut. allocation_point = ( watermark + size) - ut. base ( ) ;
473+ return Some ( ( allocations, obj) ) ;
474+ }
475+ }
476+
477+ None
478+ }
387479}
0 commit comments