/** * A1 memory allocator. */ module hulk.hurl.a1; import hulk.hurl; import hulk.hippo; import hulk.util; import hulk.pagetable; import hulk.memory; /** * The A1 memory allocator is a one-shot memory allocator for kernel memory * that is allocated but never freed. */ struct A1 { /** * Number of bytes allocated in the A1 region so far. */ private static __gshared size_t allocated; /** * Allocate memory. * * @param size * Size of memory to allocate. * * @return Address of allocated memory. This address will always be aligned * to a multiple of 16 bytes. */ public static void * allocate(size_t size) { /* Round size up to a multiple of 16. */ size = round_up_power_2(size, 16u); ulong address = Hurl.A1_BASE + allocated; ulong current_limit = round_up_power_2(address, PAGE_SIZE); allocated += size; ulong desired_limit = round_up_power_2(Hurl.A1_BASE + allocated, PAGE_SIZE); while (desired_limit > current_limit) { void * page = Hippo.allocate_page(); Hurl.map(current_limit, page, PT_WRITABLE); current_limit += PAGE_SIZE; } memset64(cast(void *)address, 0, size / 8); return cast(void *)address; } /** * Allocate memory to store an instance of a given type. * * @return Address of allocated memory. This address will always be aligned * to a multiple of 16 bytes. */ public static T * allocate(T)() { return cast(T *)allocate(T.sizeof); } }