diff options
author | Thomas Schwinge <tschwinge@gnu.org> | 2007-05-07 22:04:54 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-06-18 00:27:10 +0200 |
commit | 2c1f7f5ef7e2252312ecfa77b2352e89669006bf (patch) | |
tree | 503d5b28de51384b4789b75a8ec506132c795349 /i386/i386/pcb.c | |
parent | 029ea3ffa9e56d33eef2e859c98848f722f63b1c (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.c | 105 |
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; |