bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v4 hurd] pci: Add RPC for grabbing io ports by region


From: Damien Zammit
Subject: [PATCH v4 hurd] pci: Add RPC for grabbing io ports by region
Date: Sun, 23 Jul 2023 03:36:24 +0000

This would allow pci-arbiter to control which io ports
are accessed and pave the way to having granular access to io ports
based on pci cards exposing their IO BARs.

libpciaccess has convenient api for this kind of access, it allows
opening and registering io ports by BAR.

Therefore, we can first introduce this new RPC, then see if changing
libpciaccess to only expose PCI_CFG1 ports on x86 method and granular access
to other io ports on hurdish method still works with other servers.

Finally, once this is done, we can check if locking the io ports down
to exclusive regions that cant overlap will function correctly with
gnumach and the rest of the hurd.

---
 hurd/pci.defs            | 10 +++++++
 pci-arbiter/func_files.c |  2 +-
 pci-arbiter/func_files.h |  5 +++-
 pci-arbiter/netfs_impl.c | 18 ++++++++----
 pci-arbiter/pci-ops.c    | 59 ++++++++++++++++++++++++++++++++++++++++
 pci-arbiter/pcifs.c      |  5 +++-
 6 files changed, 90 insertions(+), 9 deletions(-)

diff --git a/hurd/pci.defs b/hurd/pci.defs
index e258f5ce..c6c20843 100644
--- a/hurd/pci.defs
+++ b/hurd/pci.defs
@@ -71,3 +71,13 @@ routine pci_get_dev_rom(
        master: pci_t;
        out data: data_t, dealloc
 );
+
+/*
+ * Request io ports for a specific io region for a device.
+ * The resulting port may be used to call mach rpc i386_io_perm_modify.
+ * Only works on io region files.
+ */
+routine pci_request_io_ports(
+       master: pci_t;
+       out io_perm: mach_port_t
+);
diff --git a/pci-arbiter/func_files.c b/pci-arbiter/func_files.c
index 27a72209..3b01e47f 100644
--- a/pci-arbiter/func_files.c
+++ b/pci-arbiter/func_files.c
@@ -129,7 +129,7 @@ read_rom_file (struct pcifs_dirent * e, off_t offset, 
size_t * len,
   return 0;
 }
 
-/* Read or write from/to a memory region by using I/O ports */
+/* Read or write from/to an io region by using I/O ports */
 static error_t
 region_block_ioport_op (uint16_t port, off_t offset, size_t * len,
                        void *data, int read)
diff --git a/pci-arbiter/func_files.h b/pci-arbiter/func_files.h
index cf77374a..70e92e5b 100644
--- a/pci-arbiter/func_files.h
+++ b/pci-arbiter/func_files.h
@@ -34,9 +34,12 @@ typedef int (*pci_io_op_t) (struct pci_device *dev, void 
*data,
 /* Rom */
 #define FILE_ROM_NAME     "rom"
 
-/* Region */
+/* Memory Region */
 #define FILE_REGION_NAME     "region"
 
+/* I/O Region */
+#define FILE_IO_NAME     "io"
+
 error_t io_config_file (struct pci_device * dev, off_t offset, size_t * len,
                        void *data, pci_io_op_t op);
 
diff --git a/pci-arbiter/netfs_impl.c b/pci-arbiter/netfs_impl.c
index 4bb5c97a..484ea9eb 100644
--- a/pci-arbiter/netfs_impl.c
+++ b/pci-arbiter/netfs_impl.c
@@ -514,8 +514,10 @@ netfs_attempt_read (struct iouser * cred, struct node * 
node,
        /* Update atime */
        UPDATE_TIMES (node->nn->ln, TOUCH_ATIME);
     }
-  else if (!strncmp
-          (node->nn->ln->name, FILE_REGION_NAME, strlen (FILE_REGION_NAME)))
+  else if ((!strncmp
+           (node->nn->ln->name, FILE_REGION_NAME, strlen (FILE_REGION_NAME)))
+       || (!strncmp
+           (node->nn->ln->name, FILE_IO_NAME, strlen (FILE_IO_NAME))))
     {
       err = io_region_file (node->nn->ln, offset, len, data, 1);
       if (!err)
@@ -548,13 +550,17 @@ netfs_attempt_write (struct iouser * cred, struct node * 
node,
           UPDATE_TIMES (node->nn->ln, TOUCH_MTIME | TOUCH_CTIME);
         }
     }
-  else if (!strncmp
-          (node->nn->ln->name, FILE_REGION_NAME, strlen (FILE_REGION_NAME)))
+  else if ((!strncmp
+           (node->nn->ln->name, FILE_REGION_NAME, strlen (FILE_REGION_NAME)))
+       || (!strncmp
+            (node->nn->ln->name, FILE_IO_NAME, strlen (FILE_IO_NAME))))
     {
       err = io_region_file (node->nn->ln, offset, len, (void*) data, 0);
       if (!err)
-       /* Update atime */
-       UPDATE_TIMES (node->nn->ln, TOUCH_MTIME | TOUCH_CTIME);
+       {
+         /* Update mtime and ctime */
+         UPDATE_TIMES (node->nn->ln, TOUCH_MTIME | TOUCH_CTIME);
+       }
     }
   else
     return EOPNOTSUPP;
diff --git a/pci-arbiter/pci-ops.c b/pci-arbiter/pci-ops.c
index 2f9f5296..562c0bca 100644
--- a/pci-arbiter/pci-ops.c
+++ b/pci-arbiter/pci-ops.c
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <hurd/netfs.h>
 #include <sys/mman.h>
+#include <mach/machine/mach_i386.h>
 
 #include <pciaccess.h>
 #include "pcifs.h"
@@ -273,3 +274,61 @@ S_pci_get_dev_rom (struct protid * master, char **data, 
mach_msg_type_number_t *
 
   return 0;
 }
+
+error_t
+request_io_ports (struct pcifs_dirent *e, io_perm_t *io_perm)
+{
+  int bar;
+  uint64_t iobase, iosize;
+  io_port_t from, to;
+  error_t err;
+  mach_port_t device_master;
+
+  if (get_privileged_ports (0, &device_master))
+    return EPERM;
+
+  bar = strtol (&e->name[strlen (FILE_IO_NAME)], NULL, 10);
+  if (errno)
+    return errno;
+
+  if ((bar < 0) || (bar > 5))
+    /* This operation only works on IO bars between 0-5 */
+    return EINVAL;
+
+  iobase = e->device->regions[bar].base_addr;
+  iosize = e->device->regions[bar].size;
+  if ((iobase >= 0x10000) || (iosize >= 0x10000) || (iobase + iosize >= 
0x10000))
+    return EINVAL;
+
+  from = iobase;
+  to = from + iosize - 1;
+
+  if ((err = i386_io_perm_create (device_master, from, to, io_perm)))
+    return err;
+
+  /* Update atime */
+  UPDATE_TIMES (e, TOUCH_ATIME);
+
+  return 0;
+}
+
+error_t
+S_pci_request_io_ports (struct protid * master, io_perm_t *io_perm)
+{
+  error_t err;
+  struct pcifs_dirent *e;
+
+  if (!master)
+    return EOPNOTSUPP;
+
+  e = master->po->np->nn->ln;
+  if (strncmp (e->name, FILE_IO_NAME, NAME_SIZE))
+    /* This operation may only be addressed to IO regions */
+    return EINVAL;
+
+  err = check_permissions (master, O_READ | O_WRITE);
+  if (err)
+    return err;
+
+  return request_io_ports (e, io_perm);
+}
diff --git a/pci-arbiter/pcifs.c b/pci-arbiter/pcifs.c
index 9c710016..7fc9a75d 100644
--- a/pci-arbiter/pcifs.c
+++ b/pci-arbiter/pcifs.c
@@ -317,7 +317,10 @@ create_fs_tree (struct pcifs * fs)
          if (device->regions[j].size > 0)
            {
              e_stat.st_size = device->regions[j].size;
-             snprintf (entry_name, NAME_SIZE, "%s%01u", FILE_REGION_NAME, j);
+             if (device->regions[j].is_IO)
+               snprintf (entry_name, NAME_SIZE, "%s%01u", FILE_IO_NAME, j);
+             else
+               snprintf (entry_name, NAME_SIZE, "%s%01u", FILE_REGION_NAME, j);
              err =
                create_dir_entry (device->domain, device->bus, device->dev,
                                  device->func, device->device_class,
-- 
2.40.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]