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#include <autoconf.h> 14#include <rumprun/gen_config.h> 15#include <bmk-core/types.h> 16#include <sel4/kernel.h> 17 18#include <bmk-core/pgalloc.h> 19#include <bmk-core/printf.h> 20#include <bmk-core/memalloc.h> 21 22#include <bmk-pcpu/pcpu.h> 23 24#include <platsupport/io.h> 25#include <sel4/helpers.h> 26#include <vspace/vspace.h> 27#include "pci_user.h" 28#include <assert.h> 29 30typedef struct a_list a_list_t; 31 32struct a_list { 33 uintptr_t vaddr; 34 uintptr_t paddr; 35 uintptr_t size; 36}; 37#define LIST_LENGTH 30 38a_list_t list[LIST_LENGTH]; 39 40int rumpcomp_pci_dmalloc(size_t size, size_t align, 41 unsigned long *pap, unsigned long *vap) 42{ 43 /* alloc and pin using platsupport implementation */ 44 void *mem = ps_dma_alloc(&env.io_ops.dma_manager, size, align, 1, PS_MEM_NORMAL); 45 if (mem == NULL) { 46 return 1; 47 } 48 uintptr_t pmem = ps_dma_pin(&env.io_ops.dma_manager, mem, size); 49 50 if (pmem == 0) { 51 /* return error if cannot find paddr */ 52 return 1; 53 } 54 /* Add entry to our inefficient entry array */ 55 int i = 0; 56 for (i = 0; i < LIST_LENGTH; i++) { 57 if (list[i].vaddr == 0) { 58 break; 59 } 60 } 61 if (i == LIST_LENGTH) { 62 ZF_LOGD("\terror: no_free entries\n"); 63 return 1; 64 } 65 list[i].vaddr = (uintptr_t) mem; 66 list[i].paddr = (uintptr_t) pmem; 67 list[i].size = size; 68 /* Return addresses */ 69 *pap = (unsigned long)pmem; 70 *vap = (unsigned long)mem; 71 72 return 0; 73} 74 75/* We already mapped in with call above ds_vacookie is *vap return from 76 rumpcomp_pci_dmalloc. */ 77int rumpcomp_pci_dmamem_map(struct rumpcomp_pci_dmaseg *dss, size_t nseg, 78 size_t totlen, void **vap) 79{ 80 *vap = (void *)dss[0].ds_vacookie; 81 return 0; 82} 83 84void rumpcomp_pci_dmafree(unsigned long mem, size_t size) 85{ 86 /* Unpin and free from our platsupport impl */ 87 ps_dma_unpin(&env.io_ops.dma_manager, (void *)mem, size); 88 89 ps_dma_free(&env.io_ops.dma_manager, (void *)mem, size); 90 91 /* Remove from our list */ 92 int i; 93 for (i = 0; i < LIST_LENGTH; i++) { 94 if (list[i].vaddr == mem) { 95 break; 96 } 97 } 98 if (i == LIST_LENGTH) { 99 bmk_printf("\terror: cannot find entry\n"); 100 } 101 list[i].vaddr = (uintptr_t) 0; 102 list[i].paddr = (uintptr_t) 0; 103 list[i].size = 0; 104} 105 106unsigned long rumpcomp_pci_virt_to_mach(void *virt) 107{ 108 /* Try and find if its from something we mapped in previously. */ 109 uintptr_t vin = (uintptr_t) virt; 110 for (int i = 0; i < LIST_LENGTH; i++) { 111 if (vin >= list[i].vaddr) { 112 if (vin < (list[i].vaddr + list[i].size)) { 113 return vin - list[i].vaddr + list[i].paddr; 114 } 115 } 116 } 117 118 /* Couldn't find above, try and find in the system allocators */ 119 /* This likely means that the upper levels have an mbuf that was not allocated through rumpcomp_pci_dmalloc */ 120 /* Apparently this behavior is fine. */ 121 uintptr_t paddr = (uintptr_t) vka_utspace_paddr(&env.vka, vspace_get_cookie(&env.vspace, virt), 122 env.rump_mapping_page_type, env.rump_mapping_page_size_bits); 123 return paddr + (vin & MASK((unsigned int) env.rump_mapping_page_size_bits)); 124} 125