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 a way to have the io ports which are attached to a particular pci device released when the pci device port is deallocated. --- hurd/pci.defs | 10 ++++++++ pci-arbiter/pci-ops.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/hurd/pci.defs b/hurd/pci.defs index e258f5ce..8542e602 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 BAR 0-5 for a given device. + * Only works on bars that correspond to IO ports. + */ +routine pci_request_io_ports( + master: pci_t; + bar: int; + out io_perm: mach_port_t +); diff --git a/pci-arbiter/pci-ops.c b/pci-arbiter/pci-ops.c index 2f9f5296..2762f140 100644 --- a/pci-arbiter/pci-ops.c +++ b/pci-arbiter/pci-ops.c @@ -24,6 +24,8 @@ #include <fcntl.h> #include <hurd/netfs.h> #include <sys/mman.h> +#include <sys/io.h> +#include <mach/machine/mach_i386.h> #include <pciaccess.h> #include "pcifs.h" @@ -273,3 +275,59 @@ 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, int bar, io_perm_t *io_perm) +{ + 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; + + 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 ((iobase & ~0xffff) || (iosize & ~0xffff)) + 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, int bar, 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_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 request_io_ports (e, bar, io_perm); +} -- 2.40.1