bug-hurd
[Top][All Lists]
Advanced

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

[RFC PATCH hurd] pci: Add RPCs for taking and freeing io ports by BAR


From: Damien Zammit
Subject: [RFC PATCH hurd] pci: Add RPCs for taking and freeing io ports by BAR
Date: Sat, 15 Jul 2023 16:09:57 +0000

The rationale behind this change is that IO ports should not be mapped
as regions, because you are not supposed to access them as a byte
stream, they are accessed in certain widths depending on what hardware
is backing them.  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.

I am looking for comments regarding this change first before I send
the others.

Specifically, I am looking for a way to have the io ports which are attached
to a particular pci device released when the device port is deallocated.

---
 hurd/pci.defs            | 18 +++++++++++
 pci-arbiter/netfs_impl.c |  4 +++
 pci-arbiter/pci-ops.c    | 67 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)

diff --git a/hurd/pci.defs b/hurd/pci.defs
index e258f5ce..920dca77 100644
--- a/hurd/pci.defs
+++ b/hurd/pci.defs
@@ -71,3 +71,21 @@ routine pci_get_dev_rom(
        master: pci_t;
        out data: data_t, dealloc
 );
+
+/*
+ * Request io ports for BAR 0-5 for a given device.
+ * Only works on bars that correspond to IO ports.
+ */
+routine pci_take_io_ports(
+       master: pci_t;
+       bar: int
+);
+
+/*
+ * Release io ports for BAR 0-5 for a given device.
+ * Only works on bars that correspond to IO ports.
+ */
+routine pci_free_io_ports(
+       master: pci_t;
+       bar: int
+);
diff --git a/pci-arbiter/netfs_impl.c b/pci-arbiter/netfs_impl.c
index b66f0019..1626a09b 100644
--- a/pci-arbiter/netfs_impl.c
+++ b/pci-arbiter/netfs_impl.c
@@ -583,6 +583,10 @@ get_filemap_region (struct node *node, vm_prot_t prot)
     strtol (&node->nn->ln->name[strlen (node->nn->ln->name) - 1], 0, 16);
   region = &node->nn->ln->device->regions[reg_num];
 
+  /* Skip IO regions, they are handled differently */
+  if (region->is_IO)
+    goto error;
+
   /* Ensure the region is mapped */
   err = device_map_region (node->nn->ln->device, region,
                           &node->nn->ln->region_maps[reg_num]);
diff --git a/pci-arbiter/pci-ops.c b/pci-arbiter/pci-ops.c
index 2f9f5296..402629e5 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 <sys/io.h>
 
 #include <pciaccess.h>
 #include "pcifs.h"
@@ -273,3 +274,69 @@ S_pci_get_dev_rom (struct protid * master, char **data, 
mach_msg_type_number_t *
 
   return 0;
 }
+
+error_t
+toggle_io_ports (struct pcifs_dirent *e, int bar, int turn_on)
+{
+  uint16_t iobase, iosize;
+
+  if ((bar < 0) || (bar > 5))
+    return EINVAL;
+
+  if (!e->device->regions[bar].is_IO)
+    /* This operation only works on IO bars */
+    return EINVAL;
+
+  iobase = e->device->regions[bar].base_addr;
+  iosize = e->device->regions[bar].size;
+
+  if (!ioperm(iobase, iobase + iosize - 1, turn_on))
+    return errno;
+
+  /* Update atime */
+  UPDATE_TIMES (e, TOUCH_ATIME);
+
+  return 0;
+}
+
+error_t
+S_pci_take_io_ports (struct protid * master, int bar)
+{
+  error_t err;
+  struct pcifs_dirent *e;
+
+  if (!master)
+    return EOPNOTSUPP;
+
+  e = master->po->np->nn->ln;
+  if (strncmp (e->name, FILE_CONFIG_NAME, NAME_SIZE))
+    /* This operation may only be addressed to the config file */
+    return EINVAL;
+
+  err = check_permissions (master, O_READ);
+  if (err)
+    return err;
+
+  return toggle_io_ports (e, bar, 1);
+}
+
+error_t
+S_pci_free_io_ports (struct protid * master, int bar)
+{
+  error_t err;
+  struct pcifs_dirent *e;
+
+  if (!master)
+    return EOPNOTSUPP;
+
+  e = master->po->np->nn->ln;
+  if (strncmp (e->name, FILE_CONFIG_NAME, NAME_SIZE))
+    /* This operation may only be addressed to the config file */
+    return EINVAL;
+
+  err = check_permissions (master, O_READ);
+  if (err)
+    return err;
+
+  return toggle_io_ports (e, bar, 0);
+}
-- 
2.40.1





reply via email to

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