--- pci-arbiter/Makefile | 7 +- pci-arbiter/main.c | 140 ++++++++++++++++++++++++++++++++++++-- pci-arbiter/netfs_impl.c | 39 +++++++---- pci-arbiter/options.c | 19 ++++++ pci-arbiter/options.h | 8 +++ pci-arbiter/pci-ops.c | 6 +- pci-arbiter/pcifs.c | 18 +++-- pci-arbiter/pcifs.h | 3 + pci-arbiter/startup-ops.c | 2 + 9 files changed, 207 insertions(+), 35 deletions(-)
diff --git a/pci-arbiter/Makefile b/pci-arbiter/Makefile index 1d0309dc..3f374d18 100644 --- a/pci-arbiter/Makefile +++ b/pci-arbiter/Makefile @@ -22,11 +22,10 @@ PORTDIR = $(srcdir)/port 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))) + startup-ops.c pciServer.c startup_notifyServer.c +OBJS = $(SRCS:.c=.o) $(MIGSTUBS) -HURDLIBS= fshelp ports shouldbeinlibc netfs iohelp ihash +HURDLIBS= fshelp ports shouldbeinlibc netfs iohelp ihash trivfs machdev LDLIBS = -lpthread $(libpciaccess_LIBS) target = pci-arbiter diff --git a/pci-arbiter/main.c b/pci-arbiter/main.c index 181bdee2..dea4af61 100644 --- a/pci-arbiter/main.c +++ b/pci-arbiter/main.c @@ -24,7 +24,12 @@ #include <fcntl.h> #include <version.h> #include <argp.h> +#include <unistd.h> #include <hurd/netfs.h> +#include <hurd/ports.h> +#include <hurd/fsys.h> +#include <device/device.h> +#include <sys/mman.h> #include <pci_S.h> #include <startup_notify_S.h> @@ -34,18 +39,70 @@ #include "libnetfs/fsys_S.h" #include "libports/interrupt_S.h" #include "libnetfs/ifsock_S.h" +#include "libmachdev/machdev.h" #include <pciaccess.h> +#include <pthread.h> #include "pcifs.h" #include "startup.h" struct pcifs *fs; -volatile struct mapped_time_value *pcifs_maptime; +volatile struct mapped_time_value *pcifs_maptime = NULL; /* Libnetfs stuff */ int netfs_maxsymlinks = 0; char *netfs_server_name = "pci-arbiter"; char *netfs_server_version = HURD_VERSION; +static mach_port_t pci_control_port; + + +static io_return_t +pci_device_open (mach_port_t reply_port, mach_msg_type_name_t reply_port_type, + dev_mode_t mode, char *name, device_t * devp, + mach_msg_type_name_t * devicePoly) +{ + io_return_t err = D_SUCCESS; + mach_port_t dev_master, root; + + if (strncmp(name, "pci", 3)) + err = D_NO_SUCH_DEVICE; + + /* Fall back to opening kernel device master */ + if (err) + { + get_privileged_ports(NULL, &dev_master); + err = device_open (dev_master, mode, name, devp); + *devicePoly = MACH_MSG_TYPE_MOVE_SEND; + return D_SUCCESS; + } + + root = pci_control_port; + *devp = root; + *devicePoly = MACH_MSG_TYPE_COPY_SEND; + return D_SUCCESS; +} + +static struct machdev_device_emulation_ops pci_arbiter_emulation_ops = { + NULL, + NULL, + NULL, + NULL, + pci_device_open, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + int netfs_demuxer (mach_msg_header_t * inp, mach_msg_header_t * outp) { @@ -67,24 +124,82 @@ netfs_demuxer (mach_msg_header_t * inp, mach_msg_header_t * outp) return FALSE; } +static void * +netfs_server_func (void *arg) +{ + error_t err; + + do + { + ports_manage_port_operations_multithread (netfs_port_bucket, + netfs_demuxer, + 1000 * 60 * 2, /* two minutes thread */ + 1000 * 60 * 10,/* ten minutes server */ + 0); + err = netfs_shutdown (0); + } + while (err); + return NULL; +} + + +static mach_port_t +pcifs_startup(mach_port_t bootstrap, int flags) +{ + error_t err; + mach_port_t realnode; + struct port_info *newpi; + + err = ports_create_port (netfs_control_class, netfs_port_bucket, + sizeof (struct port_info), &newpi); + if (!err) + { + pci_control_port = ports_get_send_right (newpi); + err = fsys_startup (bootstrap, flags, pci_control_port, MACH_MSG_TYPE_COPY_SEND, + &realnode); + assert_perror_backtrace (err); + } + if (err) + error (11, err, "Translator startup failure: fsys_startup"); + + return realnode; +} + int main (int argc, char **argv) { error_t err; mach_port_t bootstrap; + mach_port_t disk_server_task; + pthread_t t, nt; /* Parse options */ alloc_file_system (&fs); argp_parse (netfs_runtime_argp, argc, argv, 0, 0, 0); + disk_server_task = fs->params.disk_server_task; - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "must be started as a translator"); - + if (disk_server_task != MACH_PORT_NULL) + { + machdev_register (&pci_arbiter_emulation_ops); + machdev_device_init (); + machdev_trivfs_init (disk_server_task, "pci", "/servers/bus/pci", &bootstrap); + err = pthread_create (&t, NULL, machdev_server, NULL); + if (err) + error (1, err, "Creating machdev thread"); + pthread_detach (t); + } + else + { + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "must be started as a translator"); + } /* Initialize netfs and start the translator. */ netfs_init (); err = maptime_map (0, 0, &pcifs_maptime); + if (err) + err = maptime_map (1, 0, &pcifs_maptime); if (err) error (1, err, "mapping time"); @@ -93,8 +208,11 @@ main (int argc, char **argv) if (err) error (1, err, "Starting the PCI system"); - /* Create the PCI filesystem */ - err = init_file_system (netfs_startup (bootstrap, O_READ), fs); + machdev_trivfs_server(bootstrap); + /* Timer started, quickly do all these next, before we call rump_init */ + + /* Create the PCI filesystem without an underlying node first */ + err = init_file_system (pcifs_startup (bootstrap, O_READ), fs); if (err) error (1, err, "Creating the PCI filesystem"); @@ -108,6 +226,11 @@ main (int argc, char **argv) if (err) error (1, err, "Setting permissions"); + err = pthread_create (&nt, NULL, netfs_server_func, NULL); + if (err) + error (1, err, "Creating netfs loop thread"); + pthread_detach (nt); + /* * Ask init to tell us when the system is going down, * so we can try to be friendly to our correspondents on the network. @@ -116,5 +239,8 @@ main (int argc, char **argv) netfs_server_loop (); /* Never returns. */ + /* Let the other threads do their job */ + pthread_exit(NULL); + /* Never reached */ return 0; } diff --git a/pci-arbiter/netfs_impl.c b/pci-arbiter/netfs_impl.c index b987a0bc..45059195 100644 --- a/pci-arbiter/netfs_impl.c +++ b/pci-arbiter/netfs_impl.c @@ -59,25 +59,17 @@ get_dirents (struct pcifs_dirent *dir, int i, count; size_t size; char *p; + int nentries = (int)dir->dir->num_entries; - if (first_entry >= dir->dir->num_entries) + if (first_entry >= nentries) { *data_len = 0; *data_entries = 0; return 0; } - if (max_entries < 0) - count = dir->dir->num_entries; - else - { - count = ((first_entry + max_entries) >= dir->dir->num_entries ? - dir->dir->num_entries : max_entries) - first_entry; - } - - size = - (count * DIRENTS_CHUNK_SIZE) > - max_data_len ? max_data_len : count * DIRENTS_CHUNK_SIZE; + count = nentries - first_entry; + size = count * DIRENTS_CHUNK_SIZE; *data = mmap (0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); err = ((void *) *data == (void *) -1) ? errno : 0; @@ -185,6 +177,8 @@ error_t netfs_check_open_permissions (struct iouser * user, struct node * node, int flags, int newnode) { + if (!user) + return 0; return entry_check_perms (user, node->nn->ln, flags); } @@ -234,8 +228,8 @@ netfs_get_dirents (struct iouser * cred, struct node * dir, if (dir->nn->ln->dir) { - err = get_dirents (dir->nn->ln, first_entry, max_entries, - data, data_len, max_entries, data_entries); + err = get_dirents (dir->nn->ln, first_entry, -1, + data, data_len, 0, data_entries); } else err = ENOTDIR; @@ -257,6 +251,21 @@ netfs_attempt_lookup (struct iouser * user, struct node * dir, { error_t err = 0; struct pcifs_dirent *entry; + char *last = name; + + /* Strip trailing slash */ + if (*last) + { + while (*last) + last++; + last--; + if (*last == '/') + *last = '\0'; + } + + /* Skip leading dot slash */ + if (*name == '.' && *(name+1) == '/') + name += 2; if (*name == '\0' || strcmp (name, ".") == 0) /* Current directory -- just add an additional reference to DIR's node @@ -292,7 +301,7 @@ netfs_attempt_lookup (struct iouser * user, struct node * dir, /* `dir' is a directory */ /* Check dir permissions */ - err = entry_check_perms (user, dir->nn->ln, O_READ | O_EXEC); + err = netfs_check_open_permissions (user, dir, O_READ | O_EXEC, 0); if (!err) { entry = lookup (dir, name); diff --git a/pci-arbiter/options.c b/pci-arbiter/options.c index 5767ad27..141c69e3 100644 --- a/pci-arbiter/options.c +++ b/pci-arbiter/options.c @@ -241,6 +241,15 @@ parse_opt (int opt, char *arg, struct argp_state *state) case 'n': h->ncache_len = atoi (arg); break; + case 'T': + h->disk_server_task = atoi (arg); + break; + case 'H': + h->host_priv_port = atoi (arg); + break; + case 'P': + h->dev_master_port = atoi (arg); + break; case ARGP_KEY_INIT: /* Initialize our parsing state. */ h = malloc (sizeof (struct parse_hook)); @@ -250,6 +259,9 @@ parse_opt (int opt, char *arg, struct argp_state *state) h->permsets = 0; h->num_permsets = 0; h->ncache_len = NODE_CACHE_MAX; + h->disk_server_task = MACH_PORT_NULL; + h->host_priv_port = MACH_PORT_NULL; + h->dev_master_port = MACH_PORT_NULL; err = parse_hook_add_set (h); if (err) FAIL (err, 1, err, "option parsing"); @@ -286,6 +298,11 @@ parse_opt (int opt, char *arg, struct argp_state *state) /* Set cache len */ fs->params.node_cache_max = h->ncache_len; + /* Set bootstrap ports */ + fs->params.disk_server_task = h->disk_server_task; + _hurd_host_priv = h->host_priv_port; + _hurd_device_master = h->dev_master_port; + if (fs->root) { /* @@ -364,6 +381,8 @@ netfs_append_args (char **argz, size_t * argz_len) if (fs->params.node_cache_max != NODE_CACHE_MAX) ADD_OPT ("--ncache=%u", fs->params.node_cache_max); + if (fs->params.disk_server_task != MACH_PORT_NULL) + ADD_OPT ("--disk-server-task=%lu", fs->params.disk_server_task); #undef ADD_OPT return err; } diff --git a/pci-arbiter/options.h b/pci-arbiter/options.h index 8e5a9da4..292d2963 100644 --- a/pci-arbiter/options.h +++ b/pci-arbiter/options.h @@ -45,6 +45,11 @@ struct parse_hook /* Node cache length */ size_t ncache_len; + + /* Mach ports */ + mach_port_t disk_server_task; + mach_port_t host_priv_port; + mach_port_t dev_master_port; }; /* Lwip translator options. Used for both startup and runtime. */ @@ -65,6 +70,9 @@ static const struct argp_option options[] = { {0, 0, 0, 0, "Global configuration options:", 3}, {"ncache", 'n', "LENGTH", 0, "Node cache length. " STR (NODE_CACHE_MAX) " by default"}, + {"disk-server-task", 'T', "TASK", 0, "Task for bootstrapping disk server"}, + {"host-priv-port", 'H', "PORT", 0, "Port for bootstrapping host"}, + {"dev-master-port", 'P', "PORT", 0, "Port for bootstrapping device master"}, {0} }; diff --git a/pci-arbiter/pci-ops.c b/pci-arbiter/pci-ops.c index 3346e55a..07228fbe 100644 --- a/pci-arbiter/pci-ops.c +++ b/pci-arbiter/pci-ops.c @@ -39,12 +39,12 @@ check_permissions (struct protid *master, int flags) node = master->po->np; e = node->nn->ln; - /* Check wheter the user has permissions to access this node */ - err = entry_check_perms (master->user, e, flags); + /* Check whether the user has permissions to access this node */ + err = netfs_check_open_permissions (master->user, node, flags, 0); if (err) return err; - /* Check wheter the request has been sent to the proper node */ + /* Check whether the request has been sent to the proper node */ if (e->domain != 0 /* Only domain 0 can be accessed by I/O ports */ || e->bus < 0 || e->dev < 0 || e->func < 0) err = EINVAL; diff --git a/pci-arbiter/pcifs.c b/pci-arbiter/pcifs.c index 0535779e..e09bdd13 100644 --- a/pci-arbiter/pcifs.c +++ b/pci-arbiter/pcifs.c @@ -31,6 +31,9 @@ #include "ncache.h" #include "func_files.h" +/* Empty status for root node when bootstrapping */ +static io_statbuf_t underlying_stat; + static error_t create_dir_entry (int32_t domain, int16_t bus, int16_t dev, int16_t func, int32_t device_class, char *name, @@ -93,17 +96,20 @@ init_file_system (file_t underlying_node, struct pcifs * fs) { error_t err; struct node *np; - io_statbuf_t underlying_node_stat; + io_statbuf_t *underlying_node_stat = &underlying_stat; - /* Initialize status from underlying node. */ - err = io_stat (underlying_node, &underlying_node_stat); - if (err) - return err; + if (underlying_node) + { + /* Initialize status from underlying node. */ + err = io_stat (underlying_node, underlying_node_stat); + if (err) + return err; + } np = netfs_make_node_alloc (sizeof (struct netnode)); if (!np) return ENOMEM; - np->nn_stat = underlying_node_stat; + np->nn_stat = *underlying_node_stat; np->nn_stat.st_fsid = getpid (); np->nn_stat.st_mode = S_IFDIR | S_IROOT | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | diff --git a/pci-arbiter/pcifs.h b/pci-arbiter/pcifs.h index 72cf2910..f19654d1 100644 --- a/pci-arbiter/pcifs.h +++ b/pci-arbiter/pcifs.h @@ -141,6 +141,9 @@ struct pcifs_params /* The size of the node cache. */ size_t node_cache_max; + /* Bootstrap disk server task */ + mach_port_t disk_server_task; + /* FS permissions. */ struct pcifs_perm *perms; size_t num_perms; diff --git a/pci-arbiter/startup-ops.c b/pci-arbiter/startup-ops.c index eb387fd9..fc285572 100644 --- a/pci-arbiter/startup-ops.c +++ b/pci-arbiter/startup-ops.c @@ -25,6 +25,7 @@ #include "startup.h" +#if 0 // FIXME: this conflicts with trivfs for machdev /* The system is going down. Call netfs_shutdown() */ error_t S_startup_dosync (mach_port_t handle) @@ -42,3 +43,4 @@ S_startup_dosync (mach_port_t handle) return netfs_shutdown (FSYS_GOAWAY_FORCE); } +#endif -- 2.30.0