1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE 3 #include "main.h" 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <pthread.h> 8 #include <malloc.h> 9 #include <assert.h> 10 #include <errno.h> 11 #include <limits.h> 12 13 #define SMP_CACHE_BYTES 64 14 #define cache_line_size() SMP_CACHE_BYTES 15 #define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES))) 16 #define unlikely(x) (__builtin_expect(!!(x), 0)) 17 #define likely(x) (__builtin_expect(!!(x), 1)) 18 #define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) 19 #define SIZE_MAX (~(size_t)0) 20 #define KMALLOC_MAX_SIZE SIZE_MAX 21 22 typedef pthread_spinlock_t spinlock_t; 23 24 typedef int gfp_t; 25 #define __GFP_ZERO 0x1 26 27 static void *kmalloc(unsigned size, gfp_t gfp) 28 { 29 void *p = memalign(64, size); 30 if (!p) 31 return p; 32 33 if (gfp & __GFP_ZERO) 34 memset(p, 0, size); 35 return p; 36 } 37 38 static inline void *kzalloc(unsigned size, gfp_t flags) 39 { 40 return kmalloc(size, flags | __GFP_ZERO); 41 } 42 43 static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) 44 { 45 if (size != 0 && n > SIZE_MAX / size) 46 return NULL; 47 return kmalloc(n * size, flags); 48 } 49 50 static inline void *kcalloc(size_t n, size_t size, gfp_t flags) 51 { 52 return kmalloc_array(n, size, flags | __GFP_ZERO); 53 } 54 55 static void kfree(void *p) 56 { 57 if (p) 58 free(p); 59 } 60 61 #define kvmalloc_array kmalloc_array 62 #define kvfree kfree 63 64 static void spin_lock_init(spinlock_t *lock) 65 { 66 int r = pthread_spin_init(lock, 0); 67 assert(!r); 68 } 69 70 static void spin_lock(spinlock_t *lock) 71 { 72 int ret = pthread_spin_lock(lock); 73 assert(!ret); 74 } 75 76 static void spin_unlock(spinlock_t *lock) 77 { 78 int ret = pthread_spin_unlock(lock); 79 assert(!ret); 80 } 81 82 static void spin_lock_bh(spinlock_t *lock) 83 { 84 spin_lock(lock); 85 } 86 87 static void spin_unlock_bh(spinlock_t *lock) 88 { 89 spin_unlock(lock); 90 } 91 92 static void spin_lock_irq(spinlock_t *lock) 93 { 94 spin_lock(lock); 95 } 96 97 static void spin_unlock_irq(spinlock_t *lock) 98 { 99 spin_unlock(lock); 100 } 101 102 static void spin_lock_irqsave(spinlock_t *lock, unsigned long f) 103 { 104 spin_lock(lock); 105 } 106 107 static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f) 108 { 109 spin_unlock(lock); 110 } 111 112 #include "../../../include/linux/ptr_ring.h" 113 114 static unsigned long long headcnt, tailcnt; 115 static struct ptr_ring array ____cacheline_aligned_in_smp; 116 117 /* implemented by ring */ 118 void alloc_ring(void) 119 { 120 int ret = ptr_ring_init(&array, ring_size, 0); 121 assert(!ret); 122 /* Hacky way to poke at ring internals. Useful for testing though. */ 123 if (param) 124 array.batch = param; 125 } 126 127 /* guest side */ 128 int add_inbuf(unsigned len, void *buf, void *datap) 129 { 130 int ret; 131 132 ret = __ptr_ring_produce(&array, buf); 133 if (ret >= 0) { 134 ret = 0; 135 headcnt++; 136 } 137 138 return ret; 139 } 140 141 /* 142 * ptr_ring API provides no way for producer to find out whether a given 143 * buffer was consumed. Our tests merely require that a successful get_buf 144 * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, 145 * fake it accordingly. 146 */ 147 void *get_buf(unsigned *lenp, void **bufp) 148 { 149 void *datap; 150 151 if (tailcnt == headcnt || __ptr_ring_full(&array)) 152 datap = NULL; 153 else { 154 datap = "Buffer\n"; 155 ++tailcnt; 156 } 157 158 return datap; 159 } 160 161 bool used_empty() 162 { 163 return (tailcnt == headcnt || __ptr_ring_full(&array)); 164 } 165 166 void disable_call() 167 { 168 assert(0); 169 } 170 171 bool enable_call() 172 { 173 assert(0); 174 } 175 176 void kick_available(void) 177 { 178 assert(0); 179 } 180 181 /* host side */ 182 void disable_kick() 183 { 184 assert(0); 185 } 186 187 bool enable_kick() 188 { 189 assert(0); 190 } 191 192 bool avail_empty() 193 { 194 return __ptr_ring_empty(&array); 195 } 196 197 bool use_buf(unsigned *lenp, void **bufp) 198 { 199 void *ptr; 200 201 ptr = __ptr_ring_consume(&array); 202 203 return ptr; 204 } 205 206 void call_used(void) 207 { 208 assert(0); 209 } 210