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 = {