summaryrefslogtreecommitdiff
path: root/i386/i386/pcb.c
diff options
context:
space:
mode:
authorThomas Schwinge <tschwinge@gnu.org>2007-05-07 22:04:54 +0000
committerThomas Schwinge <tschwinge@gnu.org>2009-06-18 00:27:10 +0200
commit2c1f7f5ef7e2252312ecfa77b2352e89669006bf (patch)
tree503d5b28de51384b4789b75a8ec506132c795349 /i386/i386/pcb.c
parent029ea3ffa9e56d33eef2e859c98848f722f63b1c (diff)
2007-05-07 Thomas Schwinge <tschwinge@gnu.org>
[bug #15295 --- ``Mach lets processes write to I/O ports''] * 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'. * i386/i386/io_port.h: Remove file. * i386/i386at/kd.c: Don't include <i386/io_port.h>. (vga_port_list, kd_io_device, kd_io_map_open, kd_io_map_close): Don't define and don't use anymore. * include/stddef.h: New file. * i386/i386/io_perm.c: Include <string.h>, <device/device_emul.h>, <ipc/ipc_space.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-05-07 Marcus Brinkmann <marcus@gnu.org> [bug #15295 --- ``Mach lets processes write to I/O ports''] * 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.
Diffstat (limited to 'i386/i386/pcb.c')
-rw-r--r--i386/i386/pcb.c105
1 files changed, 57 insertions, 48 deletions
diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
index 1b24557..58b4ea9 100644
--- a/i386/i386/pcb.c
+++ b/i386/i386/pcb.c
@@ -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, continuation, 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);
}
}
@@ -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, flavor, tstate, count)
*/
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, flavor, tstate, count)
*/
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;