diff options
author | Damien Zammit <damien@zamaudio.com> | 2019-11-03 21:35:57 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2019-11-03 21:37:57 +0100 |
commit | b160d6f3b3cdcd6a293c33cd89dcc46ab54c3264 (patch) | |
tree | babcc0b5db069672277131e914beef6d6b4dddc5 /pci-arbiter | |
parent | 084e5a86e5eca77cec49e08e0d83fe8266eca91b (diff) | |
download | hurd-b160d6f3b3cdcd6a293c33cd89dcc46ab54c3264.tar.gz hurd-b160d6f3b3cdcd6a293c33cd89dcc46ab54c3264.tar.bz2 hurd-b160d6f3b3cdcd6a293c33cd89dcc46ab54c3264.zip |
pci-arbiter: Use libpciaccess instead of embedding it
This patch removes all embedded pciaccess code from the arbiter
and instead uses the external pciaccess library.
* pci-arbiter/Makefile:
* Remove pci_access.c and x86_pci.c from the sources.
* pci-arbiter/func_files.c:
* io_config_file: Use a harcoded PCI config size.
* read_rom_file:
Grab the full rom first, then return the
requested amount.
* pci-arbiter/main.c:
* main: Call create_fs_tree() w/o pci_sys.
Since it's not part of the translator anymore.
* pci-arbiter/netfs_impl.c:
* netfs_attempt_read:
Send pci_device_cfg_read() as the read op.
* netfs_attempt_write:
Send pci_device_cfg_write() as the write op.
* pci-arbiter/pci-ops.c:
* S_pci_conf_read: Call libpciaccess' pci_device_cfg_read().
* S_pci_conf_write: Call libpciaccess' pci_device_cfg_write().
* S_pci_get_dev_rom:
Set rom.base_addr to zero for the moment, until
libpciaccess esposes it properly.
* pci-arbiter/pci_access.c: Deleted
* pci-arbiter/pci_access.h: Deleted
* pci-arbiter/pcifs.c:
* create_fs_tree:
Remove the pci_sys parameter.
Use libpciaccess' iterator.
Use a hardcoded config space size.
* pci-arbiter/pcifs.h: Definitions for changes in pcifs.c.
* pci-arbiter/x86_pci.c: Deleted.
* pci-arbiter/x86_pci.h: Deleted.
Diffstat (limited to 'pci-arbiter')
-rw-r--r-- | pci-arbiter/Makefile | 4 | ||||
-rw-r--r-- | pci-arbiter/TODO | 9 | ||||
-rw-r--r-- | pci-arbiter/func_files.c | 34 | ||||
-rw-r--r-- | pci-arbiter/func_files.h | 4 | ||||
-rw-r--r-- | pci-arbiter/main.c | 6 | ||||
-rw-r--r-- | pci-arbiter/netfs_impl.c | 22 | ||||
-rw-r--r-- | pci-arbiter/pci-ops.c | 8 | ||||
-rw-r--r-- | pci-arbiter/pci_access.c | 51 | ||||
-rw-r--r-- | pci-arbiter/pci_access.h | 187 | ||||
-rw-r--r-- | pci-arbiter/pcifs.c | 24 | ||||
-rw-r--r-- | pci-arbiter/pcifs.h | 11 | ||||
-rw-r--r-- | pci-arbiter/x86_pci.c | 843 | ||||
-rw-r--r-- | pci-arbiter/x86_pci.h | 34 |
13 files changed, 68 insertions, 1169 deletions
diff --git a/pci-arbiter/Makefile b/pci-arbiter/Makefile index 357bb081..b13aefa8 100644 --- a/pci-arbiter/Makefile +++ b/pci-arbiter/Makefile @@ -20,14 +20,14 @@ makemode = server PORTDIR = $(srcdir)/port -SRCS = main.c pci-ops.c pci_access.c x86_pci.c netfs_impl.c \ +SRCS = main.c pci-ops.c netfs_impl.c \ pcifs.c ncache.c options.c func_files.c startup.c \ startup-ops.c MIGSRCS = pciServer.c startup_notifyServer.c OBJS = $(patsubst %.S,%.o,$(patsubst %.c,%.o, $(SRCS) $(MIGSRCS))) HURDLIBS= fshelp ports shouldbeinlibc netfs iohelp ihash -LDLIBS = -lpthread +LDLIBS = -lpthread -lpciaccess target = pci-arbiter diff --git a/pci-arbiter/TODO b/pci-arbiter/TODO index 22ae72a8..20060842 100644 --- a/pci-arbiter/TODO +++ b/pci-arbiter/TODO @@ -5,11 +5,10 @@ - pci_get_ndevs should be deprecated, applications shouldn't be relying on this -- we shouldn't duplicate pci_access.[ch] x86_pci.[ch] from libpciaccess, we - should get libpciaccess to expose pci_system_x86_create() to keep the - maintenance of x86 port knocking there. +- In pci-ops.c - config_block_op: + Update len with remaining allowed size once op() returns EIO + so that we get short reads/writes implemented by leaving it to pciaccess - At least one difference with libpciaccess is the refresh operation. Perhaps - we'd need to extend libpciaccess to fix that. +- Upstream hurdish access method + x86 fixes to libpciaccess BTW we could also support libpci. diff --git a/pci-arbiter/func_files.c b/pci-arbiter/func_files.c index 7df94d2f..c7da6978 100644 --- a/pci-arbiter/func_files.c +++ b/pci-arbiter/func_files.c @@ -35,10 +35,11 @@ config_block_op (struct pci_device *dev, off_t offset, size_t * len, { error_t err; size_t pendent = *len; + pciaddr_t actual = 0; while (pendent >= 4) { - err = op (dev->bus, dev->dev, dev->func, offset, data, 4); + err = op (dev, data, offset, 4, &actual); if (err) return err; @@ -49,7 +50,7 @@ config_block_op (struct pci_device *dev, off_t offset, size_t * len, if (pendent >= 2) { - err = op (dev->bus, dev->dev, dev->func, offset, data, 2); + err = op (dev, data, offset, 2, &actual); if (err) return err; @@ -60,7 +61,7 @@ config_block_op (struct pci_device *dev, off_t offset, size_t * len, if (pendent) { - err = op (dev->bus, dev->dev, dev->func, offset, data, 1); + err = op (dev, data, offset, 1, &actual); if (err) return err; @@ -85,10 +86,10 @@ io_config_file (struct pci_device * dev, off_t offset, size_t * len, assert_backtrace (dev != 0); /* Don't exceed the config space size */ - if (offset > dev->config_size) + if (offset > PCI_CONFIG_SIZE) return EINVAL; - if ((offset + *len) > dev->config_size) - *len = dev->config_size - offset; + if ((offset + *len) > PCI_CONFIG_SIZE) + *len = PCI_CONFIG_SIZE - offset; pthread_mutex_lock (&fs->pci_conf_lock); err = config_block_op (dev, offset, len, data, op); @@ -102,24 +103,25 @@ error_t read_rom_file (struct pci_device * dev, off_t offset, size_t * len, void *data) { - error_t err; + void *fullrom; /* This should never happen */ assert_backtrace (dev != 0); - /* Refresh the ROM */ - err = pci_sys->device_refresh (dev, -1, 1); - if (err) - return err; - /* Don't exceed the ROM size */ if (offset > dev->rom_size) return EINVAL; if ((offset + *len) > dev->rom_size) *len = dev->rom_size - offset; - memcpy (data, dev->rom_memory + offset, *len); + /* Grab the full rom first */ + fullrom = calloc(1, dev->rom_size); + pci_device_read_rom(dev, fullrom); + + /* Return the requested amount */ + memcpy (data, fullrom + offset, *len); + free(fullrom); return 0; } @@ -177,7 +179,6 @@ error_t io_region_file (struct pcifs_dirent * e, off_t offset, size_t * len, void *data, int read) { - error_t err; size_t reg_num; struct pci_mem_region *region; @@ -188,11 +189,6 @@ io_region_file (struct pcifs_dirent * e, off_t offset, size_t * len, reg_num = strtol (&e->name[strlen (e->name) - 1], 0, 16); region = &e->device->regions[reg_num]; - /* Refresh the region */ - err = pci_sys->device_refresh (e->device, reg_num, -1); - if (err) - return err; - /* Don't exceed the region size */ if (offset > region->size) return EINVAL; diff --git a/pci-arbiter/func_files.h b/pci-arbiter/func_files.h index b65d2c57..03cafee1 100644 --- a/pci-arbiter/func_files.h +++ b/pci-arbiter/func_files.h @@ -23,6 +23,10 @@ #define FUNC_FILES_H #include "pcifs.h" +#include <pciaccess.h> + +typedef int (*pci_io_op_t) (struct pci_device *dev, void *data, + pciaddr_t reg, pciaddr_t width, pciaddr_t *bytes); /* Config */ #define FILE_CONFIG_NAME "config" diff --git a/pci-arbiter/main.c b/pci-arbiter/main.c index bc085274..112cd98b 100644 --- a/pci-arbiter/main.c +++ b/pci-arbiter/main.c @@ -34,7 +34,7 @@ #include "libnetfs/fsys_S.h" #include "libports/interrupt_S.h" #include "libnetfs/ifsock_S.h" -#include "pci_access.h" +#include <pciaccess.h> #include "pcifs.h" #include "startup.h" @@ -85,7 +85,7 @@ main (int argc, char **argv) if (err) error (1, err, "mapping time"); - /* Start the PCI system */ + /* Start the PCI system: NB: pciaccess will choose x86 first and take lock */ err = pci_system_init (); if (err) error (1, err, "Starting the PCI system"); @@ -96,7 +96,7 @@ main (int argc, char **argv) error (1, err, "Creating the PCI filesystem"); /* Create the filesystem tree */ - err = create_fs_tree (fs, pci_sys); + err = create_fs_tree (fs); if (err) error (1, err, "Creating the PCI filesystem tree"); diff --git a/pci-arbiter/netfs_impl.c b/pci-arbiter/netfs_impl.c index b96c7d8d..0be8c370 100644 --- a/pci-arbiter/netfs_impl.c +++ b/pci-arbiter/netfs_impl.c @@ -32,7 +32,7 @@ #include "pcifs.h" #include "ncache.h" -#include "pci_access.h" +#include <pciaccess.h> #include "func_files.h" #define DIRENTS_CHUNK_SIZE (8*1024) @@ -499,11 +499,11 @@ netfs_attempt_read (struct iouser * cred, struct node * node, if (!strncmp (node->nn->ln->name, FILE_CONFIG_NAME, NAME_SIZE)) { err = - io_config_file (node->nn->ln->device, offset, len, data, - pci_sys->read); + io_config_file (node->nn->ln->device, offset, len, data, + pci_device_cfg_read); if (!err) - /* Update atime */ - UPDATE_TIMES (node->nn->ln, TOUCH_ATIME); + /* Update atime */ + UPDATE_TIMES (node->nn->ln, TOUCH_ATIME); } else if (!strncmp (node->nn->ln->name, FILE_ROM_NAME, NAME_SIZE)) { @@ -538,13 +538,13 @@ netfs_attempt_write (struct iouser * cred, struct node * node, if (!strncmp (node->nn->ln->name, FILE_CONFIG_NAME, NAME_SIZE)) { err = - io_config_file (node->nn->ln->device, offset, len, data, - pci_sys->write); + io_config_file (node->nn->ln->device, offset, len, data, + pci_device_cfg_write); if (!err) - { - /* Update mtime and ctime */ - UPDATE_TIMES (node->nn->ln, TOUCH_MTIME | TOUCH_CTIME); - } + { + /* Update mtime and ctime */ + UPDATE_TIMES (node->nn->ln, TOUCH_MTIME | TOUCH_CTIME); + } } else if (!strncmp (node->nn->ln->name, FILE_REGION_NAME, strlen (FILE_REGION_NAME))) diff --git a/pci-arbiter/pci-ops.c b/pci-arbiter/pci-ops.c index 328db5b2..8279540a 100644 --- a/pci-arbiter/pci-ops.c +++ b/pci-arbiter/pci-ops.c @@ -25,7 +25,7 @@ #include <hurd/netfs.h> #include <sys/mman.h> -#include "pci_access.h" +#include <pciaccess.h> #include "pcifs.h" #include "func_files.h" @@ -112,7 +112,7 @@ S_pci_conf_read (struct protid * master, int reg, char **data, * libnetfs which is multi-threaded. A lock is needed for arbitration. */ pthread_mutex_lock (lock); - err = pci_sys->read (e->bus, e->dev, e->func, reg, *data, amount); + err = pci_device_cfg_read (e->device, *data, reg, amount, NULL); pthread_mutex_unlock (lock); if (!err) @@ -149,7 +149,7 @@ S_pci_conf_write (struct protid * master, int reg, char *data, size_t datalen, return err; pthread_mutex_lock (lock); - err = pci_sys->write (e->bus, e->dev, e->func, reg, data, datalen); + err = pci_device_cfg_write (e->device, data, reg, datalen, NULL); pthread_mutex_unlock (lock); if (!err) @@ -260,7 +260,7 @@ S_pci_get_dev_rom (struct protid * master, char **data, size_t * datalen) } /* Copy the regions info */ - rom.base_addr = e->device->rom_base; + rom.base_addr = 0; // pci_device_private only rom.size = e->device->rom_size; memcpy (*data, &rom, size); diff --git a/pci-arbiter/pci_access.c b/pci-arbiter/pci_access.c deleted file mode 100644 index 4d7fc68f..00000000 --- a/pci-arbiter/pci_access.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * (C) Copyright IBM Corporation 2006 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * PCI access general header. - * - * Following code is borrowed from libpciaccess: - * https://cgit.freedesktop.org/xorg/lib/libpciaccess/ - */ - -#include "pci_access.h" - -#include <errno.h> - -#include "x86_pci.h" - -/* Configure PCI parameters */ -int -pci_system_init (void) -{ - int err = ENOSYS; - -#ifdef __GNU__ - err = pci_system_x86_create (); -#else -#error "Unsupported OS" -#endif - - return err; -} diff --git a/pci-arbiter/pci_access.h b/pci-arbiter/pci_access.h deleted file mode 100644 index cf42cf62..00000000 --- a/pci-arbiter/pci_access.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * (C) Copyright IBM Corporation 2006 - * Copyright 2009 Red Hat, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -/* - * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/* - * PCI access general header. - * - * Following code is borrowed from libpciaccess: - * https://cgit.freedesktop.org/xorg/lib/libpciaccess/ - */ - -#ifndef PCI_ACCESS_H -#define PCI_ACCESS_H - -#include <stddef.h> -#include <stdint.h> -#include <errno.h> - -typedef uint64_t pciaddr_t; - -/* - * BAR descriptor for a PCI device. - */ -struct pci_mem_region -{ - /* - * When the region is mapped, this is the pointer to the memory. - */ - void *memory; - - /* - * Base physical address of the region from the CPU's point of view. - * - * This address is typically passed to \c pci_device_map_range to create - * a mapping of the region to the CPU's virtual address space. - */ - pciaddr_t base_addr; - - - /* - * Size, in bytes, of the region. - */ - pciaddr_t size; - - - /* - * Is the region I/O ports or memory? - */ - unsigned is_IO:1; - - /* - * Is the memory region prefetchable? - * - * \note - * This can only be set if \c is_IO is not set. - */ - unsigned is_prefetchable:1; - - - /* - * Is the memory at a 64-bit address? - * - * \note - * This can only be set if \c is_IO is not set. - */ - unsigned is_64:1; -}; - -/* - * PCI device. - * - * Contains all of the information about a particular PCI device. - */ -struct pci_device -{ - /* - * Complete bus identification, including domain, of the device. On - * platforms that do not support PCI domains (e.g., 32-bit x86 hardware), - * the domain will always be zero. - */ - uint16_t domain; - uint8_t bus; - uint8_t dev; - uint8_t func; - - /* - * Device's class, subclass, and programming interface packed into a - * single 32-bit value. The class is at bits [23:16], subclass is at - * bits [15:8], and programming interface is at [7:0]. - */ - uint32_t device_class; - - /* - * BAR descriptors for the device. - */ - struct pci_mem_region regions[6]; - - /* - * Size, in bytes, of the device's expansion ROM. - */ - pciaddr_t rom_size; - - /* - * Physical address of the ROM - */ - pciaddr_t rom_base; - - /* - * Mapped ROM - */ - void *rom_memory; - - /* - * Size of the configuration space - */ - size_t config_size; -}; - -typedef error_t (*pci_io_op_t) (unsigned bus, unsigned dev, unsigned func, - pciaddr_t reg, void *data, unsigned size); - -typedef error_t (*pci_refresh_dev_op_t) (struct pci_device * dev, - int num_region, int rom); - -/* Global PCI data */ -struct pci_system -{ - size_t num_devices; - struct pci_device *devices; - - /* Callbacks */ - pci_io_op_t read; - pci_io_op_t write; - pci_refresh_dev_op_t device_refresh; -}; - -struct pci_system *pci_sys; - -int pci_system_init (void); - -#endif /* PCI_ACCESS_H */ diff --git a/pci-arbiter/pcifs.c b/pci-arbiter/pcifs.c index 3bf255bc..cc08fad0 100644 --- a/pci-arbiter/pcifs.c +++ b/pci-arbiter/pcifs.c @@ -134,7 +134,7 @@ init_file_system (file_t underlying_node, struct pcifs * fs) } error_t -create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) +create_fs_tree (struct pcifs * fs) { error_t err = 0; int c_domain, c_bus, c_dev, i, j; @@ -144,11 +144,17 @@ create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) *func_parent, *list; struct stat e_stat; char entry_name[NAME_SIZE]; + const struct pci_slot_match match = + { PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0 }; + /* domain bus device func */ + struct pci_device_iterator *iter; nentries = 1; /* Skip root entry */ c_domain = c_bus = c_dev = -1; - for (i = 0, device = pci_sys->devices; i < pci_sys->num_devices; - i++, device++) + iter = pci_slot_match_iterator_create(&match); + device = pci_device_next(iter); + + for (i = 0; device != NULL; i++, device = pci_device_next(iter) ) { if (device->domain != c_domain) { @@ -181,6 +187,8 @@ create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) nentries++; /* + rom */ } + pci_iterator_destroy(iter); + list = realloc (fs->entries, nentries * sizeof (struct pcifs_dirent)); if (!list) return ENOMEM; @@ -189,8 +197,10 @@ create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) memset (e, 0, sizeof (struct pcifs_dirent)); c_domain = c_bus = c_dev = -1; domain_parent = bus_parent = dev_parent = func_parent = 0; - for (i = 0, device = pci_sys->devices; i < pci_sys->num_devices; - i++, device++) + iter = pci_slot_match_iterator_create(&match); + device = pci_device_next(iter); + + for (i = 0; device != NULL; i++, device = pci_device_next(iter)) { if (device->domain != c_domain) { @@ -268,7 +278,7 @@ create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) e_stat = func_parent->stat; e_stat.st_mode &= ~(S_IFDIR | S_IXUSR | S_IXGRP); e_stat.st_mode |= S_IFREG | S_IWUSR | S_IWGRP; - e_stat.st_size = device->config_size; + e_stat.st_size = PCI_CONFIG_SIZE; // FIXME: Hardcoded /* Create config entry */ strncpy (entry_name, FILE_CONFIG_NAME, NAME_SIZE - 1); @@ -312,6 +322,8 @@ create_fs_tree (struct pcifs * fs, struct pci_system * pci_sys) } } + pci_iterator_destroy(iter); + /* The root node points to the first element of the entry list */ fs->entries = list; fs->num_entries = nentries; diff --git a/pci-arbiter/pcifs.h b/pci-arbiter/pcifs.h index 7a35c77d..deb57b06 100644 --- a/pci-arbiter/pcifs.h +++ b/pci-arbiter/pcifs.h @@ -27,8 +27,11 @@ #include <pthread.h> #include <maptime.h> -#include "pci_access.h" -#include "netfs_impl.h" +#include <pciaccess.h> +// FIXME: Hardcoded PCI config size +#define PCI_CONFIG_SIZE 256 + +#include <netfs_impl.h> /* Size of a directory entry name */ #ifndef NAME_SIZE @@ -200,9 +203,9 @@ volatile struct mapped_time_value *pcifs_maptime; /* FS manipulation functions */ error_t alloc_file_system (struct pcifs **fs); error_t init_file_system (file_t underlying_node, struct pcifs *fs); -error_t create_fs_tree (struct pcifs *fs, struct pci_system *pci_sys); +error_t create_fs_tree (struct pcifs *fs); error_t fs_set_permissions (struct pcifs *fs); error_t entry_check_perms (struct iouser *user, struct pcifs_dirent *e, - int flags); + int flags); #endif /* PCIFS_H */ diff --git a/pci-arbiter/x86_pci.c b/pci-arbiter/x86_pci.c deleted file mode 100644 index 9cf1f54a..00000000 --- a/pci-arbiter/x86_pci.c +++ /dev/null @@ -1,843 +0,0 @@ -/* - * Copyright (c) 2017 Joan Lledó - * Copyright (c) 2009, 2012, 2018 Samuel Thibault - * Heavily inspired from the freebsd, netbsd, and openbsd backends - * (C) Copyright Eric Anholt 2006 - * (C) Copyright IBM Corporation 2006 - * Copyright (c) 2008 Juan Romero Pardines - * Copyright (c) 2008 Mark Kettenis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * PCI backend for x86 (32 and 64 bit) architectures. - * - * Following code is borrowed from libpciaccess: - * https://cgit.freedesktop.org/xorg/lib/libpciaccess/ - */ - -#include "x86_pci.h" - -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/io.h> -#include <string.h> - -#include "pci_access.h" - -#define PCI_VENDOR(reg) ((reg) & 0xFFFF) -#define PCI_VENDOR_INVALID 0xFFFF - -#define PCI_VENDOR_ID 0x00 -#define PCI_VENDOR_ID_COMPAQ 0x0e11 -#define PCI_VENDOR_ID_INTEL 0x8086 - -#define PCI_CLASS 0x08 -#define PCI_CLASS_DEVICE 0x0a -#define PCI_CLASS_DISPLAY_VGA 0x0300 -#define PCI_CLASS_BRIDGE_HOST 0x0600 - -#define PCI_BAR_ADDR_0 0x10 -#define PCI_XROMBAR_ADDR_00 0x30 -#define PCI_XROMBAR_ADDR_01 0x38 - -#define PCI_HDRTYPE 0x0E -#define PCI_HDRTYPE_DEVICE 0x00 -#define PCI_HDRTYPE_BRIDGE 0x01 -#define PCI_HDRTYPE_CARDBUS 0x02 - -#define PCI_COMMAND 0x04 -#define PCI_SECONDARY_BUS 0x19 - -#define PCI_CONFIG_SIZE 256 - -static error_t -x86_enable_io (void) -{ - if (!ioperm (0, 0xffff, 1)) - return 0; - return errno; -} - -static error_t -x86_disable_io (void) -{ - if (!ioperm (0, 0xffff, 0)) - return 0; - return errno; -} - -static error_t -pci_system_x86_conf1_probe (void) -{ - unsigned long sav; - int res = ENODEV; - - outb (0x01, 0xCFB); - sav = inl (0xCF8); - outl (0x80000000, 0xCF8); - if (inl (0xCF8) == 0x80000000) - res = 0; - outl (sav, 0xCF8); - - return res; -} - -static error_t -pci_system_x86_conf1_read (unsigned bus, unsigned dev, unsigned func, - pciaddr_t reg, void *data, unsigned size) -{ - unsigned addr = 0xCFC + (reg & 3); - unsigned long sav; - error_t ret = 0; - - if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 - || size == 3) - return EIO; - - sav = inl (0xCF8); - outl (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), - 0xCF8); - /* NOTE: x86 is already LE */ - switch (size) - { - case 1: - { - uint8_t *val = data; - *val = inb (addr); - break; - } - case 2: - { - uint16_t *val = data; - *val = inw (addr); - break; - } - case 4: - { - uint32_t *val = data; - *val = inl (addr); - break; - } - } - outl (sav, 0xCF8); - - return ret; -} - -static error_t -pci_system_x86_conf1_write (unsigned bus, unsigned dev, unsigned func, - pciaddr_t reg, void *data, unsigned size) -{ - unsigned addr = 0xCFC + (reg & 3); - unsigned long sav; - error_t ret = 0; - - if (bus >= 0x100 || dev >= 32 || func >= 8 || reg >= 0x100 || size > 4 - || size == 3) - return EIO; - - sav = inl (0xCF8); - outl (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3), - 0xCF8); - /* NOTE: x86 is already LE */ - switch (size) - { - case 1: - { - const uint8_t *val = data; - outb (*val, addr); - break; - } - case 2: - { - const uint16_t *val = data; - outw (*val, addr); - break; - } - case 4: - { - const uint32_t *val = data; - outl (*val, addr); - break; - } - } - outl (sav, 0xCF8); - - return ret; -} - -static error_t -pci_system_x86_conf2_probe (void) -{ - outb (0, 0xCFB); - outb (0, 0xCF8); - outb (0, 0xCFA); - if (inb (0xCF8) == 0 && inb (0xCFA) == 0) - return 0; - - return ENODEV; -} - -static error_t -pci_system_x86_conf2_read (unsigned bus, unsigned dev, unsigned func, - pciaddr_t reg, void *data, unsigned size) -{ - unsigned addr = 0xC000 | dev << 8 | reg; - error_t ret = 0; - - if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100) - return EIO; - - outb ((func << 1) | 0xF0, 0xCF8); - outb (bus, 0xCFA); - /* NOTE: x86 is already LE */ - switch (size) - { - case 1: - { - uint8_t *val = data; - *val = inb (addr); - break; - } - case 2: - { - uint16_t *val = data; - *val = inw (addr); - break; - } - case 4: - { - uint32_t *val = data; - *val = inl (addr); - break; - } - default: - ret = EIO; - break; - } - outb (0, 0xCF8); - - return ret; -} - -static error_t -pci_system_x86_conf2_write (unsigned bus, unsigned dev, unsigned func, - pciaddr_t reg, void *data, unsigned size) -{ - unsigned addr = 0xC000 | dev << 8 | reg; - error_t ret = 0; - - if (bus >= 0x100 || dev >= 16 || func >= 8 || reg >= 0x100) - return EIO; - - outb ((func << 1) | 0xF0, 0xCF8); - outb (bus, 0xCFA); - /* NOTE: x86 is already LE */ - switch (size) - { - case 1: - { - const uint8_t *val = data; - outb (*val, addr); - break; - } - case 2: - { - const uint16_t *val = data; - outw (*val, addr); - break; - } - case 4: - { - const uint32_t *val = data; - outl (*val, addr); - break; - } - default: - ret = EIO; - break; - } - outb (0, 0xCF8); - - return ret; -} - -/* Returns the number of regions (base address registers) the device has */ -static int -pci_device_x86_get_num_regions (uint8_t header_type) -{ - switch (header_type & 0x7f) - { - case 0: - return 6; - case 1: - return 2; - case 2: - return 1; - default: - return 0; - } -} - -/* Masks out the flag bigs of the base address register value */ -static uint32_t -get_map_base (uint32_t val) -{ - if (val & 0x01) - return val & ~0x03; - else - return val & ~0x0f; -} - -/* Returns the size of a region based on the all-ones test value */ -static unsigned -get_test_val_size (uint32_t testval) -{ - unsigned size = 1; - - if (testval == 0) - return 0; - - /* Mask out the flag bits */ - testval = get_map_base (testval); - if (!testval) - return 0; - - while ((testval & 1) == 0) - { - size <<= 1; - testval >>= 1; - } - - return size; -} - -/* Read BAR `reg_num' in `dev' and map the data if any */ -static error_t -pci_device_x86_region_probe (struct pci_device *dev, int reg_num) -{ - error_t err; - uint8_t offset; - uint32_t reg, addr, testval; - int memfd; - - offset = PCI_BAR_ADDR_0 + 0x4 * reg_num; - - /* Get the base address */ - err = - pci_sys->read (dev->bus, dev->dev, dev->func, offset, &addr, - sizeof (addr)); - if (err) - return err; - - /* Test write all ones to the register, then restore it. */ - reg = 0xffffffff; - err = pci_sys->write (dev->bus, dev->dev, dev->func, offset, ®, - sizeof (reg)); - if (err) - return err; - err = pci_sys->read (dev->bus, dev->dev, dev->func, offset, &testval, - sizeof (testval)); - if (err) - return err; - err = pci_sys->write (dev->bus, dev->dev, dev->func, offset, &addr, - sizeof (addr)); - if (err) - return err; - - if (addr & 0x01) - dev->regions[reg_num].is_IO = 1; - if (addr & 0x04) - dev->regions[reg_num].is_64 = 1; - if (addr & 0x08) - dev->regions[reg_num].is_prefetchable = 1; - - /* Set the size */ - dev->regions[reg_num].size = get_test_val_size (testval); - - /* Set the base address value */ - dev->regions[reg_num].base_addr = get_map_base (addr); - - if (dev->regions[reg_num].is_64) - { - err = - pci_sys->read (dev->bus, dev->dev, dev->func, offset + 4, &addr, - sizeof (addr)); - if (err) - return err; - - dev->regions[reg_num].base_addr |= ((uint64_t) addr << 32); - } - - if (dev->regions[reg_num].is_IO) - { - /* Enable the I/O Space bit */ - err = - pci_sys->read (dev->bus, dev->dev, dev->func, PCI_COMMAND, ®, - sizeof (reg)); - if (err) - return err; - - if (!(reg & 0x1)) - { - reg |= 0x1; - - err = - pci_sys->write (dev->bus, dev->dev, dev->func, PCI_COMMAND, - ®, sizeof (reg)); - if (err) - return err; - } - - /* Clear the map pointer */ - dev->regions[reg_num].memory = 0; - } - else if (dev->regions[reg_num].size > 0) - { - /* Enable the Memory Space bit */ - err = - pci_sys->read (dev->bus, dev->dev, dev->func, PCI_COMMAND, ®, - sizeof (reg)); - if (err) - return err; - - if (!(reg & 0x2)) - { - reg |= 0x2; - - err = - pci_sys->write (dev->bus, dev->dev, dev->func, PCI_COMMAND, - ®, sizeof (reg)); - if (err) - return err; - } - - /* Map the region in our space */ - memfd = open ("/dev/mem", O_RDONLY | O_CLOEXEC); - if (memfd == -1) - return errno; - - dev->regions[reg_num].memory = - mmap (NULL, dev->regions[reg_num].size, PROT_READ | PROT_WRITE, 0, - memfd, dev->regions[reg_num].base_addr); - if (dev->regions[reg_num].memory == MAP_FAILED) - { - dev->regions[reg_num].memory = 0; - close (memfd); - return errno; - } - - close (memfd); - } - - return 0; -} - -/* Read the XROMBAR in `dev' and map the data if any */ -static error_t -pci_device_x86_rom_probe (struct pci_device *dev) -{ - error_t err; - uint8_t reg_8, xrombar_addr; - uint32_t reg, reg_back; - pciaddr_t rom_size; - pciaddr_t rom_base; - void *rom_mapped; - int memfd; - - /* First we need to know which type of header is this */ - err = pci_sys->read (dev->bus, dev->dev, dev->func, PCI_HDRTYPE, ®_8, - sizeof (reg_8)); - if (err) - return err; - - /* Get the XROMBAR register address */ - switch (reg_8 & 0x3) - { - case PCI_HDRTYPE_DEVICE: - xrombar_addr = PCI_XROMBAR_ADDR_00; - break; - case PCI_HDRTYPE_BRIDGE: - xrombar_addr = PCI_XROMBAR_ADDR_01; - break; - default: - return -1; - } - - /* Get size and physical address */ - err = pci_sys->read (dev->bus, dev->dev, dev->func, xrombar_addr, ®, - sizeof (reg)); - if (err) - return err; - - reg_back = reg; - reg = 0xFFFFF800; /* Base address: first 21 bytes */ - err = pci_sys->write (dev->bus, dev->dev, dev->func, xrombar_addr, ®, - sizeof (reg)); - if (err) - return err; - err = pci_sys->read (dev->bus, dev->dev, dev->func, xrombar_addr, ®, - sizeof (reg)); - if (err) - return err; - - rom_size = (~reg + 1); - rom_base = reg_back & reg; - - if (rom_size == 0) - return 0; - - /* Enable the address decoder and write the physical address back */ - reg_back |= 0x1; - err = pci_sys->write - (dev->bus, dev->dev, dev->func, xrombar_addr, ®_back, - sizeof (reg_back)); - if (err) - return err; - - /* Enable the Memory Space bit */ - err = pci_sys->read (dev->bus, dev->dev, dev->func, PCI_COMMAND, ®, - sizeof (reg)); - if (err) - return err; - - if (!(reg & 0x2)) - { - reg |= 0x2; - - err = - pci_sys->write (dev->bus, dev->dev, dev->func, PCI_COMMAND, ®, - sizeof (reg)); - if (err) - return err; - } - - /* Map the ROM in our space */ - memfd = open ("/dev/mem", O_RDONLY | O_CLOEXEC); - if (memfd == -1) - return errno; - - rom_mapped = mmap (NULL, rom_size, PROT_READ, 0, memfd, rom_base); - if (rom_mapped == MAP_FAILED) - { - close (memfd); - return errno; - } - - close (memfd); - - dev->rom_size = rom_size; - dev->rom_base = rom_base; - dev->rom_memory = rom_mapped; - - return 0; -} - -/* Configure BARs and ROM */ -static error_t -pci_device_x86_probe (struct pci_device *dev) -{ - error_t err; - uint8_t hdrtype; - int i; - - /* Probe BARs */ - err = pci_sys->read (dev->bus, dev->dev, dev->func, PCI_HDRTYPE, &hdrtype, - sizeof (hdrtype)); - if (err) - return err; - - for (i = 0; i < pci_device_x86_get_num_regions (hdrtype); i++) - { - err = pci_device_x86_region_probe (dev, i); - if (err) - return err; - - if (dev->regions[i].is_64) - /* Move the pointer one BAR ahead */ - i++; - } - - /* Probe ROM */ - err = pci_device_x86_rom_probe (dev); - if (err) - return err; - - return 0; -} - -/* - * Refresh the device. Check for updates in region `reg_num' - * or in ROM if `rom' = true. `reg_num' < 0 means no region check. - */ -static error_t -pci_device_x86_refresh (struct pci_device *dev, int reg_num, int rom) -{ - error_t err; - uint8_t offset, hdrtype; - uint32_t addr; - - if (reg_num >= 0 && dev->regions[reg_num].size > 0) - { - /* Read the BAR */ - offset = PCI_BAR_ADDR_0 + 0x4 * reg_num; - err = - pci_sys->read (dev->bus, dev->dev, dev->func, offset, &addr, - sizeof (addr)); - if (err) - return err; - - /* Check whether the region is outdated, if so, the refresh it */ - if (dev->regions[reg_num].base_addr != get_map_base (addr)) - { - err = pci_device_x86_region_probe (dev, reg_num); - if (err) - return err; - } - } - - if (rom && dev->rom_size > 0) - { - /* Read the BAR */ - err = - pci_sys->read (dev->bus, dev->dev, dev->func, PCI_HDRTYPE, &hdrtype, - sizeof (hdrtype)); - if (err) - return err; - - switch (hdrtype & 0x3) - { - case PCI_HDRTYPE_DEVICE: - offset = PCI_XROMBAR_ADDR_00; - break; - case PCI_HDRTYPE_BRIDGE: - offset = PCI_XROMBAR_ADDR_01; - break; - default: - return -1; - } - - err = pci_sys->read (dev->bus, dev->dev, dev->func, offset, &addr, - sizeof (addr)); - if (err) - return err; - - /* Check whether the ROM is outdated, if so, the refresh it */ - if (dev->rom_base != (addr & 0xFFFFF800)) - { - err = pci_device_x86_rom_probe (dev); - if (err) - return err; - } - } - - return 0; -} - -/* Check that this really looks like a PCI configuration. */ -static error_t -pci_system_x86_check (struct pci_system *pci_sys) -{ - int dev; - uint16_t class, vendor; - - /* Look on bus 0 for a device that is a host bridge, a VGA card, - * or an intel or compaq device. */ - - for (dev = 0; dev < 32; dev++) - { - if (pci_sys->read (0, dev, 0, PCI_CLASS_DEVICE, &class, sizeof (class))) - continue; - if (class == PCI_CLASS_BRIDGE_HOST || class == PCI_CLASS_DISPLAY_VGA) - return 0; - if (pci_sys->read (0, dev, 0, PCI_VENDOR_ID, &vendor, sizeof (vendor))) - continue; - if (vendor == PCI_VENDOR_ID_INTEL || class == PCI_VENDOR_ID_COMPAQ) - return 0; - } - - return ENODEV; -} - -/* Find out which conf access method use */ -static error_t -pci_probe (struct pci_system *pci_sys) -{ - if (pci_system_x86_conf1_probe () == 0) - { - pci_sys->read = pci_system_x86_conf1_read; - pci_sys->write = pci_system_x86_conf1_write; - if (pci_system_x86_check (pci_sys) == 0) - return 0; - } - - if (pci_system_x86_conf2_probe () == 0) - { - pci_sys->read = pci_system_x86_conf2_read; - pci_sys->write = pci_system_x86_conf2_write; - if (pci_system_x86_check (pci_sys) == 0) - return 0; - } - - return ENODEV; -} - -static error_t -pci_nfuncs (struct pci_system *pci_sys, int bus, int dev, uint8_t * nfuncs) -{ - uint8_t hdrtype; - error_t err; - - err = pci_sys->read (bus, dev, 0, PCI_HDRTYPE, &hdrtype, sizeof (hdrtype)); - if (err) - return err; - - *nfuncs = hdrtype & 0x80 ? 8 : 1; - - return 0; -} - -/* Recursively scan bus number `bus' */ -static error_t -pci_system_x86_scan_bus (struct pci_system *pci_sys, uint8_t bus) -{ - error_t err; - uint8_t dev, func, nfuncs, hdrtype, secbus; - uint32_t reg; - struct pci_device *d, *devices; - - for (dev = 0; dev < 32; dev++) - { - err = pci_nfuncs (pci_sys, bus, dev, &nfuncs); - if (err) - return err; - - for (func = 0; func < nfuncs; func++) - { - err = - pci_sys->read (bus, dev, func, PCI_VENDOR_ID, ®, sizeof (reg)); - if (err) - return err; - - if (PCI_VENDOR (reg) == PCI_VENDOR_INVALID || PCI_VENDOR (reg) == 0) - continue; - - err = pci_sys->read (bus, dev, func, PCI_CLASS, ®, sizeof (reg)); - if (err) - return err; - - err = - pci_sys->read (bus, dev, func, PCI_HDRTYPE, &hdrtype, - sizeof (hdrtype)); - if (err) - return err; - - devices = - realloc (pci_sys->devices, - (pci_sys->num_devices + 1) * sizeof (struct pci_device)); - if (!devices) - return ENOMEM; - - d = devices + pci_sys->num_devices; - memset (d, 0, sizeof (struct pci_device)); - - /* Fixed values as PCI express is still not supported */ - d->domain = 0; - d->config_size = PCI_CONFIG_SIZE; - - d->bus = bus; - d->dev = dev; - d->func = func; - - d->device_class = reg >> 8; - - err = pci_device_x86_probe (d); - if (err) - return err; - - pci_sys->devices = devices; - pci_sys->num_devices++; - - switch (hdrtype & 0x3) - { - case PCI_HDRTYPE_DEVICE: - break; - case PCI_HDRTYPE_BRIDGE: - case PCI_HDRTYPE_CARDBUS: - { - err = - pci_sys->read (bus, dev, func, PCI_SECONDARY_BUS, &secbus, - sizeof (secbus)); - if (err) - return err; - - err = pci_system_x86_scan_bus (pci_sys, secbus); - if (err) - return err; - - break; - } - default: - /* Unknown header, do nothing */ - break; - } - } - } - - return 0; -} - -/* Initialize the x86 module */ -error_t -pci_system_x86_create (void) -{ - error_t err; - - err = x86_enable_io (); - if (err) - return err; - - pci_sys = calloc (1, sizeof (struct pci_system)); - if (pci_sys == NULL) - { - x86_disable_io (); - return ENOMEM; - } - - err = pci_probe (pci_sys); - if (err) - { - x86_disable_io (); - free (pci_sys); - return err; - } - pci_sys->device_refresh = pci_device_x86_refresh; - - /* Recursive scan */ - pci_sys->num_devices = 0; - err = pci_system_x86_scan_bus (pci_sys, 0); - if (err) - { - x86_disable_io (); - free (pci_sys); - pci_sys = NULL; - return err; - } - - return 0; -} diff --git a/pci-arbiter/x86_pci.h b/pci-arbiter/x86_pci.h deleted file mode 100644 index fb2374a6..00000000 --- a/pci-arbiter/x86_pci.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2009, 2012 Samuel Thibault - * Heavily inspired from the freebsd, netbsd, and openbsd backends - * (C) Copyright Eric Anholt 2006 - * (C) Copyright IBM Corporation 2006 - * Copyright (c) 2008 Juan Romero Pardines - * Copyright (c) 2008 Mark Kettenis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * PCI backend header for x86 (32 and 64 bit) architectures. - * - * Following code is borrowed from libpciaccess: - * https://cgit.freedesktop.org/xorg/lib/libpciaccess/ - */ - -#ifndef X86_PCI_H -#define X86_PCI_H - -int pci_system_x86_create (void); - -#endif /* X86_PCI_H */ |