Allow allocating arbitrarily aligned physical memory regions
This will be needed for USB (XHCI controller driver).
This commit is contained in:
parent
b2497d1ee0
commit
7313b01732
@ -198,6 +198,7 @@ task "run", desc: "Run HOS in QEMU" do
|
|||||||
sh %W[
|
sh %W[
|
||||||
qemu-system-x86_64
|
qemu-system-x86_64
|
||||||
-machine q35
|
-machine q35
|
||||||
|
-m 128M
|
||||||
-cpu max
|
-cpu max
|
||||||
-smp cpus=4
|
-smp cpus=4
|
||||||
-serial file:qemu/serial.out
|
-serial file:qemu/serial.out
|
||||||
|
@ -89,6 +89,12 @@ struct Hippo
|
|||||||
*/
|
*/
|
||||||
public static void free_region(T)(T start, ulong size)
|
public static void free_region(T)(T start, ulong size)
|
||||||
{
|
{
|
||||||
|
if (size == PAGE_SIZE)
|
||||||
|
{
|
||||||
|
free_page(start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (regions is null)
|
if (regions is null)
|
||||||
{
|
{
|
||||||
/* The free regions list is empty. Append this new region. */
|
/* The free regions list is empty. Append this new region. */
|
||||||
@ -124,6 +130,72 @@ struct Hippo
|
|||||||
m_n_free_pages += size >> 12;
|
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.
|
* Get the number of free pages.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user