Skip to content

Commit

Permalink
Some serious hammerwork
Browse files Browse the repository at this point in the history
Signed-off-by: Hannu Lyytinen <[email protected]>
  • Loading branch information
hlyytine committed Oct 13, 2023
1 parent 626d4ac commit 058296a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 203 deletions.
173 changes: 120 additions & 53 deletions accel/sel4/sel4-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ typedef struct SeL4State
int fd;
int vmfd;
int ioreqfd;
struct sel4_iohandler_buffer *ioreq_buffer;
int eventfd;
void *iobuf;
void *event;
sel4_rpc_t rpc;
MemoryListener mem_listener;
} SeL4State ;

Expand Down Expand Up @@ -92,8 +95,6 @@ static int sel4_vm_ioctl(SeL4State *s, int type, ...)
return ret;
}

void seL4_Yield(void){}

static void sel4_setup_post(MachineState *ms, AccelState *accel)
{
SeL4State *s = SEL4_STATE(ms->accelerator);
Expand Down Expand Up @@ -189,76 +190,115 @@ static void sel4_change_state_handler(void *opaque, bool running, RunState state
}
}

static void sel4_mmio_do_io(struct sel4_ioreq *ioreq)
static void sel4_mmio_do_io(unsigned int dir, seL4_Word addr, seL4_Word *data,
unsigned int len)
{
qemu_mutex_lock_iothread();
switch (ioreq->direction) {
case SEL4_IO_DIR_WRITE:
address_space_write(&address_space_memory, ioreq->addr, MEMTXATTRS_UNSPECIFIED, &ioreq->data, ioreq->len);
break;
case SEL4_IO_DIR_READ:
address_space_read(&address_space_memory, ioreq->addr, MEMTXATTRS_UNSPECIFIED, &ioreq->data, ioreq->len);
break;
default:
error_report("sel4: invalid ioreq direction (%d)", ioreq->direction);
break;
if (dir == SEL4_IO_DIR_READ) {
address_space_read(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED, data, len);
} else {
address_space_write(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED, data, len);
}
qemu_mutex_unlock_iothread();
}

static void sel4_pci_do_io(struct sel4_ioreq *ioreq)
static void sel4_pci_do_io(unsigned int addr_space, unsigned int dir,
seL4_Word addr, seL4_Word *data,
unsigned int len)
{
PCIDevice *dev = pci_devs[ioreq->addr_space];
PCIDevice *dev = pci_devs[addr_space];
uint64_t val;

qemu_mutex_lock_iothread();
switch (ioreq->direction) {
case SEL4_IO_DIR_WRITE:
if (dir == SEL4_IO_DIR_READ) {
val = dev->config_read(dev, addr, len);
memcpy(data, &val, len);
} else {
val = 0;
memcpy(&val, &ioreq->data, ioreq->len);
dev->config_write(dev, ioreq->addr, val, ioreq->len);
break;
case SEL4_IO_DIR_READ:
val = dev->config_read(dev, ioreq->addr, ioreq->len);
memcpy(&ioreq->data, &val, ioreq->len);
break;
default:
error_report("sel4: invalid ioreq direction (%d)", ioreq->direction);
break;
memcpy(&val, data, len);
dev->config_write(dev, addr, val, len);
}
}

static inline int handle_mmio(SeL4State *s, rpcmsg_t *req)
{
seL4_Word dir = BIT_FIELD_GET(req->mr0, RPC_MR0_MMIO_DIRECTION);
seL4_Word as = BIT_FIELD_GET(req->mr0, RPC_MR0_MMIO_ADDR_SPACE);
seL4_Word len = BIT_FIELD_GET(req->mr0, RPC_MR0_MMIO_LENGTH);
seL4_Word slot = BIT_FIELD_GET(req->mr0, RPC_MR0_MMIO_SLOT);
seL4_Word addr = req->mr1;
seL4_Word data = req->mr2;

qemu_mutex_lock_iothread();

if (as == AS_GLOBAL) {
sel4_mmio_do_io(dir, addr, &data, len);
} else {
sel4_pci_do_io(as, dir, addr, &data, len);
}

qemu_mutex_unlock_iothread();

return driver_ack_mmio_finish(&s->rpc, slot, data) ? 0 : -1;
}

static inline void handle_ioreq(SeL4State *s)
static int handle_msg(SeL4State *s, rpcmsg_t *msg)
{
struct sel4_ioreq *ioreq;
int slot;

for (slot = 0; slot < SEL4_MAX_IOREQS; slot++) {
ioreq = &s->ioreq_buffer->request_slots[slot];
if (qatomic_load_acquire(&ioreq->state) == SEL4_IOREQ_STATE_PROCESSING) {
if (ioreq->addr_space == AS_GLOBAL) {
sel4_mmio_do_io(ioreq);
} else {
sel4_pci_do_io(ioreq);
}
unsigned int op = BIT_FIELD_GET(msg->mr0, RPC_MR0_OP);

sel4_vm_ioctl(s, SEL4_NOTIFY_IO_HANDLED, slot);
}
switch (op) {
case RPC_MR0_OP_MMIO:
return handle_mmio(s, msg);
default:
/* no idea what to do */
return -1;
}

return 0;
}

static inline int sel4_vm_wait_for_io(SeL4State *s)
{
return sel4_vm_ioctl(s, SEL4_WAIT_IO, 0);
}

static void *do_sel4_virtio(void *opaque)
{
SeL4State *s = opaque;
rpcmsg_t *msg;
int rc;

for (;;) {
rc = sel4_vm_ioctl(s, SEL4_WAIT_IO, 0);
sel4_rpc_doorbell(&s->rpc);

// fprintf(stderr, "qemu going to wait\n");
rc = sel4_vm_wait_for_io(s);
if (rc)
continue;

handle_ioreq(s);
while ((msg = rpcmsg_queue_head(s->rpc.rx_queue)) != NULL) {
seL4_Word state = BIT_FIELD_GET(msg->mr0, RPC_MR0_STATE);

if (state == RPC_MR0_STATE_RESERVED) {
/* VMM side is still crafting the message, try again later */
break;
} else if (state == RPC_MR0_STATE_PENDING) {
/* kernel has not examined this yet, try again later */
break;
} else if (state != RPC_MR0_STATE_PROCESSING) {
/* kernel is supposed to discard completed ioeventfds */
error_report("corrupted msgqueue");
exit(1);
}

rc = handle_msg(s, msg);
if (rc) {
error_report("handle_msg() failed (%d)", rc);
exit(1);
}

msg->mr0 = BIT_FIELD_SET(msg->mr0, RPC_MR0_STATE, RPC_MR0_STATE_COMPLETE);

/* smp_wmb()? */
rpcmsg_queue_advance_head(s->rpc.rx_queue);
}
}

return NULL;
Expand Down Expand Up @@ -348,6 +388,14 @@ static void sel4_region_del(MemoryListener *listener, MemoryRegionSection *secti
tii_printf("WARNING: %s entered, but no real implementation\n", __func__);
}

static void s2_fault_doorbell(void *cookie)
{
uint32_t *event_bar = cookie;

/* data does not matter, just the write fault */
event_bar[0] = 1;
}

static int sel4_init(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
Expand Down Expand Up @@ -407,13 +455,32 @@ static int sel4_init(MachineState *ms)
}
s->ioreqfd = rc;

s->ioreq_buffer = mmap(NULL, sizeof(*s->ioreq_buffer),
PROT_READ | PROT_WRITE, MAP_SHARED, s->ioreqfd, 0);
if (!s->ioreq_buffer) {
s->iobuf = mmap(NULL, 2 * 4096, PROT_READ | PROT_WRITE, MAP_SHARED,
s->ioreqfd, 0);
if (!s->iobuf) {
fprintf(stderr, "sel4: iohandler mmap failed %m\n");
goto err;
}

rc = sel4_vm_ioctl(s, SEL4_CREATE_EVENT_BAR, 0);
if (rc < 0) {
fprintf(stderr, "sel4: create event handler failed: %d %s\n", -rc,
strerror(-rc));
goto err;
}
s->eventfd = rc;
s->event = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED,
s->eventfd, 0);
if (!s->iobuf) {
fprintf(stderr, "sel4: event mmap failed %m\n");
goto err;
}

s->rpc.rx_queue = device_rx_queue(s->iobuf);
s->rpc.tx_queue = device_tx_queue(s->iobuf);
s->rpc.doorbell = s2_fault_doorbell;
s->rpc.doorbell_cookie = s->event;

s->mem_listener.eventfd_add = sel4_io_ioeventfd_add;
s->mem_listener.eventfd_del = sel4_io_ioeventfd_del;
s->mem_listener.region_add = sel4_region_add;
Expand All @@ -426,8 +493,8 @@ static int sel4_init(MachineState *ms)
return 0;

err:
if (s->ioreq_buffer)
munmap(s->ioreq_buffer, sizeof(*s->ioreq_buffer));
if (s->iobuf)
munmap(s->iobuf, 2 * 4096);

if (ram)
munmap(ram, ms->ram_size);
Expand Down Expand Up @@ -546,7 +613,7 @@ static void sel4_accel_instance_init(Object *obj)
s->fd = -1;
s->vmfd = -1;
s->ioreqfd = -1;
s->ioreq_buffer = NULL;
memset(&s->rpc, 0, sizeof(s->rpc));

virt_memmap_customize = sel4_memmap_customize;
}
Expand Down
Loading

0 comments on commit 058296a

Please sign in to comment.