bug-hurd
[Top][All Lists]
Advanced

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

Re: I/O permission bitmap patch for oskit-mach


From: Marcus Brinkmann
Subject: Re: I/O permission bitmap patch for oskit-mach
Date: Fri, 8 Mar 2002 01:39:49 +0100
User-agent: Mutt/1.3.27i

On Wed, Mar 06, 2002 at 02:58:56AM -0500, Roland McGrath wrote:
> Please add -p to your diff switches.

At one time I will learn it, sorry.  I did it this time.
 
> For ktss, don't use a weak alias, use a strong one.

Done (I needed to put "ktss" in parenthesis).

> I don't see a reason to zalloc the struct machine_task.  Why not just have
> the struct task member be a struct instead of a pointer? 

Done.  I didn't pursue the opaqueness anyway (the struct was already defined
in the header).

> For the SMP problem, it would certainly be simple to hack the existing
> check_io_fault code to notice when the task's iopb has changed, reload it,
> and retry the instruction.  But I am really not concerned about this
> problem cropping up in practice--certainly it won't before we finish making
> SMP work at all! :)

:)

> In io_bitmap_init, just use memset.  That's what it's for.

Ok, done.  I also removed the second argument, we always initialize to no
permission by default.  Now the function became pretty pointless, but, oh well.

> Might as well use io_port_t for fields like iopb_size.

Done.

I also included another patch I forgot, that is making dev_open_alloc and
setup_no_senders non-static, because I need them when setting up the pseudo
device, and fixed three warnings.  It compiles, but I did not run it
(changes are quite small, I can give it a last try before we check it in or
so).

Thanks,
Marcus

diff -ruNp oskit-mach/ChangeLog.oskit oskit-mach.new/ChangeLog.oskit
--- oskit-mach/ChangeLog.oskit  Fri Mar  8 00:29:11 2002
+++ oskit-mach.new/ChangeLog.oskit      Fri Mar  8 01:22:47 2002
@@ -1,3 +1,64 @@
+2002-02-27  Marcus Brinkmann  <marcus@gnu.org>
+
+       * bogus/mach_machine_routines.h (MACH_MACHINE_ROUTINES): Set to 1.
+       * i386/i386/io_perm.h: New file.
+       * i386/i386/io_perm.c: New file.
+       * i386/i386/machine_task.c: New file.
+       * i386/Makefrag (i386-files): Add io_perm.c and machine_task.c.
+       * i386/i386/mp_desc.h: Include `machine/tss.h' instead
+       `oskit/x86/tss.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/i386/tss.h: New file.
+       * i386/include/mach/i386/mach_i386.defs: Do not include
+       `mach/machine/mach_i386_types.h'.
+       [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_removed): 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.
+       * oskit/x86/main.c: Include `i386/io_perm.h' and `machine/tss.h'.
+       (ktss): New static global variable that replaces base_tss at link
+       time.
+       (main): Set up the base_tss to include an I/O permission bitmap.
+       * oskit/ds_oskit.h [__i386__]: Include `machine/io_perm.h'.
+       (struct device) [__i386__]: Add a structure with io_perm range
+       to the com union.
+       * oskit/ds_routines.c (dev_open_alloc): Remove static attribute.
+       (setup_no_senders): Likewise.
+
 2002-02-28  Marcus Brinkmann <marcus@gnu.org>
 
         * oskit/ds_routines.c (device_deallocate): Allow DEVICE->com_device
diff -ruNp oskit-mach/bogus/mach_machine_routines.h 
oskit-mach.new/bogus/mach_machine_routines.h
--- oskit-mach/bogus/mach_machine_routines.h    Tue Feb 25 22:28:04 1997
+++ oskit-mach.new/bogus/mach_machine_routines.h        Fri Mar  8 00:34:38 2002
@@ -1 +1 @@
-#define MACH_MACHINE_ROUTINES 0
+#define MACH_MACHINE_ROUTINES 1
diff -ruNp oskit-mach/i386/Makefrag oskit-mach.new/i386/Makefrag
--- oskit-mach/i386/Makefrag    Tue Feb 27 04:10:18 2001
+++ oskit-mach.new/i386/Makefrag        Fri Mar  8 00:34:38 2002
@@ -20,7 +20,7 @@ DEFINES += -D__ELF__=1 -Di386=1 -DAT386=
 i386at-files = int_init.c pic_isa.c
 i386-files = ast_check.c fpu.c gdt.c idt.c ldt.c \
             mp_desc.c pcb.c phys.c pic.c pit.c trap.c user_ldt.c \
-            hardclock.c # loose_ends.c
+            hardclock.c io_perm.c machine_task.c # loose_ends.c
 intel-files = pmap.c read_fault.c
 
 # Assembler source
diff -ruNp oskit-mach/i386/i386/io_perm.c oskit-mach.new/i386/i386/io_perm.c
--- oskit-mach/i386/i386/io_perm.c      Thu Jan  1 01:00:00 1970
+++ oskit-mach.new/i386/i386/io_perm.c  Fri Mar  8 01:27:36 2002
@@ -0,0 +1,242 @@
+/* io_perm.c - Code to manipulate I/O permission bitmap objects.
+   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. */
+
+/*
+ * 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 <mach/boolean.h>
+#include <mach/kern_return.h>
+
+#include <ipc/ipc_port.h>
+
+#include <kern/kalloc.h>
+#include <kern/lock.h>
+#include <kern/queue.h>
+#include <kern/thread.h>
+
+#include <device/dev_hdr.h>
+#include <device/device_port.h>
+
+#include <oskit/ds_oskit.h>
+
+#include "io_perm.h"
+#include "gdt.h"
+
+
+/* XXX From oskit/ds_routines.c  */
+device_t dev_open_alloc (void);
+void setup_no_senders (device_t dev);
+
+
+/* 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)
+{
+  return convert_device_to_port ((device_t) io_perm);
+}
+
+
+/* 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)
+{
+  return (io_perm_t) dev_port_lookup (port);
+}
+
+
+/* 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)
+{
+  device_deallocate ((device_t) io_perm);
+}
+
+
+/* Initialize bitmap by setting all bits to OFF == 1.  */
+void
+io_bitmap_init (unsigned char *iopb)
+{
+  memset (iopb, ~0, IOPB_BYTES);
+}
+
+
+/* Set selected bits in bitmap to ON == 0.  */
+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.  */
+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)
+{
+  if (master_port != master_device_port || from > to)
+    return KERN_INVALID_ARGUMENT;
+
+  *new = (io_perm_t) dev_open_alloc ();
+  if (! *new)
+    return KERN_RESOURCE_SHORTAGE;
+
+  /* Set up the dummy device.  */
+  (*new)->com_device = 0;
+  (*new)->mode = 0;
+  (*new)->ops = &no_device_ops;
+  setup_no_senders ((device_t) *new);
+
+  (*new)->com.io_perm.from = from;
+  (*new)->com.io_perm.to = to;
+
+  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 || (device_t) io_perm == DEVICE_NULL)
+    return KERN_INVALID_ARGUMENT;
+
+  from = io_perm->com.io_perm.from;
+  to = io_perm->com.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);
+      iopb = (unsigned char *) kalloc (IOPB_BYTES);
+      simple_lock (&target_task->machine.iopb_lock);
+      if (target_task->machine.iopb)
+       {
+         if (iopb)
+           kfree ((vm_offset_t) iopb, IOPB_BYTES);
+         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
+       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, io_perm->com.io_perm.from,
+                      io_perm->com.io_perm.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;
+}
diff -ruNp oskit-mach/i386/i386/io_perm.h oskit-mach.new/i386/i386/io_perm.h
--- oskit-mach/i386/i386/io_perm.h      Thu Jan  1 01:00:00 1970
+++ oskit-mach.new/i386/i386/io_perm.h  Fri Mar  8 00:34:38 2002
@@ -0,0 +1,48 @@
+/* io_perm.h - Data types for I/O permission bitmap objects.
+   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. */
+
+#ifndef _I386_IO_PERM_H_
+#define _I386_IO_PERM_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 device is defined in <oskit/ds_oskit.h>, which includes this
+   file for the io_port_t type definition above.  */
+typedef struct device *io_perm_t;
+
+extern io_perm_t convert_port_to_io_perm (/* struct ipc_port * */);
+extern struct ipc_port *convert_io_perm_to_port(/* io_perm_t */);
+extern void io_perm_deallocate(/* io_perm_t */);
+
+#endif
diff -ruNp oskit-mach/i386/i386/machine_task.c 
oskit-mach.new/i386/i386/machine_task.c
--- oskit-mach/i386/i386/machine_task.c Thu Jan  1 01:00:00 1970
+++ oskit-mach.new/i386/i386/machine_task.c     Fri Mar  8 00:44:35 2002
@@ -0,0 +1,70 @@
+/* machine_task.h - Machine specific data for a task on i386.
+   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. */
+
+#include <kern/lock.h>
+#include <mach/mach_types.h>
+#include <kern/mach_param.h>
+#include <machine/task.h>
+
+#include <machine/io_perm.h>
+
+/* The zone which holds our machine_task_t structures.  */
+static zone_t machine_task_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 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)
+    kfree ((vm_offset_t) task->machine.iopb, IOPB_BYTES);
+}
+
+
+/* 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)
+    {
+      kfree ((vm_offset_t) task->machine.iopb, IOPB_BYTES);
+      task->machine.iopb = 0;
+    }
+}
diff -ruNp oskit-mach/i386/i386/mp_desc.c oskit-mach.new/i386/i386/mp_desc.c
--- oskit-mach/i386/i386/mp_desc.c      Sun Mar  3 18:39:22 2002
+++ oskit-mach.new/i386/i386/mp_desc.c  Fri Mar  8 00:34:38 2002
@@ -52,7 +52,8 @@ vm_offset_t   int_stack_high;
 #include <oskit/x86/base_idt.h>
 #include "gdt.h"
 #include <oskit/x86/base_tss.h>
-
+#include <machine/tss.h>
+#include <machine/io_perm.h>
 
 /*
  * The i386 needs an interrupt stack to keep the PCB stack from being
@@ -83,7 +84,7 @@ struct mp_desc_table  *mp_desc_table[NCPU
 /*
  * Pointer to TSS for access in load_context.
  */
-struct x86_tss         *mp_ktss[NCPUS];
+struct task_tss        *mp_ktss[NCPUS];
 
 /*
  * Pointer to GDT to reset the KTSS busy bit.
@@ -105,7 +106,7 @@ mp_desc_init(mycpu)
                 * Master CPU uses the tables built at boot time.
                 * Just set the TSS and GDT pointers.
                 */
-               mp_ktss[mycpu] = &base_tss;
+               mp_ktss[mycpu] = (struct task_tss *) &base_tss;
                mp_gdt[mycpu] = gdt;
                return 0;
        }
@@ -138,7 +139,7 @@ mp_desc_init(mycpu)
                        ACC_P|ACC_PL_K|ACC_LDT, 0);
                fill_descriptor(&mpt->gdt[sel_idx(KERNEL_TSS)],
                        (unsigned)kvtolin(&mpt->ktss),
-                       sizeof(struct x86_tss) - 1,
+                       sizeof(struct task_tss) - 1,
                        ACC_P|ACC_PL_K|ACC_TSS, 0);
 
                /*
@@ -150,8 +151,9 @@ mp_desc_init(mycpu)
                        (unsigned)kvtolin(&mpt->cpu_number), sizeof(int) - 1,
                        ACC_P|ACC_PL_K|ACC_DATA, 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;
        }
diff -ruNp oskit-mach/i386/i386/mp_desc.h oskit-mach.new/i386/i386/mp_desc.h
--- oskit-mach/i386/i386/mp_desc.h      Tue Apr 10 20:39:05 2001
+++ oskit-mach.new/i386/i386/mp_desc.h  Fri Mar  8 00:34:38 2002
@@ -43,7 +43,7 @@
 #include <mach/std_types.h>
 
 #include <oskit/x86/base_idt.h>        /* IDTSZ */
-#include <oskit/x86/tss.h>
+#include <machine/tss.h>
 
 #include "gdt.h"
 #include "ldt.h"
@@ -57,7 +57,7 @@ struct mp_desc_table {
        struct x86_gate idt[IDTSZ];     /* IDT */
        struct x86_desc gdt[GDTSZ];     /* GDT */
        struct x86_desc ldt[LDTSZ];     /* LDT */
-       struct x86_tss  ktss;
+       struct task_tss ktss;
 };
 
 /*
@@ -68,7 +68,7 @@ extern struct mp_desc_table   *mp_desc_tab
 /*
  * The kernel TSS gets its own pointer.
  */
-extern struct x86_tss          *mp_ktss[NCPUS];
+extern struct task_tss *mp_ktss[NCPUS];
 
 /*
  * So does the GDT.
diff -ruNp oskit-mach/i386/i386/pcb.c oskit-mach.new/i386/i386/pcb.c
--- oskit-mach/i386/i386/pcb.c  Tue Oct 31 00:57:25 2000
+++ oskit-mach.new/i386/i386/pcb.c      Fri Mar  8 01:20:13 2002
@@ -24,6 +24,8 @@
  * the rights to redistribute these changes.
  */
 
+#include <stddef.h>
+
 #include <cpus.h>
 #include <mach_debug.h>
 
@@ -52,6 +54,8 @@
 #include <oskit/x86/base_tss.h>
 #include <oskit/x86/proc_reg.h>
 
+#include <machine/tss.h>
+
 #if    NCPUS > 1
 #include <i386/mp_desc.h>
 #endif
@@ -59,8 +63,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 +128,7 @@ vm_offset_t stack_detach(thread)
 #define        curr_ktss(mycpu)        (mp_ktss[mycpu])
 #else
 #define        curr_gdt(mycpu)         (gdt)
-#define        curr_ktss(mycpu)        (&base_tss)
+#define        curr_ktss(mycpu)        ((struct task_tss *)&base_tss)
 #endif
 
 #define        gdt_desc_p(mycpu,sel) \
@@ -137,7 +139,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 +154,7 @@ void switch_ktss(pcb)
                        ? (int) (&pcb->iss + 1)
                        : (int) (&pcb->iss.v86_es);
 
-       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 x86_desc *)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;
     }
 
     {
@@ -200,6 +183,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:
  *
@@ -229,6 +230,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);
        }
     }
 
@@ -310,7 +324,6 @@ void pcb_module_init()
                         0, "i386 pcb state");
 
        fpu_module_init();
-       iopb_init();
 }
 
 void pcb_init(thread)
@@ -354,8 +367,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)
@@ -509,7 +520,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);
@@ -666,32 +676,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.
-                    */
-
-                   bcopy((char *) tss->bitmap,
-                         (char *) state->pm,
-                         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;
diff -ruNp oskit-mach/i386/i386/task.h oskit-mach.new/i386/i386/task.h
--- oskit-mach/i386/i386/task.h Thu Jan  1 01:00:00 1970
+++ oskit-mach.new/i386/i386/task.h     Fri Mar  8 00:41:59 2002
@@ -0,0 +1,57 @@
+/* task.h - Data types for machine specific parts of tasks on i386.
+   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. */
+
+#ifndef        _I386_TASK_H_
+#define _I386_TASK_H_
+
+#include <kern/kern_types.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;
+
+
+/* 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_ */
diff -ruNp oskit-mach/i386/i386/thread.h oskit-mach.new/i386/i386/thread.h
--- oskit-mach/i386/i386/thread.h       Tue Apr 10 20:39:06 2001
+++ oskit-mach.new/i386/i386/thread.h   Fri Mar  8 00:34:38 2002
@@ -39,8 +39,6 @@
 
 #include <kern/lock.h>
 
-#include <i386/iopb.h>
-
 /*
  * The old `struct i386_saved_state' is replaced by the (identical)
  * OSKit `struct trap_state'.
@@ -129,7 +127,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;
diff -ruNp oskit-mach/i386/i386/tss.h oskit-mach.new/i386/i386/tss.h
--- oskit-mach/i386/i386/tss.h  Thu Jan  1 01:00:00 1970
+++ oskit-mach.new/i386/i386/tss.h      Fri Mar  8 00:34:38 2002
@@ -0,0 +1,36 @@
+/* tss.h - Data type for TSS with an I/O permission bitmap.
+   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. */
+
+#ifndef _I386_TSS_H_
+#define _I386_TSS_H_
+
+#include <oskit/x86/tss.h>
+#include <machine/io_perm.h>
+
+/* The structure extends the TSS structure provided by OSKit by an I/O
+   permission bitmap and the barrier.  */
+struct task_tss
+{
+  struct x86_tss tss;
+  unsigned char iopb[IOPB_BYTES];
+  unsigned char barrier;
+};
+
+#endif  /* _I386_TSS_H_ */
diff -ruNp oskit-mach/i386/include/mach/i386/mach_i386.defs 
oskit-mach.new/i386/include/mach/i386/mach_i386.defs
--- oskit-mach/i386/include/mach/i386/mach_i386.defs    Tue Apr 10 20:39:09 2001
+++ oskit-mach.new/i386/include/mach/i386/mach_i386.defs        Fri Mar  8 
00:34:38 2002
@@ -42,19 +42,25 @@ type        device_list_t   =       ^array[] of device_
 type   descriptor_t    =       struct[2] of int;
 type   descriptor_list_t =     array[*] of descriptor_t;
 
-import <mach/machine/mach_i386_types.h>;
+#if    KERNEL_SERVER
+simport <machine/io_perm.h>;
+#endif
 
-routine        i386_io_port_add(
-               target_thread   : thread_t;
-               device          : device_t);
+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)
+               destructor: io_perm_deallocate(io_perm_t)
+#endif /* KERNEL_SERVER */
+               ;
 
-routine        i386_io_port_remove(
-               target_thread   : thread_t;
-               device          : device_t);
+import <mach/machine/mach_i386_types.h>;
 
-routine        i386_io_port_list(
-               target_thread   : thread_t;
-       out     device_list     : device_list_t);
+skip;  /* i386_io_port_add */
+skip;  /* i386_io_port_remove */
+skip;  /* i386_io_port_list */
 
 routine        i386_set_ldt(
                target_thread   : thread_t;
@@ -66,3 +72,25 @@ routine      i386_get_ldt(
                first_selector  : int;
                selector_count  : int;
        out     desc_list       : descriptor_list_t);
+
+/* 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 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.  */
+routine i386_io_perm_modify(
+               target_task     : task_t;
+               io_perm         : io_perm_t;
+               enable          : boolean_t);
diff -ruNp oskit-mach/i386/include/mach/i386/mach_i386_types.h 
oskit-mach.new/i386/include/mach/i386/mach_i386_types.h
--- oskit-mach/i386/include/mach/i386/mach_i386_types.h Tue Feb 25 22:27:00 1997
+++ oskit-mach.new/i386/include/mach/i386/mach_i386_types.h     Fri Mar  8 
00:34:38 2002
@@ -46,4 +46,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_ */
diff -ruNp oskit-mach/kern/task.c oskit-mach.new/kern/task.c
--- oskit-mach/kern/task.c      Mon May 24 18:47:15 1999
+++ oskit-mach.new/kern/task.c  Fri Mar  8 00:34:38 2002
@@ -78,6 +78,7 @@ void task_init(void)
                        0, "tasks");
 
        eml_init();
+       machine_task_module_init ();
 
        /*
         * Create the kernel task as the first task.
@@ -160,6 +161,7 @@ kern_return_t task_create(
 #if    NET_ATM
        new_task->nw_ep_owned = 0;
 #endif
+       machine_task_init (new_task);
 
        new_task->total_user_time.seconds = 0;
        new_task->total_user_time.microseconds = 0;
@@ -247,6 +249,8 @@ void task_deallocate(
        }
 #endif /* NORMA_TASK */
 
+       machine_task_terminate (task);
+
        eml_task_deallocate(task);
 
        pset = task->processor_set;
@@ -1126,6 +1130,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)
diff -ruNp oskit-mach/kern/task.h oskit-mach.new/kern/task.h
--- oskit-mach/kern/task.h      Tue Apr 10 20:39:18 2001
+++ oskit-mach.new/kern/task.h  Fri Mar  8 00:34:38 2002
@@ -50,6 +50,7 @@
 #include <kern/processor.h>
 #include <kern/syscall_emulation.h>
 #include <vm/vm_map.h>
+#include <machine/task.h>
 
 #if    NET_ATM
 typedef struct nw_ep_owned {
@@ -117,6 +118,9 @@ struct task {
 #if    NET_ATM
        nw_ep_owned_t   nw_ep_owned;
 #endif /* NET_ATM */
+
+       /* Hardware specific data.  */
+       machine_task_t machine;
 };
 
 #define task_lock(task)                simple_lock(&(task)->lock)
diff -ruNp oskit-mach/oskit/ds_oskit.h oskit-mach.new/oskit/ds_oskit.h
--- oskit-mach/oskit/ds_oskit.h Fri Mar  8 00:29:11 2002
+++ oskit-mach.new/oskit/ds_oskit.h     Fri Mar  8 00:34:38 2002
@@ -54,6 +54,9 @@ struct device_ops {
 #include <oskit/io/asyncio.h>
 #include <oskit/dev/net.h>
 #include <oskit/io/netio.h>
+#if defined(__i386__)
+#include <machine/io_perm.h>
+#endif
 
 struct device {
   const struct device_ops *ops;
@@ -105,6 +108,12 @@ struct device {
       oskit_netio_t recvi;     /* my life as a COM object: incoming packets */
       struct ifnet ifnet;      /* cruft for net_io.c */
     } net;
+#if defined(__i386__)
+    struct
+    {
+      io_port_t from, to;
+    } io_perm;
+#endif
   } com;
 };
 
diff -ruNp oskit-mach/oskit/ds_routines.c oskit-mach.new/oskit/ds_routines.c
--- oskit-mach/oskit/ds_routines.c      Fri Mar  8 00:29:12 2002
+++ oskit-mach.new/oskit/ds_routines.c  Fri Mar  8 01:27:44 2002
@@ -292,7 +292,7 @@ dev_port_lookup(port)
 /*** Opening devices.  ***/
 
 
-static device_t
+device_t
 dev_open_alloc (void)
 {
   device_t dev = (device_t) zalloc (dev_hdr_zone);
@@ -317,7 +317,7 @@ dev_open_alloc (void)
 }
 
 
-static void
+void
 setup_no_senders (device_t dev)
 {
   ipc_port_t notify;
diff -ruNp oskit-mach/oskit/x86/main.c oskit-mach.new/oskit/x86/main.c
--- oskit-mach/oskit/x86/main.c Sun Mar  3 18:39:27 2002
+++ oskit-mach.new/oskit/x86/main.c     Fri Mar  8 01:18:51 2002
@@ -43,6 +43,14 @@
 
 #include <kern/cpu_number.h>
 
+/* The BASE_TSS in OSKit has no I/O permission bitmap, but we want
+   one.  So we replace it with an extended TSS at link-time.  */
+#include <machine/tss.h>
+#include <machine/io_perm.h>
+static struct task_tss ktss;
+extern struct x86_tss base_tss __attribute__ ((alias ("ktss")));
+#define base_tss ktss
+
 /* As of 2000-12-21 the oskit has an incorrect value for this constant
    in <oskit/x86/proc_reg.h>, so we redefine it with the correct one.  */
 #undef CR4_PGE
@@ -145,6 +153,14 @@ main (int argc, char **argv)
   int_init();
   ldt_init();
 
+  /* Set up the BASE_TSS to include an I/O permission bitmap.  */
+  fill_descriptor(&base_gdt[sel_idx(BASE_TSS)],
+                 kvtolin(&base_tss),
+                 sizeof(struct task_tss) - 1,
+                 ACC_P|ACC_PL_K|ACC_TSS, 0);
+  base_tss.tss.io_bit_map_offset = IOPB_INVAL;
+  base_tss.barrier = 0xFF;
+  /* This will also reload the TSS.  */
   base_cpu_load();
 
   /* Arrange a callback to our special exit function below, so we can


-- 
`Rhubarb is no Egyptian god.' Debian http://www.debian.org brinkmd@debian.org
Marcus Brinkmann              GNU    http://www.gnu.org    marcus@gnu.org
Marcus.Brinkmann@ruhr-uni-bochum.de
http://www.marcus-brinkmann.de



reply via email to

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