-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
isubasinghe
committed
Feb 28, 2024
1 parent
36bb9a1
commit b8d94d9
Showing
13 changed files
with
2,357 additions
and
11 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include <stdbool.h> | ||
#include <string.h> | ||
|
||
#include "shared_ringbuffer.h" | ||
#include "util.h" | ||
|
||
/* Notification and PPC channels - ensure these align with .system file! */ | ||
#define MUX_RX_CH 0 | ||
#define CLIENT_CH 1 | ||
|
||
/* Ring handles */ | ||
ring_handle_t rx_ring_mux; | ||
ring_handle_t rx_ring_cli; | ||
|
||
/* Ring buffer regions */ | ||
uintptr_t rx_free_mux; | ||
uintptr_t rx_used_mux; | ||
uintptr_t rx_free_cli; | ||
uintptr_t rx_used_cli; | ||
|
||
/* Buffer data regions */ | ||
uintptr_t mux_buffer_data_region; | ||
uintptr_t cli_buffer_data_region; | ||
|
||
uintptr_t uart_base; | ||
|
||
void rx_return(void) | ||
{ | ||
bool enqueued = false; | ||
bool reprocess = true; | ||
|
||
while (reprocess) { | ||
while (!ring_empty(rx_ring_mux.used_ring) && !ring_empty(rx_ring_cli.free_ring) && | ||
!ring_full(rx_ring_mux.free_ring) && !ring_full(rx_ring_cli.used_ring)) { | ||
buff_desc_t cli_buffer, mux_buffer; | ||
int err __attribute__((unused)) = dequeue_free(&rx_ring_cli, &cli_buffer); | ||
assert(!err); | ||
|
||
if (cli_buffer.offset % BUF_SIZE || cli_buffer.offset >= BUF_SIZE * NUM_BUFFERS) { | ||
printf("COPY|LOG: Client provided offset %X which is not buffer aligned or outside of buffer region\n", cli_buffer.offset); | ||
err = enqueue_free(&rx_ring_cli, cli_buffer); | ||
assert(!err); | ||
continue; | ||
} | ||
|
||
err = dequeue_used(&rx_ring_mux, &mux_buffer); | ||
assert(!err); | ||
|
||
uintptr_t cli_addr = cli_buffer_data_region + cli_buffer.offset; | ||
uintptr_t mux_addr = mux_buffer_data_region + mux_buffer.offset; | ||
|
||
memcpy((void *)cli_addr, (void *)mux_addr, mux_buffer.len); | ||
cli_buffer.len = mux_buffer.len; | ||
mux_buffer.len = 0; | ||
|
||
err = enqueue_used(&rx_ring_cli, cli_buffer); | ||
assert(!err); | ||
|
||
err = enqueue_free(&rx_ring_mux, mux_buffer); | ||
assert(!err); | ||
|
||
enqueued = true; | ||
} | ||
|
||
request_signal(rx_ring_mux.used_ring); | ||
|
||
/* Only request signal from client if incoming packets from multiplexer are awaiting free buffers */ | ||
if (!ring_empty(rx_ring_mux.used_ring)) request_signal(rx_ring_cli.free_ring); | ||
else cancel_signal(rx_ring_cli.free_ring); | ||
|
||
reprocess = false; | ||
|
||
if (!ring_empty(rx_ring_mux.used_ring) && !ring_empty(rx_ring_cli.free_ring) && | ||
!ring_full(rx_ring_mux.free_ring) && !ring_full(rx_ring_cli.used_ring)) { | ||
cancel_signal(rx_ring_mux.used_ring); | ||
cancel_signal(rx_ring_cli.free_ring); | ||
reprocess = true; | ||
} | ||
} | ||
|
||
if (enqueued && require_signal(rx_ring_cli.used_ring)) { | ||
cancel_signal(rx_ring_cli.used_ring); | ||
sel4cp_notify(CLIENT_CH); | ||
} | ||
|
||
if (enqueued && require_signal(rx_ring_mux.free_ring)) { | ||
cancel_signal(rx_ring_mux.free_ring); | ||
sel4cp_notify_delayed(MUX_RX_CH); | ||
} | ||
} | ||
|
||
void notified(sel4cp_channel ch) | ||
{ | ||
rx_return(); | ||
} | ||
|
||
void init(void) | ||
{ | ||
ring_init(&rx_ring_mux, (ring_buffer_t *)rx_free_mux, (ring_buffer_t *)rx_used_mux, NUM_BUFFERS, NUM_BUFFERS); | ||
ring_init(&rx_ring_cli, (ring_buffer_t *)rx_free_cli, (ring_buffer_t *)rx_used_cli, NUM_BUFFERS, NUM_BUFFERS); | ||
|
||
buffers_init(rx_ring_cli.free_ring, 0, NUM_BUFFERS, BUF_SIZE); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
# 0 "out_copy.c" | ||
# 0 "<built-in>" | ||
# 0 "<command-line>" | ||
# 1 "/usr/include/stdc-predef.h" 1 3 4 | ||
# 0 "<command-line>" 2 | ||
# 1 "out_copy.c" | ||
|
||
|
||
typedef unsigned long uint64_t; | ||
typedef unsigned short uint16_t; | ||
typedef unsigned int uint32_t; | ||
typedef uint64_t size_t; | ||
typedef uint64_t uintptr_t; | ||
|
||
|
||
typedef unsigned char bool; | ||
# 19 "out_copy.c" | ||
void assert(bool b); | ||
|
||
|
||
|
||
void *memcpy(void *dest, const void *src, size_t n); | ||
|
||
|
||
typedef unsigned int sel4cp_channel; | ||
void sel4cp_notify(sel4cp_channel ch); | ||
void sel4cp_notify_delayed(sel4cp_channel ch); | ||
# 51 "out_copy.c" | ||
typedef struct buff_desc { | ||
uintptr_t phys_or_offset; | ||
uint16_t len; | ||
void *cookie; | ||
} buff_desc_t; | ||
|
||
|
||
typedef struct ring_buffer { | ||
uint32_t head; | ||
uint32_t tail; | ||
buff_desc_t buffers[512]; | ||
uint32_t size; | ||
bool consumer_signalled; | ||
} ring_buffer_t; | ||
|
||
|
||
typedef struct ring_handle { | ||
ring_buffer_t *free_ring; | ||
ring_buffer_t *used_ring; | ||
} ring_handle_t; | ||
# 79 "out_copy.c" | ||
static inline bool ring_empty(ring_buffer_t *ring) | ||
{ | ||
return (ring->head == ring->tail); | ||
} | ||
# 91 "out_copy.c" | ||
static inline bool ring_full(ring_buffer_t *ring) | ||
// requires ring->size >= 1 | ||
// ensures return == {retbody} | ||
{ | ||
return (((ring->head + 1) % ring->size) == ring->tail); | ||
} | ||
# 103 "out_copy.c" | ||
static inline uint32_t ring_size(ring_buffer_t *ring) | ||
{ | ||
return (((ring->head + ring->size) - ring->tail) % ring->size); | ||
} | ||
# 116 "out_copy.c" | ||
static inline int enqueue(ring_buffer_t *ring, buff_desc_t buffer) | ||
{ | ||
if (ring_full(ring)) return -1; | ||
|
||
ring->buffers[ring->head].phys_or_offset = buffer.phys_or_offset; | ||
ring->buffers[ring->head].len = buffer.len; | ||
ring->buffers[ring->head].cookie = buffer.cookie; | ||
if (0) ; | ||
ring->head = (ring->head + 1) % ring->size; | ||
|
||
return 0; | ||
} | ||
# 135 "out_copy.c" | ||
static inline buff_desc_t dequeue(ring_buffer_t *ring) | ||
{ | ||
if (ring_empty(ring)) assert(0); | ||
|
||
buff_desc_t buffer; | ||
buffer = ring->buffers[ring->tail]; | ||
if (0) ; | ||
ring->tail = (ring->tail + 1) % ring->size; | ||
|
||
return buffer; | ||
} | ||
# 155 "out_copy.c" | ||
static inline int enqueue_free(ring_handle_t *ring, buff_desc_t buffer) | ||
{ | ||
return enqueue(ring->free_ring, buffer); | ||
} | ||
# 168 "out_copy.c" | ||
static inline int enqueue_used(ring_handle_t *ring, buff_desc_t buffer) | ||
{ | ||
return enqueue(ring->used_ring, buffer); | ||
} | ||
# 181 "out_copy.c" | ||
static inline buff_desc_t dequeue_free(ring_handle_t *ring) | ||
{ | ||
return dequeue(ring->free_ring); | ||
} | ||
# 194 "out_copy.c" | ||
static inline buff_desc_t dequeue_used(ring_handle_t *ring) | ||
{ | ||
return dequeue(ring->used_ring); | ||
} | ||
# 208 "out_copy.c" | ||
void ring_init(ring_handle_t *ring, ring_buffer_t *free, ring_buffer_t *used, uint32_t free_size, uint32_t used_size); | ||
# 218 "out_copy.c" | ||
static inline void buffers_init(ring_buffer_t *free_ring, uintptr_t base_addr, uint32_t ring_size, uint32_t buffer_size) | ||
{ | ||
for (int i = 0; i < ring_size - 1; i++) { | ||
buff_desc_t buffer = {(buffer_size * i) + base_addr, 0, ((void *) 0)}; | ||
int err __attribute__((unused)) = enqueue(free_ring, buffer); | ||
assert(!err); | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
static inline void request_signal(ring_buffer_t *ring_buffer) | ||
{ | ||
ring_buffer->consumer_signalled = 0; | ||
if (0) ; | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
static inline void cancel_signal(ring_buffer_t *ring_buffer) | ||
{ | ||
ring_buffer->consumer_signalled = 1; | ||
if (0) ; | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
static inline bool require_signal(ring_buffer_t *ring_buffer) | ||
{ | ||
return !ring_buffer->consumer_signalled; | ||
} | ||
# 269 "out_copy.c" | ||
ring_handle_t rx_ring_mux; | ||
ring_handle_t rx_ring_cli; | ||
|
||
|
||
uintptr_t rx_free_mux; | ||
uintptr_t rx_used_mux; | ||
uintptr_t rx_free_cli; | ||
uintptr_t rx_used_cli; | ||
|
||
|
||
uintptr_t mux_buffer_data_region; | ||
uintptr_t cli_buffer_data_region; | ||
|
||
uintptr_t uart_base; | ||
|
||
void rx_return(void) | ||
{ | ||
bool enqueued = 0; | ||
bool reprocess = 1; | ||
|
||
while (reprocess) { | ||
while (!ring_empty(rx_ring_mux.used_ring) && !ring_empty(rx_ring_cli.free_ring) && | ||
!ring_full(rx_ring_mux.free_ring) && !ring_full(rx_ring_cli.used_ring)) { | ||
buff_desc_t cli_buffer, mux_buffer; | ||
int err; | ||
cli_buffer = dequeue_free(&rx_ring_cli); | ||
|
||
if (cli_buffer.phys_or_offset % 2048 || cli_buffer.phys_or_offset >= 2048 * 512) { | ||
((void) 0); | ||
err = enqueue_free(&rx_ring_cli, cli_buffer); | ||
assert(!err); | ||
} else { | ||
mux_buffer = dequeue_used(&rx_ring_mux); | ||
|
||
uintptr_t cli_addr = cli_buffer_data_region + cli_buffer.phys_or_offset; | ||
uintptr_t mux_addr = mux_buffer_data_region + mux_buffer.phys_or_offset; | ||
|
||
memcpy((void *)cli_addr, (void *)mux_addr, mux_buffer.len); | ||
cli_buffer.len = mux_buffer.len; | ||
mux_buffer.len = 0; | ||
|
||
err = enqueue_used(&rx_ring_cli, cli_buffer); | ||
assert(!err); | ||
|
||
err = enqueue_free(&rx_ring_mux, mux_buffer); | ||
assert(!err); | ||
|
||
enqueued = 1; | ||
} | ||
|
||
} | ||
|
||
request_signal(rx_ring_mux.used_ring); | ||
|
||
|
||
if (!ring_empty(rx_ring_mux.used_ring)) request_signal(rx_ring_cli.free_ring); | ||
else cancel_signal(rx_ring_cli.free_ring); | ||
|
||
reprocess = 0; | ||
|
||
if (!ring_empty(rx_ring_mux.used_ring) && !ring_empty(rx_ring_cli.free_ring) && | ||
!ring_full(rx_ring_mux.free_ring) && !ring_full(rx_ring_cli.used_ring)) { | ||
cancel_signal(rx_ring_mux.used_ring); | ||
cancel_signal(rx_ring_cli.free_ring); | ||
reprocess = 1; | ||
} | ||
} | ||
|
||
if (enqueued && require_signal(rx_ring_cli.used_ring)) { | ||
cancel_signal(rx_ring_cli.used_ring); | ||
sel4cp_notify(1); | ||
} | ||
|
||
if (enqueued && require_signal(rx_ring_mux.free_ring)) { | ||
cancel_signal(rx_ring_mux.free_ring); | ||
sel4cp_notify_delayed(0); | ||
} | ||
} | ||
|
||
void notified(sel4cp_channel ch) | ||
{ | ||
rx_return(); | ||
} | ||
|
||
void init(void) | ||
{ | ||
ring_init(&rx_ring_mux, (ring_buffer_t *)rx_free_mux, (ring_buffer_t *)rx_used_mux, 512, 512); | ||
ring_init(&rx_ring_cli, (ring_buffer_t *)rx_free_cli, (ring_buffer_t *)rx_used_cli, 512, 512); | ||
|
||
buffers_init(rx_ring_cli.free_ring, 0, 512, 2048); | ||
} |
Oops, something went wrong.