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