mirror of
https://github.com/AsahiLinux/m1n1
synced 2025-03-07 00:37:14 +00:00
Merge branch 'pulls/286' into m2_dptx
This commit is contained in:
commit
e029c588c0
7 changed files with 444 additions and 19 deletions
1
Makefile
1
Makefile
|
@ -119,6 +119,7 @@ OBJECTS := \
|
|||
rtkit.o \
|
||||
sart.o \
|
||||
sep.o \
|
||||
sio.o \
|
||||
smp.o \
|
||||
start.o \
|
||||
startup.o \
|
||||
|
|
|
@ -399,12 +399,7 @@ int display_configure(const char *config)
|
|||
return -1;
|
||||
}
|
||||
|
||||
cur_boot_args.mem_size -= size;
|
||||
fb_pa = cur_boot_args.phys_base + cur_boot_args.mem_size;
|
||||
/* add guard page between RAM and framebuffer */
|
||||
// TODO: update mapping?
|
||||
cur_boot_args.mem_size -= SZ_16K;
|
||||
|
||||
fb_pa = top_of_memory_alloc(size);
|
||||
memset((void *)fb_pa, 0, size);
|
||||
|
||||
tmp_dva = iova_alloc(dcp->iovad_dcp, size);
|
||||
|
|
161
src/kboot.c
161
src/kboot.c
|
@ -14,6 +14,7 @@
|
|||
#include "pcie.h"
|
||||
#include "pmgr.h"
|
||||
#include "sep.h"
|
||||
#include "sio.h"
|
||||
#include "smp.h"
|
||||
#include "types.h"
|
||||
#include "usb.h"
|
||||
|
@ -1155,18 +1156,14 @@ static u64 dart_get_mapping(dart_dev_t *dart, const char *path, u64 paddr, size_
|
|||
return iova;
|
||||
}
|
||||
|
||||
static int dt_device_set_reserved_mem(int node, dart_dev_t *dart, const char *name,
|
||||
uint32_t phandle, u64 paddr, u64 size)
|
||||
static int dt_device_set_reserved_mem(int node, const char *name, uint32_t phandle, u64 iova,
|
||||
u64 size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
u64 iova = dart_get_mapping(dart, name, paddr, size);
|
||||
if (DART_IS_ERR(iova))
|
||||
bail("ADT: no mapping found for '%s' 0x%012lx iova:0x%08lx)\n", name, paddr, iova);
|
||||
|
||||
ret = fdt_appendprop_u32(dt, node, "iommu-addresses", phandle);
|
||||
if (ret != 0)
|
||||
bail("DT: could not append phandle '%s.compatible' property: %d\n", name, ret);
|
||||
bail("DT: could not append phandle to '%s.iommu-addresses' property: %d\n", name, ret);
|
||||
|
||||
ret = fdt_appendprop_u64(dt, node, "iommu-addresses", iova);
|
||||
if (ret != 0)
|
||||
|
@ -1179,6 +1176,16 @@ static int dt_device_set_reserved_mem(int node, dart_dev_t *dart, const char *na
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dt_device_set_reserved_mem_from_dart(int node, dart_dev_t *dart, const char *name,
|
||||
uint32_t phandle, u64 paddr, u64 size)
|
||||
{
|
||||
u64 iova = dart_get_mapping(dart, name, paddr, size);
|
||||
if (DART_IS_ERR(iova))
|
||||
bail("ADT: no mapping found for '%s' 0x%012lx iova:0x%08lx)\n", name, paddr, iova);
|
||||
|
||||
return dt_device_set_reserved_mem(node, name, phandle, iova, size);
|
||||
}
|
||||
|
||||
static int dt_get_or_add_reserved_mem(const char *node_name, const char *compat, u64 paddr,
|
||||
size_t size)
|
||||
{
|
||||
|
@ -1235,6 +1242,9 @@ static int dt_device_add_mem_region(const char *alias, uint32_t phandle, const c
|
|||
if (dev_node < 0)
|
||||
bail("DT: failed to update node for alias '%s'\n", alias);
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
ret = fdt_appendprop_string(dt, dev_node, "memory-region-names", name);
|
||||
if (ret != 0)
|
||||
bail("DT: failed to append to 'memory-region-names' property\n");
|
||||
|
@ -1350,20 +1360,20 @@ static int dt_add_reserved_regions(const char *dcp_alias, const char *disp_alias
|
|||
uint32_t mem_phandle = fdt_get_phandle(dt, mem_node);
|
||||
|
||||
if (maps[i].map_dcp && dart_dcp) {
|
||||
ret = dt_device_set_reserved_mem(mem_node, dart_dcp, node_name, dcp_phandle,
|
||||
region[i].paddr, region[i].size);
|
||||
ret = dt_device_set_reserved_mem_from_dart(mem_node, dart_dcp, node_name, dcp_phandle,
|
||||
region[i].paddr, region[i].size);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
}
|
||||
if (maps[i].map_disp && dart_disp) {
|
||||
ret = dt_device_set_reserved_mem(mem_node, dart_disp, node_name, disp_phandle,
|
||||
region[i].paddr, region[i].size);
|
||||
ret = dt_device_set_reserved_mem_from_dart(mem_node, dart_disp, node_name, disp_phandle,
|
||||
region[i].paddr, region[i].size);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
}
|
||||
if (maps[i].map_piodma && dart_piodma) {
|
||||
ret = dt_device_set_reserved_mem(mem_node, dart_piodma, node_name, piodma_phandle,
|
||||
region[i].paddr, region[i].size);
|
||||
ret = dt_device_set_reserved_mem_from_dart(
|
||||
mem_node, dart_piodma, node_name, piodma_phandle, region[i].paddr, region[i].size);
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
}
|
||||
|
@ -1490,6 +1500,61 @@ static int dt_vram_reserved_region(const char *dcp_alias, const char *disp_alias
|
|||
disp_reserved_regions_vram, ®ion, 1);
|
||||
}
|
||||
|
||||
static int dt_reserve_asc_firmware(const char *adt_path, const char *fdt_path)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
int fdt_node = fdt_path_offset(dt, fdt_path);
|
||||
if (fdt_node < 0) {
|
||||
printf("DT: '%s' not found\n", fdt_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int node = adt_path_offset(adt, adt_path);
|
||||
if (node < 0)
|
||||
bail("ADT: '%s' not found\n", adt_path);
|
||||
|
||||
uint32_t dev_phandle = fdt_get_phandle(dt, fdt_node);
|
||||
if (!dev_phandle) {
|
||||
ret = fdt_generate_phandle(dt, &dev_phandle);
|
||||
if (!ret)
|
||||
ret = fdt_setprop_u32(dt, fdt_node, "phandle", dev_phandle);
|
||||
if (ret != 0)
|
||||
bail("DT: couldn't set '%s.phandle' property: %d\n", fdt_path, ret);
|
||||
}
|
||||
|
||||
const uint64_t *segments;
|
||||
u32 segments_len;
|
||||
|
||||
segments = adt_getprop(adt, node, "segment-ranges", &segments_len);
|
||||
unsigned int num_maps = segments_len / 32;
|
||||
|
||||
for (unsigned i = 0; i < num_maps; i++) {
|
||||
u64 paddr = segments[0];
|
||||
u64 iova = segments[2];
|
||||
u32 size = segments[3];
|
||||
segments += 4;
|
||||
|
||||
char node_name[64];
|
||||
snprintf(node_name, sizeof(node_name), "asc-firmware@%lx", paddr);
|
||||
|
||||
int mem_node = dt_get_or_add_reserved_mem(node_name, "apple,asc-mem", paddr, size);
|
||||
if (mem_node < 0)
|
||||
return ret;
|
||||
uint32_t mem_phandle = fdt_get_phandle(dt, mem_node);
|
||||
|
||||
ret = dt_device_set_reserved_mem(mem_node, node_name, dev_phandle, iova, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dt_device_add_mem_region(fdt_path, mem_phandle, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct disp_mapping disp_reserved_regions_t8103[] = {
|
||||
{"region-id-50", "dcp_data", true, false, false},
|
||||
{"region-id-57", "region57", true, false, false},
|
||||
|
@ -1626,6 +1691,72 @@ static int dt_set_display(void)
|
|||
return dt_vram_reserved_region("dcp", "disp0");
|
||||
}
|
||||
|
||||
static int dt_set_sio_fwdata(void)
|
||||
{
|
||||
const char *path = "/soc/sio";
|
||||
|
||||
int node = fdt_path_offset(dt, path);
|
||||
if (node < 0) {
|
||||
printf("FDT: '%s' node not found\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = sio_setup_fwdata();
|
||||
if (ret < 0)
|
||||
bail("DT: failed to set up SIO firmware data: %d\n", ret);
|
||||
|
||||
int phandle = fdt_get_phandle(dt, node);
|
||||
uint32_t max_phandle;
|
||||
ret = fdt_find_max_phandle(dt, &max_phandle);
|
||||
if (ret)
|
||||
bail("DT: failed to get max phandle: %d\n", ret);
|
||||
|
||||
if (!phandle) {
|
||||
phandle = ++max_phandle;
|
||||
ret = fdt_setprop_u32(dt, node, "phandle", phandle);
|
||||
if (ret != 0)
|
||||
bail("DT: couldn't set '%s.phandle' property: %d\n", path, ret);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sio_num_fwdata; i++) {
|
||||
struct sio_mapping *mapping = &sio_fwdata[i];
|
||||
|
||||
char node_name[64];
|
||||
snprintf(node_name, sizeof(node_name), "sio-firmware-data@%lx", mapping->phys);
|
||||
|
||||
int mem_node =
|
||||
dt_get_or_add_reserved_mem(node_name, "apple,asc-mem", mapping->phys, mapping->size);
|
||||
if (mem_node < 0)
|
||||
return ret;
|
||||
uint32_t mem_phandle = fdt_get_phandle(dt, mem_node);
|
||||
|
||||
int ret =
|
||||
dt_device_set_reserved_mem(mem_node, node_name, phandle, mapping->iova, mapping->size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dt_device_add_mem_region(path, mem_phandle, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = fdt_path_offset(dt, path);
|
||||
if (node < 0)
|
||||
bail("DT: '%s' not found\n", path);
|
||||
|
||||
for (int i = 0; i < sio_num_fwparams; i++) {
|
||||
struct sio_fwparam *param = &sio_fwparams[i];
|
||||
|
||||
if (fdt_appendprop_u32(dt, node, "apple,sio-firmware-params", param->key))
|
||||
bail("DT: couldn't append to SIO parameters\n");
|
||||
|
||||
if (fdt_appendprop_u32(dt, node, "apple,sio-firmware-params", param->value))
|
||||
bail("DT: couldn't append to SIO parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dt_disable_missing_devs(const char *adt_prefix, const char *dt_prefix, int max_devs)
|
||||
{
|
||||
int ret = -1;
|
||||
|
@ -1934,6 +2065,10 @@ int kboot_prepare_dt(void *fdt)
|
|||
return -1;
|
||||
if (dt_disable_missing_devs("i2c", "i2c@", 8))
|
||||
return -1;
|
||||
if (dt_reserve_asc_firmware("/arm-io/sio", "/soc/sio"))
|
||||
return -1;
|
||||
if (dt_set_sio_fwdata())
|
||||
return -1;
|
||||
#ifndef RELEASE
|
||||
if (dt_transfer_virtios())
|
||||
return 1;
|
||||
|
|
249
src/sio.c
Normal file
249
src/sio.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#include "adt.h"
|
||||
#include "errno.h"
|
||||
#include "malloc.h"
|
||||
#include "sio.h"
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
// Reuse pages for different data sections, if space allows it
|
||||
#define MERGE_SIO_FWDATA
|
||||
|
||||
#define SIO_KEY(s) _SIO_KEY(#s)
|
||||
#define _SIO_KEY(s) (((s)[0] << 24) | ((s)[1] << 16) | ((s)[2] << 8) | (s)[3])
|
||||
|
||||
#define MAX_FWDATA 6
|
||||
#define MAX_FWPARAMS 16
|
||||
|
||||
int sio_num_fwdata;
|
||||
struct sio_mapping *sio_fwdata;
|
||||
int sio_num_fwparams;
|
||||
struct sio_fwparam *sio_fwparams;
|
||||
|
||||
static void *alloc_mapped_data(size_t size, u64 *iova)
|
||||
{
|
||||
if (sio_num_fwdata >= MAX_FWDATA)
|
||||
return NULL;
|
||||
|
||||
struct sio_mapping *mapping = &sio_fwdata[sio_num_fwdata];
|
||||
|
||||
#ifdef MERGE_SIO_FWDATA
|
||||
if (sio_num_fwdata && ALIGN_UP((mapping - 1)->size, SZ_16K) >= (mapping - 1)->size + size) {
|
||||
mapping--;
|
||||
*iova = mapping->iova + mapping->size;
|
||||
mapping->size = ALIGN_UP(mapping->size + size, SZ_4K);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!sio_num_fwdata++)
|
||||
mapping->iova = *iova = 0x30000;
|
||||
else
|
||||
mapping->iova = *iova = ALIGN_UP((mapping - 1)->iova + (mapping - 1)->size, SZ_16K);
|
||||
mapping->size = ALIGN_UP(size, SZ_4K);
|
||||
mapping->phys = top_of_memory_alloc(size);
|
||||
memset64((void *)mapping->phys, 0, ALIGN_UP(mapping->size, SZ_16K));
|
||||
|
||||
done:
|
||||
return (void *)((*iova - mapping->iova) + mapping->phys);
|
||||
}
|
||||
|
||||
static void mapping_fixup(void)
|
||||
{
|
||||
for (int i = 0; i < sio_num_fwdata; i++) {
|
||||
struct sio_mapping *mapping = &sio_fwdata[i];
|
||||
mapping->size = ALIGN_UP(mapping->size, SZ_16K);
|
||||
}
|
||||
}
|
||||
|
||||
static void *add_fwdata(size_t size, u32 param_id)
|
||||
{
|
||||
if (sio_num_fwparams + 1 >= MAX_FWPARAMS)
|
||||
return NULL;
|
||||
|
||||
u64 iova;
|
||||
void *p = alloc_mapped_data(size, &iova);
|
||||
|
||||
struct sio_fwparam *param = &sio_fwparams[sio_num_fwparams];
|
||||
param->key = param_id;
|
||||
param->value = iova >> 12;
|
||||
param++;
|
||||
param->key = param_id + 1;
|
||||
param->value = size;
|
||||
sio_num_fwparams += 2;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#define PARAM_UNK_000b 0x000b
|
||||
#define PARAM_PANIC_BUFFER 0x000f
|
||||
#define PARAM_MAP_RANGE 0x001a
|
||||
#define PARAM_DEVICE_TYPE 0x001c
|
||||
#define PARAM_TUNABLES 0x001e
|
||||
#define PARAM_DMASHIM_DATA 0x0022
|
||||
#define PARAM_UNK_030d 0x030d
|
||||
|
||||
struct copy_rule {
|
||||
const char *prop;
|
||||
int fw_param;
|
||||
bool keyed;
|
||||
int blobsize;
|
||||
u32 nkeys;
|
||||
const char *keys[9];
|
||||
};
|
||||
|
||||
#define SPACER "\xff\xff\xff\xff"
|
||||
|
||||
struct copy_rule copy_rules[] = {
|
||||
{
|
||||
.prop = "asio-ascwrap-tunables",
|
||||
.fw_param = PARAM_TUNABLES,
|
||||
},
|
||||
{
|
||||
.blobsize = 0x1b80,
|
||||
.fw_param = PARAM_UNK_000b,
|
||||
},
|
||||
{
|
||||
.blobsize = 0x1e000,
|
||||
.fw_param = PARAM_PANIC_BUFFER,
|
||||
},
|
||||
{
|
||||
// peformance endpoint? FIFO?
|
||||
.blobsize = 0x4000,
|
||||
.fw_param = PARAM_UNK_030d,
|
||||
},
|
||||
{
|
||||
.prop = "map-range",
|
||||
.fw_param = PARAM_MAP_RANGE,
|
||||
.blobsize = 16,
|
||||
.keyed = true,
|
||||
.keys = {SPACER, SPACER, SPACER, "MISC", NULL},
|
||||
},
|
||||
{
|
||||
.prop = "dmashim",
|
||||
.fw_param = PARAM_DMASHIM_DATA,
|
||||
.blobsize = 32,
|
||||
.keyed = true,
|
||||
.keys = {"SSPI", "SUAR", "SAUD", "ADMA", "AAUD", NULL},
|
||||
},
|
||||
{
|
||||
// it seems 'device_type' must go after 'dmashim'
|
||||
.prop = "device-type",
|
||||
.fw_param = PARAM_DEVICE_TYPE,
|
||||
.blobsize = 8,
|
||||
.keyed = true,
|
||||
.keys = {"dSPI", "dUAR", "dMCA", "dDPA", "dPDM", "dALE", "dAMC", "dAPD", NULL},
|
||||
},
|
||||
};
|
||||
|
||||
int find_key_index(const char *keylist[], u32 needle)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; keylist[i]; i++) {
|
||||
const char *s = keylist[i];
|
||||
u32 key = ((u32)s[0]) << 24 | ((u32)s[1]) << 16 | ((u32)s[2]) << 8 | s[3];
|
||||
if (key == needle)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int sio_setup_fwdata(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
if (sio_fwdata)
|
||||
return 0;
|
||||
|
||||
sio_fwdata = calloc(MAX_FWDATA, sizeof(*sio_fwdata));
|
||||
if (!sio_fwdata)
|
||||
return -ENOMEM;
|
||||
sio_num_fwdata = 0;
|
||||
|
||||
sio_fwparams = calloc(MAX_FWPARAMS, sizeof(*sio_fwdata));
|
||||
if (!sio_fwparams) {
|
||||
free(sio_fwdata);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sio_num_fwparams = 0;
|
||||
|
||||
int node = adt_path_offset(adt, "/arm-io/sio");
|
||||
if (node < 0) {
|
||||
printf("%s: missing node\n", __func__);
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)ARRAY_SIZE(copy_rules); i++) {
|
||||
struct copy_rule *rule = ©_rules[i];
|
||||
u32 len;
|
||||
|
||||
if (!rule->prop) {
|
||||
if (!add_fwdata(rule->blobsize, rule->fw_param))
|
||||
goto err_nomem;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const u8 *adt_blob = adt_getprop(adt, node, rule->prop, &len);
|
||||
if (!adt_blob) {
|
||||
printf("%s: missing ADT property '%s'\n", __func__, rule->prop);
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
if (!rule->keyed) {
|
||||
u8 *sio_blob = add_fwdata(len, rule->fw_param);
|
||||
if (!sio_blob)
|
||||
goto err_nomem;
|
||||
memcpy8(sio_blob, (void *)adt_blob, len);
|
||||
continue;
|
||||
}
|
||||
|
||||
int nkeys = find_key_index(rule->keys, 0);
|
||||
u8 *sio_blob = add_fwdata(nkeys * rule->blobsize, rule->fw_param);
|
||||
if (len % (rule->blobsize + 4) != 0) {
|
||||
printf("%s: bad length %d of ADT property '%s', expected multiple of %d + 4\n",
|
||||
__func__, len, rule->prop, rule->blobsize);
|
||||
}
|
||||
|
||||
for (u32 off = 0; off + rule->blobsize <= len; off += (rule->blobsize + 4)) {
|
||||
const u8 *p = &adt_blob[off];
|
||||
u32 key = *((u32 *)p);
|
||||
int key_idx = find_key_index(rule->keys, key);
|
||||
|
||||
if (key_idx >= nkeys) {
|
||||
printf("%s: unknown key %x found in ADT property '%s'\n", __func__, key,
|
||||
rule->prop);
|
||||
goto err_inval;
|
||||
}
|
||||
|
||||
memcpy8(sio_blob + (key_idx * rule->blobsize), (void *)(p + 4), rule->blobsize);
|
||||
}
|
||||
}
|
||||
|
||||
mapping_fixup();
|
||||
|
||||
return 0;
|
||||
|
||||
err_inval:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
err_nomem:
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
|
||||
err:
|
||||
for (int i = 0; i < MAX_FWDATA; i++) {
|
||||
if (!sio_fwdata[i].size)
|
||||
break;
|
||||
// No way to give back memory with the top of memory
|
||||
// allocator.
|
||||
// free((void *)sio_fwdata[i].phys);
|
||||
}
|
||||
free(sio_fwdata);
|
||||
free(sio_fwparams);
|
||||
sio_fwdata = NULL;
|
||||
sio_fwparams = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
24
src/sio.h
Normal file
24
src/sio.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef SIO_H
|
||||
#define SIO_H
|
||||
|
||||
struct sio_mapping {
|
||||
u64 phys;
|
||||
u64 iova;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct sio_fwparam {
|
||||
u32 key;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
extern int sio_num_fwdata;
|
||||
extern struct sio_mapping *sio_fwdata;
|
||||
extern int sio_num_fwparams;
|
||||
extern struct sio_fwparam *sio_fwparams;
|
||||
|
||||
int sio_setup_fwdata(void);
|
||||
|
||||
#endif
|
20
src/utils.c
20
src/utils.c
|
@ -180,3 +180,23 @@ bool is_heap(void *addr)
|
|||
|
||||
return p > top_of_kernel_data && p < top_of_ram;
|
||||
}
|
||||
|
||||
// TODO: update mapping?
|
||||
u64 top_of_memory_alloc(size_t size)
|
||||
{
|
||||
static bool guard_page_inserted = false;
|
||||
cur_boot_args.mem_size -= ALIGN_UP(size, SZ_16K);
|
||||
u64 ret = cur_boot_args.phys_base + cur_boot_args.mem_size;
|
||||
|
||||
if (!guard_page_inserted) {
|
||||
cur_boot_args.mem_size -= SZ_16K;
|
||||
guard_page_inserted = true;
|
||||
} else {
|
||||
// If the guard page was already there, move it down and allocate
|
||||
// above it -- this is accomplished by simply shifting the allocated
|
||||
// region by one page up.
|
||||
ret += SZ_16K;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -440,5 +440,6 @@ extern struct vector_args next_stage;
|
|||
void deep_wfi(void);
|
||||
|
||||
bool is_heap(void *addr);
|
||||
u64 top_of_memory_alloc(size_t size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue