qemu_pci_serial device locking/sync

This commit is contained in:
2025-11-24 22:29:32 +01:00
parent 80a29d8ff6
commit cc2b96f37a
3 changed files with 83 additions and 2 deletions

View File

@ -6,6 +6,8 @@
#include "sysdefs/dev.h" #include "sysdefs/dev.h"
#include "util/util.h" #include "util/util.h"
#include "dev/dev.h" #include "dev/dev.h"
#include "cjob/cjob.h"
#include "proc/proc.h"
#include "errors.h" #include "errors.h"
#include "hshtb.h" #include "hshtb.h"
#include "kprintf.h" #include "kprintf.h"
@ -53,6 +55,11 @@ int32_t qemu_pci_serial_dev_sendb(struct Dev *dev, uint8_t *buffer, size_t len,
(void)len; (void)pid; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra; QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
_serial_sendb(qpsd->iobase, buffer[0]); _serial_sendb(qpsd->iobase, buffer[0]);
return E_OK; return E_OK;
@ -63,6 +70,10 @@ int32_t qemu_pci_serial_dev_sendready(struct Dev *dev, uint8_t *buffer, size_t l
QemuPciSerialDev *qpsd = dev->extra; QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
return _serial_sendready(qpsd->iobase); return _serial_sendready(qpsd->iobase);
} }
@ -71,17 +82,76 @@ int32_t qemu_pci_serial_dev_recvb(struct Dev *dev, uint8_t *buffer, size_t len,
QemuPciSerialDev *qpsd = dev->extra; QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
return _serial_recvb(qpsd->iobase); return _serial_recvb(qpsd->iobase);
} }
int32_t qemu_pci_serial_dev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { int32_t qemu_pci_serial_dev_recvready(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)pid; (void)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra; QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate != -1 && qpsd->lockstate != (int)pid) {
return E_DEVLOCKED;
}
return _serial_recvready(qpsd->iobase); return _serial_recvready(qpsd->iobase);
} }
int32_t qemu_pci_serial_dev_lock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate == (int)pid) {
return E_OK;
}
if (qpsd->lockstate == -1) {
qpsd->lockstate = (int)pid;
return E_OK;
}
return E_DEVLOCKED;
}
int32_t qemu_pci_serial_dev_unlock(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)buffer; (void)len; (void)pid;
QemuPciSerialDev *qpsd = dev->extra;
if (qpsd->lockstate == (int)pid) {
qpsd->lockstate = -1;
return E_OK;
}
return E_DEVNOTYOURLOCK;
}
void pci_qemu_pci_serial_gc_cjob(void *arg) {
Dev *dev = arg;
QemuPciSerialDev *qpsd;
spinlock_acquire(&dev->spinlock);
qpsd = dev->extra;
uint64_t pid = qpsd->lockstate;
spinlock_release(&dev->spinlock);
Proc *proc = NULL;
spinlock_acquire(&PROCS.spinlock);
LL_FINDPROP(PROCS.procs, proc, pid, pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
spinlock_acquire(&dev->spinlock);
qpsd = dev->extra;
qpsd->lockstate = -1;
spinlock_release(&dev->spinlock);
}
}
void pci_qemu_pci_serial_init(void) { void pci_qemu_pci_serial_init(void) {
PciDev dev = pci_getdev(0x1B36, 0x0002, -1); PciDev dev = pci_getdev(0x1B36, 0x0002, -1);
if (!dev.bits) { if (!dev.bits) {
@ -97,6 +167,7 @@ void pci_qemu_pci_serial_init(void) {
QEMU_PCI_SERIAL_DEV._magic = QEMU_PCI_SERIAL_MAGIC; QEMU_PCI_SERIAL_DEV._magic = QEMU_PCI_SERIAL_MAGIC;
QEMU_PCI_SERIAL_DEV.iobase = iobase; QEMU_PCI_SERIAL_DEV.iobase = iobase;
QEMU_PCI_SERIAL_DEV.lockstate = -1;
Dev *serialdev = NULL; Dev *serialdev = NULL;
HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev); HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev);
@ -104,8 +175,13 @@ void pci_qemu_pci_serial_init(void) {
serialdev->fns[1] = &qemu_pci_serial_dev_sendready; serialdev->fns[1] = &qemu_pci_serial_dev_sendready;
serialdev->fns[2] = &qemu_pci_serial_dev_recvb; serialdev->fns[2] = &qemu_pci_serial_dev_recvb;
serialdev->fns[3] = &qemu_pci_serial_dev_recvready; serialdev->fns[3] = &qemu_pci_serial_dev_recvready;
serialdev->fns[4] = &qemu_pci_serial_dev_lock;
serialdev->fns[5] = &qemu_pci_serial_dev_unlock;
spinlock_init(&serialdev->spinlock); spinlock_init(&serialdev->spinlock);
serialdev->extra = &QEMU_PCI_SERIAL_DEV; serialdev->extra = &QEMU_PCI_SERIAL_DEV;
cjob_register(&pci_qemu_pci_serial_gc_cjob, serialdev);
_serial_init(QEMU_PCI_SERIAL_DEV.iobase); _serial_init(QEMU_PCI_SERIAL_DEV.iobase);
} }

View File

@ -9,6 +9,7 @@
typedef struct { typedef struct {
uint32_t _magic; uint32_t _magic;
uint16_t iobase; uint16_t iobase;
int lockstate;
} QemuPciSerialDev; } QemuPciSerialDev;
void pci_qemu_pci_serial_init(void); void pci_qemu_pci_serial_init(void);

View File

@ -17,6 +17,8 @@
#define E_SPAWNERROR -13 #define E_SPAWNERROR -13
#define E_NOTYET -14 #define E_NOTYET -14
#define E_MOUNTERR -15 #define E_MOUNTERR -15
#define E_DEVLOCKED -16
#define E_DEVNOTYOURLOCK -17
#if !defined(__ASSEMBLER__) #if !defined(__ASSEMBLER__)
@ -38,6 +40,8 @@ static const char *_ERROR_STRINGS[] = {
"Process spawn error", "Process spawn error",
"Data isn't ready yet", "Data isn't ready yet",
"File system mount error", "File system mount error",
"This device is locked",
"Device is hasn't been locked by this process",
}; };
#define ERRSTRING_INDEX(ioh) ((size_t)((ioh) < 0 ? (ioh) * (-1) : (ioh))) #define ERRSTRING_INDEX(ioh) ((size_t)((ioh) < 0 ? (ioh) * (-1) : (ioh)))