bug-hurd
[Top][All Lists]
Advanced

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

[PATCH 3/4] Bootstrappable pci-arbiter


From: Damien Zammit
Subject: [PATCH 3/4] Bootstrappable pci-arbiter
Date: Tue, 2 Mar 2021 22:41:36 +1100

---
 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




reply via email to

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