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*
_kernel_malloc(size_t size,int flags)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
_kernel_free(void * ptr)41 _kernel_free(void *ptr)
42 {
43 free(ptr);
44 }
45
46
47 void *
_kernel_contigmalloc(const char * file,int line,size_t size,int flags,vm_paddr_t low,vm_paddr_t high,unsigned long alignment,unsigned long boundary)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
_kernel_contigfree(void * addr,size_t size)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
pmap_kextract(vm_offset_t virtualAddress)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