iodev, uartproxy: Fix write interleaving causing corruption

This should fix the issue where console writes from another CPU in the
middle of events/etc corrupt data

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2022-07-22 07:01:46 +09:00
parent 170cca1482
commit 4c672c00b6
3 changed files with 24 additions and 0 deletions

View file

@ -124,6 +124,24 @@ void iodev_flush(iodev_id_t id)
spin_unlock(&iodevs[id]->lock);
}
void iodev_lock(iodev_id_t id)
{
if (!iodevs[id])
return;
if (mmu_active())
spin_lock(&iodevs[id]->lock);
}
void iodev_unlock(iodev_id_t id)
{
if (!iodevs[id])
return;
if (mmu_active())
spin_unlock(&iodevs[id]->lock);
}
int in_iodev = 0;
static DECLARE_SPINLOCK(console_lock);

View file

@ -49,6 +49,8 @@ ssize_t iodev_write(iodev_id_t id, const void *buf, size_t length);
ssize_t iodev_queue(iodev_id_t id, const void *buf, size_t length);
void iodev_flush(iodev_id_t id);
void iodev_handle_events(iodev_id_t id);
void iodev_lock(iodev_id_t id);
void iodev_unlock(iodev_id_t id);
void iodev_console_write(const void *buf, size_t length);
void iodev_console_kick(void);

View file

@ -270,6 +270,7 @@ int uartproxy_run(struct uartproxy_msg_start *start)
sysop("dsb sy");
sysop("isb");
reply.checksum = checksum(&reply, REPLY_SIZE - 4);
iodev_lock(uartproxy_iodev);
iodev_queue(iodev, &reply, REPLY_SIZE);
if ((request.type == REQ_MEMREAD) && (reply.status == ST_OK)) {
@ -284,6 +285,7 @@ int uartproxy_run(struct uartproxy_msg_start *start)
}
}
iodev_unlock(uartproxy_iodev);
// Flush all queued data
iodev_write(iodev, NULL, 0);
iodev_flush(iodev);
@ -307,7 +309,9 @@ void uartproxy_send_event(u16 event_type, void *data, u16 length)
csum = checksum_start(&hdr, sizeof(UartEventHdr));
csum = checksum_finish(checksum_add(data, length, csum));
}
iodev_lock(uartproxy_iodev);
iodev_queue(uartproxy_iodev, &hdr, sizeof(UartEventHdr));
iodev_queue(uartproxy_iodev, data, length);
iodev_write(uartproxy_iodev, &csum, sizeof(csum));
iodev_unlock(uartproxy_iodev);
}