diff --git a/Rsconscript b/Rsconscript index 86e2cc8..3c48ef5 100644 --- a/Rsconscript +++ b/Rsconscript @@ -198,6 +198,7 @@ task "run", desc: "Run HOS in QEMU" do sh %W[ qemu-system-x86_64 -machine q35 + -m 128M -cpu max -smp cpus=4 -serial file:qemu/serial.out diff --git a/src/hulk/hippo.d b/src/hulk/hippo.d index c21862d..877b7a9 100644 --- a/src/hulk/hippo.d +++ b/src/hulk/hippo.d @@ -89,6 +89,12 @@ struct Hippo */ public static void free_region(T)(T start, ulong size) { + if (size == PAGE_SIZE) + { + free_page(start); + return; + } + if (regions is null) { /* The free regions list is empty. Append this new region. */ @@ -124,6 +130,72 @@ struct Hippo m_n_free_pages += size >> 12; } + /** + * Allocate a region with the given size and alignment. + * + * @param size Region size. + * @param alignment Region alignment. + */ + public static void * allocate_aligned_region(ulong size, ulong alignment) + { + Region ** regionp = ®ions; + for (;;) + { + Region * region = *regionp; + if (region is null) + { + break; + } + + /* The size of the region must be large enough */ + if (region.size >= size) + { + /* The alignment contstraint must be satisfied. */ + if ((cast(ulong)region & (alignment - 1)) == 0) + { + /* The region start address happens to already be aligned. */ + if (region.size > size) + { + /* Region found is larger that needed. */ + Region * new_region = cast(Region *)(cast(ulong)region + size); + new_region.size = region.size - size; + new_region.next = region.next; + *regionp = new_region; + return region; + } + else + { + /* Region happens to be the size requested. */ + *regionp = region.next; + return region; + } + } + else + { + /* This region is large enough but not aligned. See if an + * aligned subregion can be found at the end. */ + ulong start = (cast(ulong)region + region.size - size) & ~(alignment - 1); + if (start > cast(ulong)region) + { + /* The aligned subregion does fit in this region. */ + region.size = (start - cast(ulong)region); + ulong region_end = cast(ulong)region + region.size; + if (region_end > (start + size)) + { + /* There is another region following the aligned + * subregion that we must reclaim. */ + free_region(start + size, region_end - (start + size)); + } + return cast(void *)start; + } + } + } + + regionp = ®ion.next; + } + return null; + } + /** * Get the number of free pages. *