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