14Srgrimes/*
24Srgrimes * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
34Srgrimes * Copyright 2019, Haiku, Inc. All rights reserved.
44Srgrimes * Distributed under the terms of the MIT License.
54Srgrimes */
64Srgrimes
74Srgrimesextern "C" {
84Srgrimes#include <compat/sys/malloc.h>
94Srgrimes}
104Srgrimes
114Srgrimes#include <stdio.h>
124Srgrimes#include <string.h>
134Srgrimes
144Srgrimes#include <util/BitUtils.h>
154Srgrimes
164Srgrimes#include <kernel/heap.h>
174Srgrimes#include <kernel/vm/vm.h>
184Srgrimes
194Srgrimes
204Srgrimesvoid*
214Srgrimes_kernel_malloc(size_t size, int flags)
224Srgrimes{
234Srgrimes	// According to the FreeBSD kernel malloc man page the allocator is expected
244Srgrimes	// to return power of two aligned addresses for allocations up to one page
254Srgrimes	// size. While it also states that this shouldn't be relied upon, at least
264Srgrimes	// bus_dmamem_alloc expects it and drivers may depend on it as well.
274Srgrimes	void *ptr
284Srgrimes		= memalign_etc(size >= PAGESIZE ? PAGESIZE : next_power_of_2(size), size,
294Srgrimes			(flags & M_NOWAIT) ? HEAP_DONT_WAIT_FOR_MEMORY : 0);
304Srgrimes	if (ptr == NULL)
314Srgrimes		return NULL;
324Srgrimes
334Srgrimes	if (flags & M_ZERO)
344Srgrimes		memset(ptr, 0, size);
354Srgrimes
36619Srgrimes	return ptr;
3710268Sbde}
384Srgrimes
394Srgrimes
403185Ssosvoid
413185Ssos_kernel_free(void *ptr)
423185Ssos{
433185Ssos	free(ptr);
443185Ssos}
452913Sache
462913Sache
474Srgrimesvoid *
484Srgrimes_kernel_contigmalloc(const char *file, int line, size_t size, int flags,
494Srgrimes	vm_paddr_t low, vm_paddr_t high, unsigned long alignment,
502056Swollman	unsigned long boundary)
512056Swollman{
522056Swollman	const bool zero = (flags & M_ZERO) != 0, dontWait = (flags & M_NOWAIT) != 0;
532056Swollman
544180Sbde	size = ROUNDUP(size, B_PAGE_SIZE);
552056Swollman
562056Swollman	uint32 creationFlags = (zero ? 0 : CREATE_AREA_DONT_CLEAR)
572056Swollman		| (dontWait ? CREATE_AREA_DONT_WAIT : 0);
587090Sbde
592056Swollman	char name[B_OS_NAME_LENGTH];
602056Swollman	const char* baseName = strrchr(file, '/');
614Srgrimes	baseName = baseName != NULL ? baseName + 1 : file;
622873Sbde	snprintf(name, sizeof(name), "contig:%s:%d", baseName, line);
632873Sbde
642873Sbde	virtual_address_restrictions virtualRestrictions = {};
652873Sbde
662873Sbde	physical_address_restrictions physicalRestrictions = {};
672913Sache	physicalRestrictions.low_address = low;
682873Sbde	physicalRestrictions.high_address = high;
694Srgrimes	physicalRestrictions.alignment = alignment;
704Srgrimes	physicalRestrictions.boundary = boundary;
714Srgrimes
724Srgrimes	void* address;
731390Ssos	area_id area = create_area_etc(B_SYSTEM_TEAM, name, size, B_CONTIGUOUS,
744Srgrimes		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, creationFlags, 0,
754180Sbde		&virtualRestrictions, &physicalRestrictions, &address);
764180Sbde	if (area < 0)
774180Sbde		return NULL;
784180Sbde
794180Sbde	return address;
804180Sbde}
814180Sbde
824180Sbde
834180Sbdevoid
844180Sbde_kernel_contigfree(void *addr, size_t size)
854180Sbde{
864180Sbde	if (addr == NULL)
874180Sbde		return;
884180Sbde
894180Sbde	delete_area(area_for(addr));
904180Sbde}
914180Sbde
924180Sbde
934180Sbdevm_paddr_t
943366Sachepmap_kextract(vm_offset_t virtualAddress)
958448Sbde{
962017Swollman	physical_entry entry;
974180Sbde	status_t status = get_memory_map((void *)virtualAddress, 1, &entry, 1);
982017Swollman	if (status < B_OK) {
995291Sbde		panic("fbsd compat: get_memory_map failed for %p, error %08" B_PRIx32
1004180Sbde			"\n", (void *)virtualAddress, status);
1014180Sbde	}
1024180Sbde
1031390Ssos	return (vm_paddr_t)entry.address;
1044180Sbde}
1055291Sbde