xref: /haiku/src/libs/compat/freebsd_network/malloc.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
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 
7 extern "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 
20 void*
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 
40 void
41 _kernel_free(void *ptr)
42 {
43 	free(ptr);
44 }
45 
46 
47 void *
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 
83 void
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 
93 vm_paddr_t
94 pmap_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