bug-hurd
[Top][All Lists]
Advanced

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

Patch for i/o permission control in GNU Mach (was: I/O permission contro


From: Thomas Schwinge
Subject: Patch for i/o permission control in GNU Mach (was: I/O permission control in OSKit-Mach)
Date: Wed, 25 Apr 2007 18:45:44 +0200
User-agent: Mutt/1.5.11

Hello!

On Wed, Apr 25, 2007 at 03:07:34PM +0200, I wrote:
> Now that it finally works, I can now polish and test my patch a bit.  :-)

Here we go.

There are a few places marked with ``TODO''.  Please comment on them.

If someone wants to see my testing equipment, I'll happily provide it.

I worked on integrating Marcus's work into the GNU Mach branch and did
not really check that all the low level details are correct -- I would
assume that checking those has been done at the time Marcus's patch was
installed into the OSKit-Mach branch.

With this patch, glibc's `ioperm' call will ``automagically'' begin to
work, as soon as it's been recompiled with the modified GNU Mach header
and definition files in place.


#v+
2007-04-25  Thomas Schwinge  <tschwinge@gnu.org>

        * i386/i386/io_port.h: Remove file.
        * i386/i386at/kd.c: TODO.

        * i386/Makefrag.am (libkernel_a_SOURCES): Add `i386/i386/io_perm.c',
        `i386/i386/io_perm.h', `i386/i386/machine_task.c', `i386/i386/task.h'
        and remove `i386/i386/io_port.h', `i386/i386/iopb.c',
        `i386/i386/iopb.h'.

        * include/stddef.h: New file.

        * i386/i386/io_perm.c: Include <string.h>, <device/device_emul.h> and
        don't include <oskit/ds_oskit.h>.
        (io_perm_device_emulation_ops): New variable.
        (dev_open_alloc, setup_no_senders): Remove declarations.
        (convert_io_perm_to_port, convert_port_to_io_perm, io_perm_deallocate):
        Rewrite.
        (no_senders): New function.
        (i386_io_perm_create, i386_io_perm_modify): Rewrite partially, to adapt
        to the GNU Mach environment.
        * i386/i386/io_perm.h: Include <device/dev_hdr.h> and
        <ipc/ipc_types.h>.
        (io_perm, io_perm_t): New structure and accompanying type definition.
        (IO_PERM_NULL): Define.
        * i386/i386/locore.S (ktss): Move variable to...
        * i386/i386/ktss.c: ... here, make it a ``struct task_tss''.
        (ktss_init): Initialize the `task_tss' structure and the i/o permission
        bit map.
        * i386/i386/ktss.h: Adapt to that.
        * i386/i386/machine_task.c (machine_task_module_init): Adapt the `zinit'
        call to the GNU Mach environment.
        * i386/i386/mp_desc.c: Include <machine/ktss.h>.
        * i386/i386/tss.h: Include <machine/io_perm.h>.
        (task_tss): New structure, equivalent to the OSKit-Mach one.
        * i386/include/mach/i386/mach_i386.defs: Don't include
        <device/device_types.defs>.
        (device_list_t): Remove type.
        * i386/include/mach/i386/mach_i386_types.h (device_list_t): Remove type
        definition.

2007-04-25  Marcus Brinkmann  <marcus@gnu.org>

        * i386/i386/iopb.h, i386/i386/iopb.c: Obsolete files removed.

        * i386/i386/pcb.c (switch_context): Update the I/O permission
        bitmap from stack_handoff() here (not only in stack_handoff()).

        * i386/i386/machine_task.c (machine_task_module_init): Set
        ZONE_COLLECTABLE and ZONE_EXHAUSTIBLE flags for the iopb zone.
        Requested by Roland McGrath <roland@frob.com>.

        * i386/i386/io_perm.h: New file.
        * i386/i386/io_perm.c: New file.
        * i386/i386/machine_task.c: New file.
        * i386/i386/mp_desc.h: (struct mp_desc_table): Change type of ktss to
        struct task_tss.
        (mp_ktss): Likewise for array of pointers to the struct.
        * i386/i386/mp_desc.c: Include `machine/tss.h' and `machine/io_perm.h'.
        (mp_ktss): Change type to array of struct task_tss.
        (mp_desc_init): Cast pointer to x86_tss into pointer to task_tss,
        and use size of struct task_tss instead size of struct x86_tss.
        Initialize the task_tss structure.
        * i386/i386/pcb.c: Include `stddef.h' and `machine/tss.h'.
        (iopb_create, iopb_destroy): Prototypes removed.
        (curr_ktss): Cast pointer to base_tss to pointer to struct
        task_tss.
        (switch_ktss): Always use kernel TSS.
        (update_ktss_iopb): New function.
        (stack_handoff): Call update_ktss_iopb.
        (pcb_module_init): Do not call iopb_init.
        (pcb_terminate): Do not call iopb_destroy.
        (thread_setstatus): Remove local variable tss.
        (thread_getstatus): Rewrite i386_ISA_PORT_MAP_STATE case handler.
        * i386/i386/task.h: New file.
        * i386/i386/thread.h: Do not include `i386/iopb.h'.
        (struct i386_machine_state): Remove member io_tss.
        * i386/include/mach/i386/mach_i386.defs [KERNEL_SERVER]: Include
        `machine/io_perm.h'.  Define intran, outtran and destructor.
        (io_port_t): New type.
        (io_perm_t): Likewise.
        (i386_io_port_add): Interface removed.
        (i386_io_port_remove): Likewise.
        (i386_io_port_list): Likewise.
        (i386_io_perm_create): New interface.
        (i386_io_perm_modify): Likewise.
        * i386/include/mach/i386/mach_i386_types.h [MACH_KERNEL]: Include
        `i386/io_perm.h'.
        [!MACH_KERNEL]: Define types io_port_t and io_perm_t.
        * kern/task.c (task_init): Call machine_task_module_init.
        (task_create): Call machine_task_init.
        (task_deallocate): Call machine_task_terminate.
        (task_collect_scan): Call machine_task_collect.
        * task.h: Include `machine/task.h'.
        (struct task): Add member machine.


Index: i386/Makefrag.am
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/Attic/Makefrag.am,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 Makefrag.am
--- i386/Makefrag.am    1 Apr 2007 22:10:39 -0000       1.1.2.9
+++ i386/Makefrag.am    25 Apr 2007 16:36:32 -0000
@@ -85,9 +85,8 @@ libkernel_a_SOURCES += \
        i386/i386/idt.c \
        i386/i386/idt_inittab.S \
        i386/i386/io_map.c \
-       i386/i386/io_port.h \
-       i386/i386/iopb.c \
-       i386/i386/iopb.h \
+       i386/i386/io_perm.c \
+       i386/i386/io_perm.h \
        i386/i386/ipl.h \
        i386/i386/ktss.c \
        i386/i386/ktss.h \
@@ -101,6 +100,7 @@ libkernel_a_SOURCES += \
        i386/i386/loose_ends.c \
        i386/i386/mach_param.h \
        i386/i386/machine_routines.h \
+       i386/i386/machine_task.c \
        i386/i386/machspl.h \
        i386/i386/mp_desc.c \
        i386/i386/mp_desc.h \
@@ -120,6 +120,7 @@ libkernel_a_SOURCES += \
        i386/i386/setjmp.h \
        i386/i386/spl.S \
        i386/i386/spl.h \
+       i386/i386/task.h \
        i386/i386/thread.h \
        i386/i386/time_stamp.h \
        i386/i386/timer.h \
Index: i386/i386/io_perm.c
===================================================================
RCS file: i386/i386/io_perm.c
diff -N i386/i386/io_perm.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ i386/i386/io_perm.c 25 Apr 2007 16:36:32 -0000
@@ -0,0 +1,313 @@
+/* Manipulate I/O permission bitmap objects.
+
+   Copyright (C) 2002, 2007 Free Software Foundation, Inc.
+
+   Written by Marcus Brinkmann.  Glued into GNU Mach by Thomas Schwinge.
+
+   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.
+
+   This program 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.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <string.h>
+
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+
+#include <ipc/ipc_port.h>
+
+#include <kern/zalloc.h>
+#include <kern/lock.h>
+#include <kern/queue.h>
+#include <kern/thread.h>
+
+#include <device/dev_hdr.h>
+#include <device/device_emul.h>
+#include <device/device_port.h>
+
+#include "io_perm.h"
+#include "gdt.h"
+
+/* Our device emulation ops.  See below, at the bottom of this file.  */
+static struct device_emulation_ops io_perm_device_emulation_ops;
+
+
+/* The outtran which allows MIG to convert an io_perm_t object to a port
+   representing it.  */
+ipc_port_t
+convert_io_perm_to_port (io_perm_t io_perm)
+{
+  if (io_perm == IO_PERM_NULL)
+    return IP_NULL;
+
+  ipc_port_t port;
+
+  port = ipc_port_make_send (io_perm->port);
+
+  return port;
+}
+
+
+/* The intran which allows MIG to convert a port representing an
+   io_perm_t object to the object itself.  */
+io_perm_t
+convert_port_to_io_perm (ipc_port_t port)
+{
+  device_t device;
+
+  device = dev_port_lookup (port);
+
+  if (device == DEVICE_NULL)
+    return IO_PERM_NULL;
+
+  io_perm_t io_perm;
+
+  io_perm = device->emul_data;
+
+  return io_perm;
+}
+
+#if REMOVE_ME
+/* TODO.  Fix this comment.  */
+/* The destructor which is called when the last send right to a port
+   representing an io_perm_t object vanishes.  */
+void
+io_perm_deallocate (io_perm_t io_perm)
+{
+  /* TODO.  Is there anything to deallocate in here?  I don't think so, as we
+     don't allocate anything in `convert_port_to_io_perm'.  */
+}
+#endif
+
+/* Our ``no senders'' handling routine.  Deallocate the object.  */
+static
+void
+no_senders (mach_no_senders_notification_t *notification)
+{
+  io_perm_t io_perm;
+
+  io_perm = convert_port_to_io_perm
+    ((ipc_port_t) notification->not_header.msgh_remote_port);
+
+  assert (io_perm != IO_PERM_NULL);
+
+  ip_lock (io_perm->port);  /* TODO.  Actually needed?  */
+  ipc_kobject_set (io_perm->port, IKO_NULL, IKOT_NONE);
+  ipc_port_dealloc_kernel (io_perm->port);
+
+  kfree ((vm_offset_t) io_perm, sizeof *io_perm);
+}
+
+
+/* Initialize bitmap by setting all bits to OFF == 1.  */
+static inline void
+io_bitmap_init (unsigned char *iopb)
+{
+  memset (iopb, ~0, IOPB_BYTES);
+}
+
+
+/* Set selected bits in bitmap to ON == 0.  */
+static inline void
+io_bitmap_set (unsigned char *iopb, io_port_t from, io_port_t to)
+{
+  do
+    iopb[from >> 3] &= ~(1 << (from & 0x7));
+  while (from++ != to);
+}
+
+
+/* Set selected bits in bitmap to OFF == 1.  */
+static inline void
+io_bitmap_clear (unsigned char *iopb, io_port_t from, io_port_t to)
+{
+  do
+    iopb[from >> 3] |= (1 << (from & 0x7));
+  while (from++ != to);
+}
+
+
+/* Request a new port IO_PERM that represents the capability to access
+   the I/O ports [FROM; TO] directly.  MASTER_PORT is the master device port.
+
+   The function returns KERN_INVALID_ARGUMENT if TARGET_TASK is not a task,
+   or FROM is greater than TO.
+
+   The function is exported.  */
+kern_return_t
+i386_io_perm_create (ipc_port_t master_port, io_port_t from, io_port_t to,
+                    io_perm_t *new)
+{
+  /* TODO.  Check for limits [0;IOPB_MAX)?  */
+  if (master_port != master_device_port || from > to)
+    return KERN_INVALID_ARGUMENT;
+
+  io_perm_t io_perm;
+
+  io_perm = (io_perm_t) kalloc (sizeof *io_perm);
+  if (io_perm == NULL)
+    return KERN_RESOURCE_SHORTAGE;
+
+  io_perm->from = from;
+  io_perm->to = to;
+
+  io_perm->port = ipc_port_alloc_kernel ();
+  if (io_perm->port == IP_NULL)
+    {
+      kfree ((vm_offset_t) io_perm, sizeof *io_perm);
+      return KERN_RESOURCE_SHORTAGE;
+    }
+
+  /* Set up the dummy device.  */
+  ipc_kobject_set(io_perm->port,
+                 (ipc_kobject_t) &io_perm->device, IKOT_DEVICE);
+  io_perm->device.emul_data = io_perm;
+  io_perm->device.emul_ops = &io_perm_device_emulation_ops;
+
+  ipc_port_t notify;
+
+  notify = ipc_port_make_sonce(io_perm->port);
+  ip_lock(device->port);
+  ipc_port_nsrequest(io_perm->port, 1, notify, &notify);
+  assert(notify == IP_NULL);
+
+  *new = io_perm;
+
+  return KERN_SUCCESS;
+}
+
+
+/* From pcb.c.  */
+extern void update_ktss_iopb (unsigned char *new_iopb, int last);
+
+
+/* Modify the I/O permissions for TARGET_TASK.  If ENABLE is TRUE, the
+   permission to acces the I/O ports specified by IO_PERM is granted,
+   otherwise it is withdrawn.
+
+   The function returns KERN_INVALID_ARGUMENT if TARGET_TASK is not a valid
+   task or IO_PERM not a valid I/O permission port.
+
+   The function is exported.  */
+kern_return_t
+i386_io_perm_modify (task_t target_task, io_perm_t io_perm, boolean_t enable)
+{
+  io_port_t from, to;
+  unsigned char *iopb;
+  io_port_t iopb_size;
+
+  if (target_task == TASK_NULL || io_perm == IO_PERM_NULL)
+    return KERN_INVALID_ARGUMENT;
+
+  from = io_perm->from;
+  to = io_perm->to;
+
+  simple_lock (&target_task->machine.iopb_lock);
+  iopb = target_task->machine.iopb;
+  iopb_size = target_task->machine.iopb_size;
+
+  if (!enable && !iopb_size)
+    {
+      simple_unlock (&target_task->machine.iopb_lock);
+      return KERN_SUCCESS;
+    }
+
+  if (!iopb)
+    {
+      simple_unlock (&target_task->machine.iopb_lock);
+      /* TODO.  Does this have to be deallocated again?  (Thinking about
+         `no_senders'.)  Probably not, because glibc's `ioperm' call would be
+         rather difficult to implement then.*/
+      iopb = (unsigned char *) zalloc (machine_task_iopb_zone);
+      simple_lock (&target_task->machine.iopb_lock);
+      if (target_task->machine.iopb)
+       {
+         if (iopb)
+           zfree (machine_task_iopb_zone, (vm_offset_t) iopb);
+         iopb = target_task->machine.iopb;
+         iopb_size = target_task->machine.iopb_size;
+       }
+      else if (iopb)
+       {
+         target_task->machine.iopb = iopb;
+         io_bitmap_init (iopb);
+       }
+      else
+       /* TODO.  Need some unlocking here?  */
+       return KERN_RESOURCE_SHORTAGE;
+    }
+
+  if (enable)
+    {
+      io_bitmap_set (iopb, from, to);
+      if ((to >> 3) + 1 > iopb_size)
+       target_task->machine.iopb_size = (to >> 3) + 1;
+    }
+  else
+    {
+      if ((from >> 3) + 1 > iopb_size)
+       {
+         simple_unlock (&target_task->machine.iopb_lock);
+         return KERN_SUCCESS;
+       }
+
+      io_bitmap_clear (iopb, from, to);
+      while (iopb_size > 0 && iopb[iopb_size - 1] == 0xff)
+       iopb_size--;
+      target_task->machine.iopb_size = iopb_size;
+    }
+
+#if NCPUS>1
+#warning SMP support missing (notify all CPUs running threads in that of the 
I/O bitmap change).
+#endif
+  if (target_task == current_task())
+    update_ktss_iopb (iopb, target_task->machine.iopb_size);
+
+  simple_unlock (&target_task->machine.iopb_lock);
+  return KERN_SUCCESS;
+}
+
+/* We are some sort of Mach device...  */
+static struct device_emulation_ops io_perm_device_emulation_ops =
+{
+  /* ... in order to be easily able to receive a ``no senders'' notification
+     which we then use to deallocate ourselves.  */
+  .no_senders = no_senders
+};
Index: i386/i386/io_perm.h
===================================================================
RCS file: i386/i386/io_perm.h
diff -N i386/i386/io_perm.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ i386/i386/io_perm.h 25 Apr 2007 16:36:32 -0000
@@ -0,0 +1,66 @@
+/* Data types for I/O permission bitmap objects.
+
+   Copyright (C) 2002, 2007 Free Software Foundation, Inc.
+
+   Written by Marcus Brinkmann.  Glued into GNU Mach by Thomas Schwinge.
+
+   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.
+
+   This program 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.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _I386_IO_PERM_H_
+#define _I386_IO_PERM_H_
+
+#include <device/dev_hdr.h>
+#include <ipc/ipc_types.h>
+
+
+/* The highest possible I/O port.  ISA bus allows ports 0..3ff, but
+   accelerator cards are funky.  */
+#define        IOPB_MAX        0xFFFF  
+
+/* The number of bytes needed to hold all permission bits.  */
+#define        IOPB_BYTES      (((IOPB_MAX + 1) + 7) / 8)
+
+/* An offset that points outside of the permission bitmap, used to
+   disable all permission.  */
+#define IOPB_INVAL     0x2FFF
+
+
+/* The type of an I/O port address.  */
+typedef unsigned short io_port_t;
+
+
+struct io_perm
+{
+  /* We use a ``struct device'' for easy management.  */
+  struct device device;
+
+  ipc_port_t port;
+
+  io_port_t from, to;
+};
+
+typedef struct io_perm *io_perm_t;
+
+#define IO_PERM_NULL ((io_perm_t) 0)
+
+extern io_perm_t convert_port_to_io_perm (ipc_port_t);
+extern ipc_port_t convert_io_perm_to_port (io_perm_t);
+#if REMOVE_ME
+extern void io_perm_deallocate (io_perm_t);
+#endif
+
+#endif
Index: i386/i386/ktss.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/Attic/ktss.c,v
retrieving revision 1.1.1.1.4.1
diff -u -p -r1.1.1.1.4.1 ktss.c
--- i386/i386/ktss.c    13 Nov 2006 21:30:36 -0000      1.1.1.1.4.1
+++ i386/i386/ktss.c    25 Apr 2007 16:36:32 -0000
@@ -36,6 +36,9 @@
 #include "gdt.h"
 #include "ktss.h"
 
+/* A kernel TSS with a complete I/O bitmap.  */
+struct task_tss ktss;
+
 void
 ktss_init()
 {
@@ -44,16 +47,15 @@ ktss_init()
 
        /* Initialize the master TSS descriptor.  */
        fill_gdt_descriptor(KERNEL_TSS,
-                           kvtolin(&ktss), sizeof(ktss)+65536/8+1-1,
+                           kvtolin(&ktss), sizeof(struct task_tss) - 1,
                            ACC_PL_K|ACC_TSS, 0);
 
        /* Initialize the master TSS.  */
-       ktss.ss0 = KERNEL_DS;
-       ktss.esp0 = (unsigned)(exception_stack+1024);
-       ktss.io_bit_map_offset = sizeof(ktss);
-
+       ktss.tss.ss0 = KERNEL_DS;
+       ktss.tss.esp0 = (unsigned)(exception_stack+1024);
+       ktss.tss.io_bit_map_offset = IOPB_INVAL;                                
                                                                
        /* Set the last byte in the I/O bitmap to all 1's.  */
-       ((unsigned char*)&ktss)[sizeof(ktss)+65536/8] = 0xff;
+       ktss.barrier = 0xff;
 
        /* Load the TSS.  */
        ltr(KERNEL_TSS);
Index: i386/i386/ktss.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/Attic/ktss.h,v
retrieving revision 1.2
diff -u -p -r1.2 ktss.h
--- i386/i386/ktss.h    5 Apr 2001 06:39:20 -0000       1.2
+++ i386/i386/ktss.h    25 Apr 2007 16:36:32 -0000
@@ -25,6 +25,6 @@
 
 #include "tss.h"
 
-extern struct i386_tss ktss;
+extern struct task_tss ktss;
 
 #endif /* _I386_KTSS_ */
Index: i386/i386/locore.S
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/locore.S,v
retrieving revision 1.6.2.7
diff -u -p -r1.6.2.7 locore.S
--- i386/i386/locore.S  20 Dec 2006 21:13:45 -0000      1.6.2.7
+++ i386/i386/locore.S  25 Apr 2007 16:36:33 -0000
@@ -1441,12 +1441,3 @@ Entry(cpu_shutdown)
         xor     %ecx,%ecx       /* generate a divide by zero */
         div     %ecx,%eax       /* reboot now */
         ret                     /* this will "never" be executed */
-
-
-/*
- * Allocate enough space for a kernel TSS with a complete I/O bitmap,
- * for making v86-mode BIOS calls.  XXX
- */
-       .data
-       .globl  EXT(ktss)
-       .comm   EXT(ktss),0x68+65536/8+1
Index: i386/i386/machine_task.c
===================================================================
RCS file: i386/i386/machine_task.c
diff -N i386/i386/machine_task.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ i386/i386/machine_task.c    25 Apr 2007 16:36:33 -0000
@@ -0,0 +1,79 @@
+/* Machine specific data for a task on i386.
+
+   Copyright (C) 2002, 2007 Free Software Foundation, Inc.
+
+   Written by Marcus Brinkmann.  Glued into GNU Mach by Thomas Schwinge.
+
+   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.
+
+   This program 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.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <kern/lock.h>
+#include <mach/mach_types.h>
+#include <kern/zalloc.h>
+#include <kern/mach_param.h>
+#include <machine/task.h>
+
+#include <machine/io_perm.h>
+
+
+/* The zone which holds our IO permission bitmaps.  */
+zone_t machine_task_iopb_zone;
+
+
+/* Initialize the machine task module.  The function is called once at
+   start up by task_init in kern/task.c.  */
+void
+machine_task_module_init (void)
+{
+  machine_task_iopb_zone = zinit (IOPB_BYTES, 0,
+                                 TASK_MAX * IOPB_BYTES,
+                                 IOPB_BYTES,
+                                 ZONE_COLLECTABLE | ZONE_EXHAUSTIBLE,
+                                 "i386 machine task iopb");
+}
+
+
+/* Initialize the machine specific part of task TASK.  */
+void
+machine_task_init (task_t task)
+{
+  task->machine.iopb_size = 0;
+  task->machine.iopb = 0;
+  simple_lock_init (&task->machine.iopb_lock);
+}
+
+
+/* Destroy the machine specific part of task TASK and release all
+   associated resources.  */
+void
+machine_task_terminate (task_t task)
+{
+  if (task->machine.iopb)
+    zfree (machine_task_iopb_zone, (vm_offset_t) task->machine.iopb);
+}
+
+
+/* Try to release as much memory from the machine specific data in
+   task TASK.  */
+void
+machine_task_collect (task_t task)
+{
+  if (task->machine.iopb_size == 0 && task->machine.iopb)
+    {
+      zfree (machine_task_iopb_zone, (vm_offset_t) task->machine.iopb);
+      task->machine.iopb = 0;
+    }
+}
Index: i386/i386/mp_desc.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/mp_desc.c,v
retrieving revision 1.1.1.1.4.4
diff -u -p -r1.1.1.1.4.4 mp_desc.c
--- i386/i386/mp_desc.c 10 Nov 2006 01:22:57 -0000      1.1.1.1.4.4
+++ i386/i386/mp_desc.c 25 Apr 2007 16:36:33 -0000
@@ -35,6 +35,9 @@
 
 #include <i386/mp_desc.h>
 #include <i386/lock.h>
+#include <machine/ktss.h>
+#include <machine/tss.h>
+#include <machine/io_perm.h>
 
 /*
  * The i386 needs an interrupt stack to keep the PCB stack from being
@@ -82,7 +85,7 @@ struct mp_desc_table  *mp_desc_table[NCPU
 /*
  * Pointer to TSS for access in load_context.
  */
-struct i386_tss                *mp_ktss[NCPUS] = { 0 };
+struct task_tss                *mp_ktss[NCPUS] = { 0 };
 
 /*
  * Pointer to GDT to reset the KTSS busy bit.
@@ -95,7 +98,6 @@ struct real_descriptor        *mp_gdt[NCPUS] = 
 extern struct real_gate                idt[IDTSZ];
 extern struct real_descriptor  gdt[GDTSZ];
 extern struct real_descriptor  ldt[LDTSZ];
-extern struct i386_tss         ktss;
 
 /*
  * Allocate and initialize the per-processor descriptor tables.
@@ -112,7 +114,7 @@ mp_desc_init(mycpu)
                 * Master CPU uses the tables built at boot time.
                 * Just set the TSS and GDT pointers.
                 */
-               mp_ktss[mycpu] = &ktss;
+               mp_ktss[mycpu] = (struct task_tss *) &ktss;
                mp_gdt[mycpu] = gdt;
                return 0;
        }
@@ -140,7 +142,7 @@ mp_desc_init(mycpu)
                  ldt,
                  sizeof(ldt));
                memset(&mpt->ktss, 0, 
-                 sizeof(struct i386_tss));
+                 sizeof(struct task_tss));
 
                /*
                 * Fix up the entries in the GDT to point to
@@ -152,11 +154,12 @@ mp_desc_init(mycpu)
                        ACC_P|ACC_PL_K|ACC_LDT, 0);
                fill_descriptor(&mpt->gdt[sel_idx(KERNEL_TSS)],
                        (unsigned)&mpt->ktss,
-                       sizeof(struct i386_tss) - 1,
+                       sizeof(struct task_tss) - 1,
                        ACC_P|ACC_PL_K|ACC_TSS, 0);
 
-               mpt->ktss.ss0 = KERNEL_DS;
-               mpt->ktss.io_bit_map_offset = 0x0FFF;   /* no IO bitmap */
+               mpt->ktss.tss.ss0 = KERNEL_DS;
+               mpt->ktss.tss.io_bit_map_offset = IOPB_INVAL;
+               mpt->ktss.barrier = 0xFF;
 
                return mpt;
        }
Index: i386/i386/mp_desc.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/mp_desc.h,v
retrieving revision 1.2.2.1
diff -u -p -r1.2.2.1 mp_desc.h
--- i386/i386/mp_desc.h 15 Oct 2006 14:59:03 -0000      1.2.2.1
+++ i386/i386/mp_desc.h 25 Apr 2007 16:36:33 -0000
@@ -52,7 +52,7 @@ struct mp_desc_table {
        struct real_gate        idt[IDTSZ];     /* IDT */
        struct real_descriptor  gdt[GDTSZ];     /* GDT */
        struct real_descriptor  ldt[LDTSZ];     /* LDT */
-       struct i386_tss         ktss;
+       struct task_tss         ktss;
 };
 
 /*
@@ -63,7 +63,7 @@ extern struct mp_desc_table   *mp_desc_tab
 /*
  * The kernel TSS gets its own pointer.
  */
-extern struct i386_tss         *mp_ktss[NCPUS];
+extern struct task_tss         *mp_ktss[NCPUS];
 
 /*
  * So does the GDT.
Index: i386/i386/pcb.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/pcb.c,v
retrieving revision 1.2.4.9
diff -u -p -r1.2.4.9 pcb.c
--- i386/i386/pcb.c     4 Jan 2007 23:51:02 -0000       1.2.4.9
+++ i386/i386/pcb.c     25 Apr 2007 16:36:33 -0000
@@ -24,6 +24,7 @@
  * the rights to redistribute these changes.
  */
 
+#include <stddef.h>
 #include <string.h>
 
 #include <mach/std_types.h>
@@ -43,7 +44,6 @@
 #include <i386/thread.h>
 #include <i386/proc_reg.h>
 #include <i386/seg.h>
-#include <i386/tss.h>
 #include <i386/user_ldt.h>
 #include <i386/fpu.h>
 #include "eflags.h"
@@ -52,6 +52,8 @@
 #include "ktss.h"
 #include "pcb.h"
 
+#include <machine/tss.h>
+
 #if    NCPUS > 1
 #include <i386/mp_desc.h>
 #endif
@@ -59,8 +61,6 @@
 extern thread_t        Switch_context();
 extern void    Thread_continue();
 
-extern iopb_tss_t      iopb_create();
-extern void            iopb_destroy();
 extern void            user_ldt_free();
 
 zone_t         pcb_zone;
@@ -126,7 +126,7 @@ vm_offset_t stack_detach(thread)
 #define        curr_ktss(mycpu)        (mp_ktss[mycpu])
 #else
 #define        curr_gdt(mycpu)         ((void)(mycpu), gdt)
-#define        curr_ktss(mycpu)        ((void)(mycpu), &ktss)
+#define        curr_ktss(mycpu)        ((void)(mycpu), (struct task_tss 
*)&ktss)
 #endif
 
 #define        gdt_desc_p(mycpu,sel) \
@@ -137,7 +137,6 @@ void switch_ktss(pcb)
 {
        int                     mycpu = cpu_number();
     {
-       register iopb_tss_t     tss = pcb->ims.io_tss;
        vm_offset_t             pcb_stack_top;
 
        /*
@@ -153,25 +152,7 @@ void switch_ktss(pcb)
                        ? (int) (&pcb->iss + 1)
                        : (int) (&pcb->iss.v86_segs);
 
-       if (tss == 0) {
-           /*
-            *  No per-thread IO permissions.
-            *  Use standard kernel TSS.
-            */
-           if (!(gdt_desc_p(mycpu,KERNEL_TSS)->access & ACC_TSS_BUSY))
-               set_tr(KERNEL_TSS);
-           curr_ktss(mycpu)->esp0 = pcb_stack_top;
-       }
-       else {
-           /*
-            * Set the IO permissions.  Use this thread`s TSS.
-            */
-           *gdt_desc_p(mycpu,USER_TSS)
-               = *(struct real_descriptor *)tss->iopb_desc;
-           tss->tss.esp0 = pcb_stack_top;
-           set_tr(USER_TSS);
-           gdt_desc_p(mycpu,KERNEL_TSS)->access &= ~ ACC_TSS_BUSY;
-       }
+       curr_ktss(mycpu)->tss.esp0 = pcb_stack_top;
     }
 
     {
@@ -207,6 +188,24 @@ void switch_ktss(pcb)
 
 }
 
+/* If NEW_IOPB is not null, the SIZE denotes the number of bytes in
+   the new bitmap.  Expects iopb_lock to be held.  */
+void
+update_ktss_iopb (unsigned char *new_iopb, io_port_t size)
+{
+  struct task_tss *tss = curr_ktss (cpu_number ());
+
+  if (new_iopb && size > 0)
+    {
+      tss->tss.io_bit_map_offset
+       = offsetof (struct task_tss, barrier) - size;
+      memcpy (((char *) tss) + tss->tss.io_bit_map_offset,
+             new_iopb, size);
+    }
+  else
+    tss->tss.io_bit_map_offset = IOPB_INVAL;
+}
+
 /*
  *     stack_handoff:
  *
@@ -236,6 +235,19 @@ void stack_handoff(old, new)
                                     old, mycpu);
                PMAP_ACTIVATE_USER(vm_map_pmap(new_task->map),
                                   new, mycpu);
+
+               simple_lock (&new_task->machine.iopb_lock);
+#if NCPUS>1
+#warning SMP support missing (avoid races with io_perm_modify).
+#else
+               /* This optimization only works on a single processor
+                  machine, where old_task's iopb can not change while
+                  we are switching.  */
+               if (old_task->machine.iopb || new_task->machine.iopb)
+#endif
+                 update_ktss_iopb (new_task->machine.iopb,
+                                   new_task->machine.iopb_size);
+               simple_unlock (&new_task->machine.iopb_lock);
        }
     }
 
@@ -298,6 +310,19 @@ thread_t switch_context(old, continuatio
                                     old, mycpu);
                PMAP_ACTIVATE_USER(vm_map_pmap(new_task->map),
                                   new, mycpu);
+
+               simple_lock (&new_task->machine.iopb_lock);
+#if NCPUS>1
+#warning SMP support missing (avoid races with io_perm_modify).
+#else
+               /* This optimization only works on a single processor
+                  machine, where old_task's iopb can not change while
+                  we are switching.  */
+               if (old_task->machine.iopb || new_task->machine.iopb)
+#endif
+                 update_ktss_iopb (new_task->machine.iopb,
+                                   new_task->machine.iopb_size);
+               simple_unlock (&new_task->machine.iopb_lock);
        }
     }
 
@@ -317,7 +342,6 @@ void pcb_module_init()
                         0, "i386 pcb state");
 
        fpu_module_init();
-       iopb_init();
 }
 
 void pcb_init(thread)
@@ -361,8 +385,6 @@ void pcb_terminate(thread)
        counter(if (--c_threads_current < c_threads_min)
                        c_threads_min = c_threads_current);
 
-       if (pcb->ims.io_tss != 0)
-               iopb_destroy(pcb->ims.io_tss);
        if (pcb->ims.ifps != 0)
                fp_free(pcb->ims.ifps);
        if (pcb->ims.ldt != 0)
@@ -516,7 +538,6 @@ kern_return_t thread_setstatus(thread, f
             */
            case i386_ISA_PORT_MAP_STATE: {
                register struct i386_isa_port_map_state *state;
-               register iopb_tss_t     tss;
 
                if (count < i386_ISA_PORT_MAP_STATE_COUNT)
                        return(KERN_INVALID_ARGUMENT);
@@ -673,32 +694,20 @@ kern_return_t thread_getstatus(thread, f
             */
            case i386_ISA_PORT_MAP_STATE: {
                register struct i386_isa_port_map_state *state;
-               register iopb_tss_t tss;
 
                if (*count < i386_ISA_PORT_MAP_STATE_COUNT)
                        return(KERN_INVALID_ARGUMENT);
 
                state = (struct i386_isa_port_map_state *) tstate;
-               tss = thread->pcb->ims.io_tss;
-
-               if (tss == 0) {
-                   int i;
 
-                   /*
-                    *  The thread has no ktss, so no IO permissions.
-                    */
-
-                   for (i = 0; i < sizeof state->pm; i++)
-                       state->pm[i] = 0xff;
-               } else {
-                   /*
-                    *  The thread has its own ktss.
-                    */
-
-                   memcpy(state->pm,
-                          tss->bitmap,
-                          sizeof state->pm);
-               }
+               simple_lock (&thread->task->machine.iopb_lock);
+               if (thread->task->machine.iopb == 0)
+                 memset (state->pm, 0xff, sizeof state->pm);
+               else
+                 memcpy((char *) state->pm,
+                        (char *) thread->task->machine.iopb,
+                        sizeof state->pm);
+               simple_unlock (&thread->task->machine.iopb_lock);
 
                *count = i386_ISA_PORT_MAP_STATE_COUNT;
                break;
Index: i386/i386/task.h
===================================================================
RCS file: i386/i386/task.h
diff -N i386/i386/task.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ i386/i386/task.h    25 Apr 2007 16:36:33 -0000
@@ -0,0 +1,61 @@
+/* Data types for machine specific parts of tasks on i386.
+
+   Copyright (C) 2002, 2007 Free Software Foundation, Inc.
+
+   Written by Marcus Brinkmann.  Glued into GNU Mach by Thomas Schwinge.
+
+   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.
+
+   This program 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.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef        _I386_TASK_H_
+#define _I386_TASK_H_
+
+#include <kern/kern_types.h>
+#include <kern/zalloc.h>
+
+/* The machine specific data of a task.  */
+struct machine_task
+{
+  /* A lock protecting iopb_size and iopb.  */
+  decl_simple_lock_data (, iopb_lock);
+
+  /* The highest I/O port number enabled.  */
+  int iopb_size;
+
+  /* The I/O permission bitmap.  */
+  unsigned char *iopb;
+};
+typedef struct machine_task machine_task_t;
+
+
+extern zone_t machine_task_iopb_zone;
+
+/* Initialize the machine task module.  The function is called once at
+   start up by task_init in kern/task.c.  */
+void machine_task_module_init (void);
+
+/* Initialize the machine specific part of task TASK.  */
+void machine_task_init (task_t);
+
+/* Destroy the machine specific part of task TASK and release all
+   associated resources.  */
+void machine_task_terminate (task_t);
+
+/* Try to release as much memory from the machine specific data in
+   task TASK. */
+void machine_task_collect (task_t);
+
+#endif /* _I386_TASK_H_ */
Index: i386/i386/thread.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/thread.h,v
retrieving revision 1.3.2.1
diff -u -p -r1.3.2.1 thread.h
--- i386/i386/thread.h  5 Nov 2006 20:39:24 -0000       1.3.2.1
+++ i386/i386/thread.h  25 Apr 2007 16:36:33 -0000
@@ -39,7 +39,6 @@
 
 #include <kern/lock.h>
 
-#include <i386/iopb.h>
 #include <i386/tss.h>
 #include "gdt.h"
 
@@ -158,7 +157,6 @@ struct i386_interrupt_state {
  */
 
 struct i386_machine_state {
-       iopb_tss_t              io_tss;
        struct user_ldt *       ldt;
        struct i386_fpsave_state *ifps;
        struct v86_assist_state v86s;
Index: i386/i386/tss.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386/tss.h,v
retrieving revision 1.1
diff -u -p -r1.1 tss.h
--- i386/i386/tss.h     25 Feb 1997 21:27:12 -0000      1.1
+++ i386/i386/tss.h     25 Apr 2007 16:36:33 -0000
@@ -29,6 +29,8 @@
 
 #include <mach/inline.h>
 
+#include <machine/io_perm.h>
+
 /*
  *     i386 Task State Segment
  */
@@ -66,6 +68,17 @@ struct i386_tss {
                                           bit map */
 };
 
+
+/* The structure extends the above TSS structure by an I/O permission bitmap
+   and the barrier.  */
+struct task_tss
+ {
+  struct i386_tss tss;
+  unsigned char iopb[IOPB_BYTES];
+  unsigned char barrier;
+};
+
+
 /* Load the current task register.  */
 MACH_INLINE void
 ltr(unsigned short segment)
Index: i386/i386at/kd.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/i386at/Attic/kd.c,v
retrieving revision 1.5.2.12
diff -u -p -r1.5.2.12 kd.c
--- i386/i386at/kd.c    5 Feb 2007 21:09:36 -0000       1.5.2.12
+++ i386/i386at/kd.c    25 Apr 2007 16:36:34 -0000
@@ -84,7 +84,9 @@ WITH THE USE OR PERFORMANCE OF THIS SOFT
 #include <device/tty.h>
 #include <device/io_req.h>
 #include <device/buf.h>                /* for struct uio (!) */
+#if REMOVE_ME
 #include <i386/io_port.h>
+#endif
 #include <vm/vm_kern.h>
 #include <i386/vm_param.h>
 #include <i386/machspl.h>
@@ -333,6 +335,7 @@ unsigned char       key_map[NUMKEYS][WIDTH_KMA
 short  kd_index_reg    = EGA_IDX_REG;
 short  kd_io_reg       = EGA_IO_REG;
 
+#if REMOVE_ME
 /*
  * IO port sets for different controllers.
  */
@@ -360,6 +363,7 @@ kd_io_map_close()
        io_port_destroy(kd_io_device);
        kd_io_device = 0;
 }
+#endif /* REMOVE_ME */
 
 /*
  * Globals used only for bitmap-based controllers.  See kdsoft.h for
@@ -509,10 +513,12 @@ kdopen(dev, flag, ior)
                tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS;
                kdinit();
 
+#if REMOVE_ME
                /* XXX kd_io_map_open allocates memory */
                simple_unlock(&tp->t_lock);
                kd_io_map_open(ior->io_device);
                simple_lock(&tp->t_lock);
+#endif
        }
        tp->t_state |= TS_CARR_ON;
        simple_unlock(&tp->t_lock);
@@ -549,7 +555,9 @@ int flag;
            splx(s);
        }
 
+#if REMOVE_ME
        kd_io_map_close();
+#endif
 
        return;
 
Index: i386/include/mach/i386/mach_i386.defs
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/mach_i386.defs,v
retrieving revision 1.2.2.2
diff -u -p -r1.2.2.2 mach_i386.defs
--- i386/include/mach/i386/mach_i386.defs       25 Apr 2007 13:59:03 -0000      
1.2.2.2
+++ i386/include/mach/i386/mach_i386.defs       25 Apr 2007 16:36:34 -0000
@@ -35,26 +35,31 @@ subsystem
 
 #include <mach/std_types.defs>
 #include <mach/mach_types.defs>
-#include <device/device_types.defs>
-
-type   device_list_t   =       ^array[] of device_t;
 
 type   descriptor_t    =       struct[2] of int;
 type   descriptor_list_t =     array[*] of descriptor_t;
 
 import <mach/machine/mach_i386_types.h>;
 
-routine        i386_io_port_add(
-               target_thread   : thread_t;
-               device          : device_t);
-
-routine        i386_io_port_remove(
-               target_thread   : thread_t;
-               device          : device_t);
-
-routine        i386_io_port_list(
-               target_thread   : thread_t;
-       out     device_list     : device_list_t);
+#if    KERNEL_SERVER
+simport <machine/io_perm.h>;
+#endif
+
+type   io_port_t       =       MACH_MSG_TYPE_INTEGER_16;
+type   io_perm_t       =       mach_port_t
+               ctype: mach_port_t
+#if    KERNEL_SERVER
+               intran: io_perm_t convert_port_to_io_perm(mach_port_t)
+               outtran: mach_port_t convert_io_perm_to_port(io_perm_t)
+#if REMOVE_ME
+               destructor: io_perm_deallocate(io_perm_t)
+#endif
+#endif /* KERNEL_SERVER */
+               ;
+
+skip;  /* i386_io_port_add */
+skip;  /* i386_io_port_remove */
+skip;  /* i386_io_port_list */
 
 routine        i386_set_ldt(
                target_thread   : thread_t;
@@ -67,8 +72,27 @@ routine      i386_get_ldt(
                selector_count  : int;
        out     desc_list       : descriptor_list_t);
 
-skip;  /* i386_io_perm_create */
-skip;  /* i386_io_perm_modify */
+/* Request a new port IO_PERM that represents the capability to access
+   the I/O ports [FROM; TO] directly.  MASTER_PORT is the master device port.
+
+   The function returns KERN_INVALID_ARGUMENT if TARGET_TASK is not a task,
+   or FROM is greater than TO.  */
+routine        i386_io_perm_create(
+               master_port     : mach_port_t;
+               from            : io_port_t;
+               to              : io_port_t;
+       out     io_perm         : io_perm_t);
+
+/* Modify the I/O permissions for TARGET_TASK.  If ENABLE is TRUE, the
+   permission to access the I/O ports specified by IO_PERM is granted,
+   otherwise it is withdrawn.
+
+   The function returns KERN_INVALID_ARGUMENT if TARGET_TASK is not a valid
+   task or IO_PERM not a valid I/O permission port.  */
+routine        i386_io_perm_modify(
+               target_task     : task_t;
+               io_perm         : io_perm_t;
+               enable          : boolean_t);
 
 /* Modify one of a few available thread-specific segment descriptor slots.
    The SELECTOR must be a value from a previous call (on any thread),
Index: i386/include/mach/i386/mach_i386_types.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/i386/include/mach/i386/mach_i386_types.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 mach_i386_types.h
--- i386/include/mach/i386/mach_i386_types.h    25 Feb 1997 21:27:00 -0000      
1.1.1.1
+++ i386/include/mach/i386/mach_i386_types.h    25 Apr 2007 16:36:34 -0000
@@ -31,11 +31,6 @@
 #define        _MACH_MACH_I386_TYPES_H_
 
 /*
- * Array of devices.
- */
-typedef        device_t        *device_list_t;
-
-/*
  * i386 segment descriptor.
  */
 struct descriptor {
@@ -46,4 +41,15 @@ struct descriptor {
 typedef struct descriptor descriptor_t;
 typedef        struct descriptor *descriptor_list_t;
 
+/*
+ * i386 I/O port
+ */
+
+#ifdef MACH_KERNEL
+#include <i386/io_perm.h>
+#else
+typedef unsigned short io_port_t;
+typedef mach_port_t io_perm_t;
+#endif
+
 #endif /* _MACH_MACH_I386_TYPES_H_ */
Index: include/stddef.h
===================================================================
RCS file: include/stddef.h
diff -N include/stddef.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/stddef.h    25 Apr 2007 16:36:35 -0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * 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.
+ * 
+ * This program 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _STDDEF_H_
+#define _STDDEF_H_
+
+/* From GCC's `/lib/gcc/X/X/include/stddef.h'.  */
+
+/* Offset of member MEMBER in a struct of type TYPE.  */
+#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
+
+#endif /* _STDDEF_H_ */
Index: kern/task.c
===================================================================
RCS file: /cvsroot/hurd/gnumach/kern/task.c,v
retrieving revision 1.3.4.7
diff -u -p -r1.3.4.7 task.c
--- kern/task.c 4 Jan 2007 23:51:02 -0000       1.3.4.7
+++ kern/task.c 25 Apr 2007 16:36:35 -0000
@@ -67,6 +67,7 @@ void task_init(void)
                        0, "tasks");
 
        eml_init();
+       machine_task_module_init ();
 
        /*
         * Create the kernel task as the first task.
@@ -145,6 +146,7 @@ kern_return_t task_create(
        eml_task_reference(new_task, parent_task);
 
        ipc_task_init(new_task, parent_task);
+       machine_task_init (new_task);
 
        new_task->total_user_time.seconds = 0;
        new_task->total_user_time.microseconds = 0;
@@ -220,6 +222,8 @@ void task_deallocate(
        if (c != 0)
                return;
 
+       machine_task_terminate (task);
+
        eml_task_deallocate(task);
 
        pset = task->processor_set;
@@ -1092,6 +1096,7 @@ void task_collect_scan(void)
                        pset_unlock(pset);
                        simple_unlock(&all_psets_lock);
 
+                       machine_task_collect (task);
                        pmap_collect(task->map->pmap);
 
                        if (prev_task != TASK_NULL)
Index: kern/task.h
===================================================================
RCS file: /cvsroot/hurd/gnumach/kern/task.h,v
retrieving revision 1.3.2.3
diff -u -p -r1.3.2.3 task.h
--- kern/task.h 15 Oct 2006 14:59:04 -0000      1.3.2.3
+++ kern/task.h 25 Apr 2007 16:36:35 -0000
@@ -46,6 +46,7 @@
 #include <kern/processor.h>
 #include <kern/syscall_emulation.h>
 #include <vm/vm_map.h>
+#include <machine/task.h>
 
 struct task {
        /* Synchronization/destruction information */
@@ -98,6 +99,9 @@ struct task {
        vm_offset_t     fast_tas_base[TASK_FAST_TAS_NRAS];
        vm_offset_t     fast_tas_end[TASK_FAST_TAS_NRAS];
 #endif /* FAST_TAS */
+
+       /* Hardware specific data.  */
+       machine_task_t  machine;
 };
 
 #define task_lock(task)                simple_lock(&(task)->lock)
#v-


Regards,
 Thomas

Attachment: signature.asc
Description: Digital signature


reply via email to

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