bug-hurd
[Top][All Lists]
Advanced

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

proxy memory objects patch


From: Marcus Brinkmann
Subject: proxy memory objects patch
Date: Wed, 20 Nov 2002 23:15:14 +0100
User-agent: Mutt/1.4i

Hi,

here is my patch for proxy memory objects, with a new kernel type, and with
the behaviour I assumed to be the correct one in my last mail (changing that
if I was wrong is trivial, the work is in all the infrastructure of setting
up a new kernel object and adding the interface).

There is a new file in vm/memory_object_proxy.c and a new interface in
mach4.defs.  I have added a couple of skip's in the !MACH_PCSAMPLE case,
because I think reusing msgid's is bad mojo, but I am not sure if
MACH_PCSAMPLE is something to worry about specifically.

If everything is fine, I will commit it to the gnumach 1 branch
and the head, and then we can add the new interface to libmachuser.  Then we
can put a configure check into the Hurd and use it in the Hurd server's
io_map routines.  We can do it only for the read-only memobjs, or for the
read-only and writable memory objects (to avoid users messing around with
the memory object port, sending faked messages to it, etc).  I am not really
sure how important that is, maybe it's better to just make the pager robust.

Anyway, that's what I have.  Enjoy.

2002-11-21  Marcus Brinkmann  <marcus@gnu.org>

        * include/mach/mach4.defs: Add memory_object_create_proxy
        interface.
        * Makefile.in (vm-cfiles): Add memory_object_proxy.c.
        * vm/memory_object_proxy.c: New file.
        * kern/ipc_kobject.h: New macro IKOT_PAGER_PROXY.  Bump up macros
        IKOT_UNKNOWN and IKOT_MAX_TYPE.
        * kern/ipc_kobject.c (ipc_kobject_notify): Call
        memory_object_proxy_notify for IKOT_PAGER_PROXY.
        * vm/vm_init.c (vm_mem_init): Call memory_object_proxy_init.
        * vm/vm_user.c (vm_map): Implement support for proxy memory
        objects.

Thanks,
Marcus

Index: Makefile.in
===================================================================
RCS file: /cvsroot/hurd/gnumach/Makefile.in,v
retrieving revision 1.36
diff -u -p -r1.36 Makefile.in
--- Makefile.in 10 Nov 2002 02:06:25 -0000      1.36
+++ Makefile.in 20 Nov 2002 22:01:05 -0000
@@ -115,7 +115,7 @@ kern-files = $(kern-cfiles) \
        mach.srv mach4.srv mach_debug.srv mach_host.srv
 
 # Virtual memory implementation
-vm-cfiles = $(addprefix vm_,$(vm-names)) memory_object.c
+vm-cfiles = $(addprefix vm_,$(vm-names)) memory_object.c memory_object_proxy.c
 vm-names = debug.c external.c fault.c init.c kern.c map.c \
        object.c pageout.c resident.c user.c
 vm-files = $(vm-cfiles) memory_object_default.cli memory_object_user.cli \
Index: include/mach/mach4.defs
===================================================================
RCS file: /cvsroot/hurd/gnumach/include/mach/mach4.defs,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 mach4.defs
--- include/mach/mach4.defs     25 Feb 1997 21:26:51 -0000      1.1.1.1
+++ include/mach/mach4.defs     20 Nov 2002 22:01:06 -0000
@@ -79,4 +80,28 @@ skip /* pc_sampling reserved 1*/;
 skip   /* pc_sampling reserved 2*/;
 skip   /* pc_sampling reserved 3*/;
 skip   /* pc_sampling reserved 4*/;
+
+#else
+
+skip;  /* task_enable_pc_sampling */
+skip;  /* task_disable_pc_sampling */
+skip;  /* task_get_sampled_pcs */
+skip;  /* thread_enable_pc_sampling */
+skip;  /* thread_disable_pc_sampling */
+skip;  /* thread_get_sampled_pcs */
+
+skip   /* pc_sampling reserved 1*/;
+skip   /* pc_sampling reserved 2*/;
+skip   /* pc_sampling reserved 3*/;
+skip   /* pc_sampling reserved 4*/;
+
 #endif
+
+
+/* Create a new proxy memory object from OBJECT with the maximum
+   protection MAX_PROTECTION and return it in *PORT.  */
+routine memory_object_create_proxy(
+               task            : ipc_space_t;
+               object          : memory_object_t;
+               max_protection  : vm_prot_t;
+               out proxy       : mach_port_t);
Index: kern/ipc_kobject.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/kern/ipc_kobject.c,v
retrieving revision 1.2
diff -u -p -r1.2 ipc_kobject.c
--- kern/ipc_kobject.c  5 Apr 2001 06:39:20 -0000       1.2
+++ kern/ipc_kobject.c  20 Nov 2002 22:01:10 -0000
@@ -385,6 +385,9 @@ ipc_kobject_notify(request_header, reply
                case IKOT_DEVICE:
                return ds_notify(request_header);
 
+               case IKOT_PAGER_PROXY:
+               return memory_object_proxy_notify(request_header);
+
                default:
                return FALSE;
        }
Index: kern/ipc_kobject.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/kern/ipc_kobject.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 ipc_kobject.h
--- kern/ipc_kobject.h  25 Feb 1997 21:28:22 -0000      1.1.1.1
+++ kern/ipc_kobject.h  20 Nov 2002 22:01:11 -0000
@@ -77,9 +77,10 @@ typedef unsigned int ipc_kobject_type_t;
 #define IKOT_LOCK_SET          24
 #define IKOT_CLOCK             25
 #define IKOT_CLOCK_CTRL                26
+#define        IKOT_PAGER_PROXY        27
                                        /* << new entries here  */
-#define        IKOT_UNKNOWN            27      /* magic catchall       */
-#define        IKOT_MAX_TYPE           28      /* # of IKOT_ types     */
+#define        IKOT_UNKNOWN            28      /* magic catchall       */
+#define        IKOT_MAX_TYPE           29      /* # of IKOT_ types     */
  /* Please keep ipc/ipc_object.c:ikot_print_array up to date   */
 
 #define is_ipc_kobject(ikot)   (ikot != IKOT_NONE)
Index: vm/vm_init.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/vm/vm_init.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 vm_init.c
--- vm/vm_init.c        25 Feb 1997 21:28:36 -0000      1.1.1.1
+++ vm/vm_init.c        20 Nov 2002 22:01:14 -0000
@@ -81,4 +81,5 @@ void vm_mem_bootstrap()
 void vm_mem_init()
 {
        vm_object_init();
+       memory_object_proxy_init();
 }
Index: vm/vm_user.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/vm/vm_user.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 vm_user.c
--- vm/vm_user.c        25 Feb 1997 21:28:37 -0000      1.1.1.1
+++ vm/vm_user.c        20 Nov 2002 22:01:14 -0000
@@ -275,6 +275,12 @@ kern_return_t vm_copy(map, source_addres
        return KERN_SUCCESS;
 }
 
+
+/* XXX From memory_object_proxy.c  */
+kern_return_t
+memory_object_proxy_lookup (ipc_port_t proxy_object, ipc_port_t *object,
+                            vm_prot_t *max_protection);
+
 /*
  *     Routine:        vm_map
  */
@@ -324,7 +330,22 @@ kern_return_t vm_map(
                copy = FALSE;
        } else if ((object = vm_object_enter(memory_object, size, FALSE))
                        == VM_OBJECT_NULL)
-               return(KERN_INVALID_ARGUMENT);
+         {
+           ipc_port_t real_memobj;
+           vm_prot_t prot;
+           result = memory_object_proxy_lookup (memory_object, &real_memobj,
+                                                &prot);
+           if (result != KERN_SUCCESS)
+             return result;
+
+           /* Reduce the allowed access to the memory object.  */
+           max_protection &= prot;
+           cur_protection &= prot;
+
+           if ((object = vm_object_enter(real_memobj, size, FALSE))
+               == VM_OBJECT_NULL)
+             return KERN_INVALID_ARGUMENT;
+         }
 
        /*
         *      Perform the copy if requested
--- /dev/null   2002-08-17 03:12:58.000000000 +0200
+++ vm/memory_object_proxy.c    2002-11-21 00:38:54.000000000 +0100
@@ -0,0 +1,180 @@
+/* memory_object_proxy.c - Proxy memory objects for Mach.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   Written by Marcus Brinkmann.
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+/* A proxy memory object is a kernel port that can be used like a real
+   memory object in a vm_map call, except that the current and maximum
+   protection are restricted to the proxy object's maximum protection
+   at the time the mapping is established.  The kernel port will hold
+   a reference to the real memory object for the life time of the
+   proxy object.
+
+   Note that we don't need to do any reference counting on the proxy
+   object.  Our caller will hold a reference to the proxy object when
+   looking it up, and is expected to acquire its own reference to the
+   real memory object if needed before releasing the reference to the
+   proxy object.
+
+   The user provided real memory object and the maximum protection are
+   not checked for validity.  The maximum protection is only used as a
+   mask, and the memory object is validated at the time the mapping is
+   established.  */
+
+#include <mach/port.h>
+#include <mach/kern_return.h>
+#include <mach/notify.h>
+#include <mach/vm_prot.h>
+#include <kern/zalloc.h>
+#include <kern/mach_param.h>
+#include <ipc/ipc_port.h>
+
+#include <oskit/ds_oskit.h>
+
+/* The zone which holds our proxy memory objects.  */
+static zone_t memory_object_proxy_zone;
+
+struct memory_object_proxy
+{
+  struct ipc_port *port;
+
+  ipc_port_t object;
+  vm_prot_t max_protection;
+};
+typedef struct memory_object_proxy *memory_object_proxy_t;
+
+
+void
+memory_object_proxy_init (void)
+{
+  /* For limit, see PORT_MAX.  */
+  memory_object_proxy_zone = zinit (sizeof (struct memory_object_proxy),
+                                   (TASK_MAX * 3 + THREAD_MAX)
+                                   * sizeof (struct memory_object_proxy),
+                                   256 * sizeof (struct memory_object_proxy),
+                                   ZONE_EXHAUSTIBLE,
+                                   "proxy memory object zone");
+}
+  
+/* Lookup a proxy memory object by its port.  */
+static memory_object_proxy_t
+memory_object_proxy_port_lookup (ipc_port_t port)
+{
+  memory_object_proxy_t proxy;
+
+  if (!IP_VALID(port))
+    return 0;
+
+  ip_lock (port);
+  if (ip_active (port) && (ip_kotype (port) == IKOT_PAGER_PROXY))
+    proxy = (memory_object_proxy_t) port->ip_kobject;
+  else
+    proxy = 0;
+  ip_unlock (port);
+  return proxy;
+}
+
+
+/* Process a no-sender notification for the proxy memory object
+   port.  */
+boolean_t
+memory_object_proxy_notify (mach_msg_header_t *msg)
+{
+  if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS)
+    {
+      memory_object_proxy_t proxy;
+      mach_no_senders_notification_t *ns;
+
+      ns = (mach_no_senders_notification_t *) msg;
+      proxy = memory_object_proxy_port_lookup
+       ((ipc_port_t) ns->not_header.msgh_remote_port);
+      assert (proxy);
+
+      ipc_port_release_send (proxy->object);
+      return TRUE;
+    }
+
+  printf ("memory_object_proxy_notify: strange notification %d\n",
+         msg->msgh_id);
+  return FALSE;
+}
+
+
+/* Create a new proxy memory object from OBJECT with the maximum
+   protection MAX_PROTECTION and return it in *PORT.  */
+kern_return_t
+memory_object_create_proxy (ipc_space_t space, ipc_port_t object,
+                           vm_prot_t max_protection, ipc_port_t *port)
+{
+  kern_return_t kr;
+  memory_object_proxy_t proxy;
+  ipc_port_t notify;
+
+  if (space == IS_NULL)
+    return KERN_INVALID_TASK;
+
+  if (!IP_VALID(object))
+    return KERN_INVALID_NAME;
+
+  proxy = (memory_object_proxy_t) zalloc (memory_object_proxy_zone);
+
+  /* Allocate port, keeping a reference for it.  */
+  proxy->port = ipc_port_alloc_kernel ();
+  if (proxy->port == IP_NULL)
+    {
+      zfree (memory_object_proxy_zone, (vm_offset_t) proxy);
+      return KERN_RESOURCE_SHORTAGE;
+    }
+  /* Associate the port with the proxy memory object.  */
+  ipc_kobject_set (proxy->port, (ipc_kobject_t) proxy, IKOT_PAGER_PROXY);
+
+  /* Request no-senders notifications on the port.  */
+  notify = ipc_port_make_sonce (proxy->port);
+  ip_lock (proxy->port);
+  ipc_port_nsrequest (proxy->port, 1, notify, &notify);
+  assert (notify == IP_NULL);
+
+  proxy->object = ipc_port_copy_send (object);
+  proxy->max_protection = max_protection;
+
+  *port = ipc_port_make_send (proxy->port);
+  return KERN_SUCCESS;
+}
+
+
+/* Lookup the real memory object and maximum protection for the proxy
+   memory object port PORT, for which the caller holds a reference.
+   *OBJECT is only guaranteed to be valid as long as the caller holds
+   the reference to PORT (unless the caller acquires its own reference
+   to it).  If PORT is not a proxy memory object, return
+   KERN_INVALID_ARGUMENT.  */
+kern_return_t
+memory_object_proxy_lookup (ipc_port_t port, ipc_port_t *object,
+                           vm_prot_t *max_protection)
+{
+  memory_object_proxy_t proxy;
+
+  proxy = memory_object_proxy_port_lookup (port);
+  if (!proxy)
+    return KERN_INVALID_ARGUMENT;
+
+   *object = proxy->object;
+   *max_protection = proxy->max_protection;
+
+  return KERN_SUCCESS;
+}



-- 
`Rhubarb is no Egyptian god.' GNU      http://www.gnu.org    marcus@gnu.org
Marcus Brinkmann              The Hurd http://www.gnu.org/software/hurd/
Marcus.Brinkmann@ruhr-uni-bochum.de
http://www.marcus-brinkmann.de/




reply via email to

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