1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <platsupport/io.h> 16#include <stddef.h> 17#include <stdint.h> 18#include <utils/util.h> 19#include <sel4/sel4.h> 20#include <utils/attribute.h> 21 22/* Add memory to the dma allocator. This function must be called before using any 23 * of the functions below. Pass in the pool to allocate from, the size of this 24 * pool in bytes, the page size of the associated mappings and a function to 25 * reverse mappings. Callers may pass 0 as the page_size to force the allocator 26 * itself to determine it automatically. Returns 0 on success. 27 * 28 * This function is intended to be called by the CAmkES backend and not by a user. 29 */ 30int camkes_dma_init(void *dma_pool, size_t dma_pool_sz, size_t page_size) 31NONNULL(1) WARN_UNUSED_RESULT; 32 33/** 34 * Allocate memory to be used for DMA. 35 * 36 * @param size Size in bytes to allocate 37 * @param align Alignment constraint in bytes (0 == none) 38 * 39 * @return Virtual address of allocation or NULL on failure 40 */ 41void *camkes_dma_alloc(size_t size, int align, bool cached) ALLOC_SIZE(1) ALLOC_ALIGN(2) 42MALLOC WARN_UNUSED_RESULT; 43 44/** 45 * Free previously allocated DMA memory. 46 * 47 * @param ptr Virtual address that was allocated (passing NULL is treated as a 48 * no-op) 49 * @param size Size that was given in the allocation request 50 */ 51void camkes_dma_free(void *ptr, size_t size); 52 53/* Return the physical address of a pointer into a DMA buffer. Returns NULL if 54 * you pass a pointer into memory that is not part of a DMA buffer. Behaviour 55 * is undefined if you pass a pointer into memory that is part of a DMA buffer, 56 * but not one currently allocated to you by camkes_dma_alloc_page. 57 */ 58uintptr_t camkes_dma_get_paddr(void *ptr); 59 60/* Return the cap to a frame backing part of the DMA buffer. Returns seL4_CapNull 61 * if passed a pointer into memory that is not part of a DMA buffer. */ 62seL4_CPtr camkes_dma_get_cptr(void *ptr); 63 64/* Initialise a DMA manager for use with libplatsupport. This manager will be 65 * backed by the (generated) CAmkES DMA pool. Returns 0 on success. 66 * 67 * If you only need simple DMA allocation, prefer the alloc_page and free_page 68 * functions above, but if you need a more interoperable DMA interface then use 69 * this function. Note that you can mix calls to alloc_page, free_page and the 70 * manager initialised by this function with no adverse effects. 71 */ 72int camkes_dma_manager(ps_dma_man_t *man) NONNULL_ALL WARN_UNUSED_RESULT; 73 74/* Debug functionality for profiling DMA heap usage. This information is 75 * returned from a call to `camkes_dma_stats`. Note that this functionality is 76 * only available when NDEBUG is not defined. 77 */ 78typedef struct { 79 80 /* The total size of the heap in bytes. */ 81 size_t heap_size; 82 83 /* The low water mark of available bytes the heap has ever reached. */ 84 size_t minimum_heap_size; 85 86 /* The current live (allocated) heap space in bytes. Note that the 87 * currently available bytes in the heap can be calculated as 88 * `heap_size - current_outstanding` 89 */ 90 size_t current_outstanding; 91 92 /* The number of defragmentation attempts that have been performed. Note 93 * that no information is provided as to which of these defragmentation 94 * operations did useful work. 95 */ 96 uint64_t defragmentations; 97 98 /* Number of coalescing operations that were performed during 99 * defragmentations. 100 */ 101 uint64_t coalesces; 102 103 /* Total number of allocation requests (succeeded or failed) that have been 104 * performed. 105 */ 106 uint64_t total_allocations; 107 108 /* Number of allocations that initially failed, but then succeeded on 109 * retrying after defragmenting the heap. 110 */ 111 uint64_t succeeded_allocations_on_defrag; 112 113 /* Number of failed allocations. This is separated into those that failed 114 * because the heap was exhausted and for some other reason. The total 115 * failures is calculable by summing them. The succeeded allocations are 116 * available by subtracting their sum from `total_allocations`. 117 */ 118 uint64_t failed_allocations_out_of_memory; 119 uint64_t failed_allocations_other; 120 121 /* Average allocation request (succeeded or failed) in bytes. */ 122 size_t average_allocation; 123 124 /* Minimum allocation request (succeeded or failed) in bytes. */ 125 size_t minimum_allocation; 126 127 /* Maximum allocation request (succeeded or failed) in bytes. */ 128 size_t maximum_allocation; 129 130 /* Maximum alignment constraint (succeeded or failed) in bytes. */ 131 int maximum_alignment; 132 133 /* Minimum alignment constraint (succeeded or failed) in bytes. */ 134 int minimum_alignment; 135 136} camkes_dma_stats_t; 137 138/* Retrieve the above statistics for the current DMA heap. This function is 139 * only provided when NDEBUG is not defined. The caller should not modify or 140 * free the returned value that may be a static resource. 141 */ 142const camkes_dma_stats_t *camkes_dma_stats(void) RETURNS_NONNULL; 143 144/* Legacy functionality. Use the general allocation and free functions above in 145 * preference to these. 146 */ 147void *camkes_dma_alloc_page(void) 148DEPRECATED("use camkes_dma_alloc(PAGE_SIZE_4K, PAGE_SIZE_4K) instead"); 149void camkes_dma_free_page(void *ptr) 150DEPRECATED("use camkes_dma_free(ptr, PAGE_SIZE_4K) instead"); 151 152/* 153 * This struct describes the information about a frame in a component's DMA pool. 154 */ 155struct dma_frame { 156 seL4_CPtr cap; 157 size_t size; 158 uintptr_t vaddr; 159 bool cached; 160}; 161typedef struct dma_frame dma_frame_t; 162