162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#define _GNU_SOURCE 362306a36Sopenharmony_ci#include "main.h" 462306a36Sopenharmony_ci#include <stdlib.h> 562306a36Sopenharmony_ci#include <stdio.h> 662306a36Sopenharmony_ci#include <string.h> 762306a36Sopenharmony_ci#include <pthread.h> 862306a36Sopenharmony_ci#include <malloc.h> 962306a36Sopenharmony_ci#include <assert.h> 1062306a36Sopenharmony_ci#include <errno.h> 1162306a36Sopenharmony_ci#include <limits.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define SMP_CACHE_BYTES 64 1462306a36Sopenharmony_ci#define cache_line_size() SMP_CACHE_BYTES 1562306a36Sopenharmony_ci#define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES))) 1662306a36Sopenharmony_ci#define unlikely(x) (__builtin_expect(!!(x), 0)) 1762306a36Sopenharmony_ci#define likely(x) (__builtin_expect(!!(x), 1)) 1862306a36Sopenharmony_ci#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) 1962306a36Sopenharmony_ci#define SIZE_MAX (~(size_t)0) 2062306a36Sopenharmony_ci#define KMALLOC_MAX_SIZE SIZE_MAX 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_citypedef pthread_spinlock_t spinlock_t; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_citypedef int gfp_t; 2562306a36Sopenharmony_ci#define __GFP_ZERO 0x1 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void *kmalloc(unsigned size, gfp_t gfp) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci void *p = memalign(64, size); 3062306a36Sopenharmony_ci if (!p) 3162306a36Sopenharmony_ci return p; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (gfp & __GFP_ZERO) 3462306a36Sopenharmony_ci memset(p, 0, size); 3562306a36Sopenharmony_ci return p; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic inline void *kzalloc(unsigned size, gfp_t flags) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci return kmalloc(size, flags | __GFP_ZERO); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci if (size != 0 && n > SIZE_MAX / size) 4662306a36Sopenharmony_ci return NULL; 4762306a36Sopenharmony_ci return kmalloc(n * size, flags); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline void *kcalloc(size_t n, size_t size, gfp_t flags) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return kmalloc_array(n, size, flags | __GFP_ZERO); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic void kfree(void *p) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci if (p) 5862306a36Sopenharmony_ci free(p); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define kvmalloc_array kmalloc_array 6262306a36Sopenharmony_ci#define kvfree kfree 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic void spin_lock_init(spinlock_t *lock) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int r = pthread_spin_init(lock, 0); 6762306a36Sopenharmony_ci assert(!r); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic void spin_lock(spinlock_t *lock) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci int ret = pthread_spin_lock(lock); 7362306a36Sopenharmony_ci assert(!ret); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic void spin_unlock(spinlock_t *lock) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci int ret = pthread_spin_unlock(lock); 7962306a36Sopenharmony_ci assert(!ret); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic void spin_lock_bh(spinlock_t *lock) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci spin_lock(lock); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void spin_unlock_bh(spinlock_t *lock) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci spin_unlock(lock); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void spin_lock_irq(spinlock_t *lock) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci spin_lock(lock); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void spin_unlock_irq(spinlock_t *lock) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci spin_unlock(lock); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic void spin_lock_irqsave(spinlock_t *lock, unsigned long f) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci spin_lock(lock); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci spin_unlock(lock); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#include "../../../include/linux/ptr_ring.h" 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic unsigned long long headcnt, tailcnt; 11562306a36Sopenharmony_cistatic struct ptr_ring array ____cacheline_aligned_in_smp; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* implemented by ring */ 11862306a36Sopenharmony_civoid alloc_ring(void) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci int ret = ptr_ring_init(&array, ring_size, 0); 12162306a36Sopenharmony_ci assert(!ret); 12262306a36Sopenharmony_ci /* Hacky way to poke at ring internals. Useful for testing though. */ 12362306a36Sopenharmony_ci if (param) 12462306a36Sopenharmony_ci array.batch = param; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* guest side */ 12862306a36Sopenharmony_ciint add_inbuf(unsigned len, void *buf, void *datap) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci int ret; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci ret = __ptr_ring_produce(&array, buf); 13362306a36Sopenharmony_ci if (ret >= 0) { 13462306a36Sopenharmony_ci ret = 0; 13562306a36Sopenharmony_ci headcnt++; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return ret; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * ptr_ring API provides no way for producer to find out whether a given 14362306a36Sopenharmony_ci * buffer was consumed. Our tests merely require that a successful get_buf 14462306a36Sopenharmony_ci * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, 14562306a36Sopenharmony_ci * fake it accordingly. 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_civoid *get_buf(unsigned *lenp, void **bufp) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci void *datap; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (tailcnt == headcnt || __ptr_ring_full(&array)) 15262306a36Sopenharmony_ci datap = NULL; 15362306a36Sopenharmony_ci else { 15462306a36Sopenharmony_ci datap = "Buffer\n"; 15562306a36Sopenharmony_ci ++tailcnt; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return datap; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cibool used_empty() 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci return (tailcnt == headcnt || __ptr_ring_full(&array)); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_civoid disable_call() 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci assert(0); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cibool enable_call() 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci assert(0); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_civoid kick_available(void) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci assert(0); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci/* host side */ 18262306a36Sopenharmony_civoid disable_kick() 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci assert(0); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cibool enable_kick() 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci assert(0); 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cibool avail_empty() 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci return __ptr_ring_empty(&array); 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cibool use_buf(unsigned *lenp, void **bufp) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci void *ptr; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ptr = __ptr_ring_consume(&array); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci return ptr; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_civoid call_used(void) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci assert(0); 20962306a36Sopenharmony_ci} 210