iommu: use parse_cmd() for attach/detach I don't like using sscanf on user-space strings. That, and parsecmd() is the approved way to handle command strings. Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/drivers/dev/iommu.c b/kern/drivers/dev/iommu.c index b657dbd..4b9019f 100644 --- a/kern/drivers/dev/iommu.c +++ b/kern/drivers/dev/iommu.c
@@ -635,43 +635,6 @@ poperror(); } - -// XXX user pointer, parsecmd, \n -static int write_add_dev(char *va, size_t n) -{ - int bus, dev, func, err; - pid_t pid; - - err = sscanf(va, "%x:%x.%x %d\n", &bus, &dev, &func, &pid); - - if (err != 4) - error(EIO, - IOMMU "error parsing #iommu/attach; items parsed: %d", err); - - if (pid == 1) - error(EIO, IOMMU "device passthru not supported for pid = 1"); - - assign_device(bus, dev, func, pid); - - return n; -} - -static int write_remove_dev(char *va, size_t n) -{ - int bus, dev, func, err; - pid_t pid; - - err = sscanf(va, "%x:%x.%x %d\n", &bus, &dev, &func, &pid); - - if (err != 4) - error(EIO, - IOMMU "error parsing #iommu/detach; items parsed: %d", err); - - unassign_device(bus, dev, func, pid); - - return n; -} - static struct sized_alloc *open_mappings(void) { struct iommu *iommu; @@ -874,20 +837,64 @@ return -1; /* not reached */ } +static void get_bdf_pid(struct cmdbuf *cb, int *bus, int *dev, int *func, + pid_t *pid) +{ + int err; + + if (cb->nf < 2) + error(EFAIL, "bb:dd.f pid"); + + err = sscanf(cb->f[0], "%x:%x.%x", bus, dev, func); + if (err != 3) + error(EIO, + IOMMU "error parsing bdf %s; nr parsed: %d", cb->f[0], err); + + *pid = strtoul(cb->f[1], 0, 0); +} + +static void write_add_dev(struct chan *c, struct cmdbuf *cb) +{ + int bus, dev, func; + pid_t pid; + + get_bdf_pid(cb, &bus, &dev, &func, &pid); + + if (pid == 1) + error(EIO, IOMMU "device passthru not supported for pid = 1"); + + assign_device(bus, dev, func, pid); +} + +static void write_remove_dev(struct chan *c, struct cmdbuf *cb) +{ + int bus, dev, func; + pid_t pid; + + get_bdf_pid(cb, &bus, &dev, &func, &pid); + + unassign_device(bus, dev, func, pid); +} + static size_t iommuwrite(struct chan *c, void *va, size_t n, off64_t offset) { - int err = -1; + ERRSTACK(1); + struct cmdbuf *cb = parsecmd(va, n); + if (waserror()) { + kfree(cb); + nexterror(); + } switch (c->qid.path) { case Qadddev: if (!iommu_is_supported) error(EROFS, IOMMU "not supported"); - err = write_add_dev(va, n); + write_add_dev(c, cb); break; case Qremovedev: if (!iommu_is_supported) error(EROFS, IOMMU "not supported"); - err = write_remove_dev(va, n); + write_remove_dev(c, cb); break; case Qmappings: case Qinfo: @@ -896,8 +903,9 @@ default: error(EIO, "write: qid %d is impossible", c->qid.path); } - - return err; + kfree(cb); + poperror(); + return n; } struct dev iommudevtab __devtab = {