1/*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2019, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7extern "C" {
8#include <compat/sys/malloc.h>
9}
10
11#include <stdio.h>
12#include <string.h>
13
14#include <util/BitUtils.h>
15
16#include <kernel/heap.h>
17#include <kernel/vm/vm.h>
18
19
20void*
21_kernel_malloc(size_t size, int flags)
22{
23	// According to the FreeBSD kernel malloc man page the allocator is expected
24	// to return power of two aligned addresses for allocations up to one page
25	// size. While it also states that this shouldn't be relied upon, at least
26	// bus_dmamem_alloc expects it and drivers may depend on it as well.
27	void *ptr
28		= memalign_etc(size >= PAGESIZE ? PAGESIZE : next_power_of_2(size), size,
29			(flags & M_NOWAIT) ? HEAP_DONT_WAIT_FOR_MEMORY : 0);
30	if (ptr == NULL)
31		return NULL;
32
33	if (flags & M_ZERO)
34		memset(ptr, 0, size);
35
36	return ptr;
37}
38
39
40void
41_kernel_free(void *ptr)
42{
43	free(ptr);
44}
45
46
47void *
48_kernel_contigmalloc(const char *file, int line, size_t size, int flags,
49	vm_paddr_t low, vm_paddr_t high, unsigned long alignment,
50	unsigned long boundary)
51{
52	const bool zero = (flags & M_ZERO) != 0, dontWait = (flags & M_NOWAIT) != 0;
53
54	size = ROUNDUP(size, B_PAGE_SIZE);
55
56	uint32 creationFlags = (zero ? 0 : CREATE_AREA_DONT_CLEAR)
57		| (dontWait ? CREATE_AREA_DONT_WAIT : 0);
58
59	char name[B_OS_NAME_LENGTH];
60	const char* baseName = strrchr(file, '/');
61	baseName = baseName != NULL ? baseName + 1 : file;
62	snprintf(name, sizeof(name), "contig:%s:%d", baseName, line);
63
64	virtual_address_restrictions virtualRestrictions = {};
65
66	physical_address_restrictions physicalRestrictions = {};
67	physicalRestrictions.low_address = low;
68	physicalRestrictions.high_address = high;
69	physicalRestrictions.alignment = alignment;
70	physicalRestrictions.boundary = boundary;
71
72	void* address;
73	area_id area = create_area_etc(B_SYSTEM_TEAM, name, size, B_CONTIGUOUS,
74		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, creationFlags, 0,
75		&virtualRestrictions, &physicalRestrictions, &address);
76	if (area < 0)
77		return NULL;
78
79	return address;
80}
81
82
83void
84_kernel_contigfree(void *addr, size_t size)
85{
86	if (addr == NULL)
87		return;
88
89	delete_area(area_for(addr));
90}
91
92
93vm_paddr_t
94pmap_kextract(vm_offset_t virtualAddress)
95{
96	physical_entry entry;
97	status_t status = get_memory_map((void *)virtualAddress, 1, &entry, 1);
98	if (status < B_OK) {
99		panic("fbsd compat: get_memory_map failed for %p, error %08" B_PRIx32
100			"\n", (void *)virtualAddress, status);
101	}
102
103	return (vm_paddr_t)entry.address;
104}
105