[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
gnumach, task based IO ports
From: |
Alfred M. Szmidt |
Subject: |
gnumach, task based IO ports |
Date: |
Sun, 08 Jan 2006 18:03:17 +0100 |
Could you gives some explanation about this patch? I haven't looked
at it yet, and I don't recall any discussion about it. I only touched
the ChangeLog in a couple of places, since I'm more interested in a
discussion behind why this patch is needed, etc.
2006-01-02 Samuel Thibault <samuel.thibault@ens-lyon.org>
* iopb.c: IO ports permissions are now task-based.
(i386_io_port_add): Fix TSS access and locking accordingly.
(i386_io_port_remove): Same as above.
(i386_io_port_list): Same as above.
(iopb_check_mapping): Same as above.
* pcb.c (switch_ktss): Now takes next thread as parameter for
TSS switch to be task-based.
(stack_handoff): Fix parameter of switch_ktss calls.
(switch_context): Same as above.
(pcb_module_init): Move iopb initialization to new
machine_task_module_init() function.
(pcb_terminate): Move iopb termination to new
machine_task_termination() function.
(machine_task_module_init): New function.
(machine_task_init): New function.
(machine_task_terminate): New function.
(machine_task_collect): New function.
(thread_setstatus): TSS is now task-based, fix TSS and locking
accordingly.
(thread_getstatus): Same as above.
* io_emulate.c (emulate_io): Fix parameter of switch_ktss call.
* thread.h (i386_machine_state): Move io_tss member to...
(machine_task): this new structure.
* user_ldt.c (i386_set_ldt): Fix parameter of switch_ktss call.
diff -urp gnumach-mine-4-more_ports/i386/i386/iopb.c
gnumach-mine-5-io_per_task/i386/i386/iopb.c
--- gnumach-mine-4-more_ports/i386/i386/iopb.c 2006-01-02 18:42:45.000000000
+0100
+++ gnumach-mine-5-io_per_task/i386/i386/iopb.c 2005-12-29 23:42:34.000000000
+0100
@@ -65,8 +65,8 @@
/*
* Cross-reference:
- * all threads that have IO ports mapped
- * all IO ports that have threads mapped
+ * all tasks that have IO ports mapped
+ * all IO ports that have tasks mapped
*/
struct io_use {
queue_chain_t psq; /* Links from port set */
@@ -306,7 +306,7 @@
}
/*
- * Add an IO mapping to a thread.
+ * Add an IO mapping to a task.
*/
#ifdef i386
kern_return_t
@@ -320,7 +320,7 @@ i386_io_port_add(
mach_device_t device)
#endif
{
- pcb_t pcb;
+ task_t task;
#ifdef i386
mach_device_t device = d->emul_data;
#endif
@@ -332,7 +332,7 @@ i386_io_port_add(
|| device == DEVICE_NULL)
return KERN_INVALID_ARGUMENT;
- pcb = thread->pcb;
+ task = thread->task;
new_io_tss = 0;
iu = (io_use_t) kalloc(sizeof(struct io_use));
@@ -355,16 +355,16 @@ i386_io_port_add(
/* Have the IO port. */
- /* Make sure the thread has a TSS. */
+ /* Make sure the task has a TSS. */
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
+ task_lock(task);
+ io_tss = task->machine.io_tss;
if (io_tss == 0) {
if (new_io_tss == 0) {
/*
* Allocate an IO-tss.
*/
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
new_io_tss = (iopb_tss_t) kalloc(sizeof(struct iopb_tss));
@@ -373,7 +373,12 @@ i386_io_port_add(
goto Retry;
}
io_tss = new_io_tss;
- pcb->ims.io_tss = io_tss;
+ task->machine.io_tss = io_tss;
+
+ /* Update hardware if needed. */
+ if (task == current_thread()->task)
+ switch_ktss(thread);
+
new_io_tss = 0;
}
@@ -386,7 +391,7 @@ i386_io_port_add(
/*
* Already mapped.
*/
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
kfree((vm_offset_t)iu, sizeof(struct io_use));
@@ -405,7 +410,7 @@ i386_io_port_add(
queue_enter(&io_tss->io_port_list, iu, io_use_t, tsq);
io_bitmap_set(io_tss->bitmap, io_port->io_port_list);
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
if (new_io_tss)
@@ -415,7 +420,7 @@ i386_io_port_add(
}
/*
- * Remove an IO mapping from a thread.
+ * Remove an IO mapping from a task.
*/
#ifdef i386
kern_return_t
@@ -429,7 +434,7 @@ i386_io_port_remove(thread, device)
mach_device_t device;
#endif
{
- pcb_t pcb;
+ task_t task;
#ifdef i386
mach_device_t device = d->emul_data;
#endif
@@ -441,7 +446,7 @@ i386_io_port_remove(thread, device)
|| device == DEVICE_NULL)
return KERN_INVALID_ARGUMENT;
- pcb = thread->pcb;
+ task = thread->task;
simple_lock(&iopb_lock);
@@ -456,10 +461,10 @@ i386_io_port_remove(thread, device)
return KERN_INVALID_ARGUMENT;
}
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
+ task_lock(task);
+ io_tss = task->machine.io_tss;
if (io_tss == 0) {
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
return KERN_INVALID_ARGUMENT; /* not mapped */
}
@@ -477,7 +482,7 @@ i386_io_port_remove(thread, device)
queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
kfree((vm_offset_t)iu, sizeof(struct io_use));
@@ -486,6 +491,9 @@ i386_io_port_remove(thread, device)
}
}
+ task_unlock(task);
+ simple_unlock(&iopb_lock);
+
/*
* No mapping.
*/
@@ -493,7 +501,7 @@ i386_io_port_remove(thread, device)
}
/*
- * Return the IO ports mapped into a thread.
+ * Return the IO ports mapped into a task.
*/
extern ipc_port_t mach_convert_device_to_port(/* device_t */);
@@ -503,7 +511,7 @@ i386_io_port_list(thread, list, list_cou
mach_device_t **list;
unsigned int *list_count;
{
- register pcb_t pcb;
+ task_t task;
register iopb_tss_t io_tss;
unsigned int count, alloc_count;
mach_device_t *devices;
@@ -514,7 +522,7 @@ i386_io_port_list(thread, list, list_cou
if (thread == THREAD_NULL)
return KERN_INVALID_ARGUMENT;
- pcb = thread->pcb;
+ task = thread->task;
alloc_count = 16; /* a guess */
@@ -537,8 +545,8 @@ i386_io_port_list(thread, list, list_cou
count = 0;
simple_lock(&iopb_lock);
- simple_lock(&pcb->lock);
- io_tss = pcb->ims.io_tss;
+ task_lock(task);
+ io_tss = task->machine.io_tss;
if (io_tss != 0) {
register io_use_t iu;
@@ -550,7 +558,7 @@ i386_io_port_list(thread, list, list_cou
}
}
}
- simple_unlock(&pcb->lock);
+ task_unlock(task);
simple_unlock(&iopb_lock);
} while (count > alloc_count);
@@ -596,7 +604,7 @@ i386_io_port_list(thread, list, list_cou
}
/*
- * Check whether an IO device is mapped to a particular thread.
+ * Check whether an IO device is mapped to a particular task.
* Used to support the 'iopl' device automatic mapping.
*/
boolean_t
@@ -604,11 +612,11 @@ iopb_check_mapping(thread, device)
thread_t thread;
mach_device_t device;
{
- pcb_t pcb;
+ task_t task;
io_port_t io_port;
io_use_t iu;
- pcb = thread->pcb;
+ task = thread->task;
simple_lock(&iopb_lock);
@@ -622,15 +630,18 @@ iopb_check_mapping(thread, device)
/* Look up the mapping in the device`s mapping list. */
+ task_lock(task);
queue_iterate(&io_port->io_use_list, iu, io_use_t, psq) {
- if (iu->ts == pcb->ims.io_tss) {
+ if (iu->ts == task->machine.io_tss) {
/*
* Device is mapped.
*/
+ task_unlock(task);
simple_unlock(&iopb_lock);
return TRUE;
}
}
+ task_unlock(task);
simple_unlock(&iopb_lock);
return FALSE;
}
diff -urp gnumach-mine-4-more_ports/i386/i386/pcb.c
gnumach-mine-5-io_per_task/i386/i386/pcb.c
--- gnumach-mine-4-more_ports/i386/i386/pcb.c 2006-01-02 18:42:57.000000000
+0100
+++ gnumach-mine-5-io_per_task/i386/i386/pcb.c 2005-12-31 00:04:21.000000000
+0100
@@ -131,12 +131,13 @@
#define gdt_desc_p(mycpu,sel) \
((struct real_descriptor *)&curr_gdt(mycpu)[sel_idx(sel)])
-void switch_ktss(pcb)
- register pcb_t pcb;
+void switch_ktss(thread)
+ register thread_t thread;
{
int mycpu = cpu_number();
+ register pcb_t pcb = thread->pcb;
{
- register iopb_tss_t tss = pcb->ims.io_tss;
+ register iopb_tss_t tss = thread->task->machine.io_tss;
vm_offset_t pcb_stack_top;
/*
@@ -234,7 +235,7 @@ void stack_handoff(old, new)
/*
* Load the rest of the user state for the new thread
*/
- switch_ktss(new->pcb);
+ switch_ktss(new);
/*
* Switch to new thread
@@ -259,7 +260,7 @@ void stack_handoff(old, new)
void load_context(new)
register thread_t new;
{
- switch_ktss(new->pcb);
+ switch_ktss(new);
Load_context(new);
}
@@ -296,7 +297,7 @@ thread_t switch_context(old, continuatio
/*
* Load the rest of the user state for the new thread
*/
- switch_ktss(new->pcb);
+ switch_ktss(new);
return Switch_context(old, continuation, new);
}
@@ -309,7 +310,6 @@ void pcb_module_init()
0, "i386 pcb state");
fpu_module_init();
- iopb_init();
}
void pcb_init(thread)
@@ -353,8 +353,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)
@@ -374,6 +372,30 @@ void pcb_collect(thread)
{
}
+void machine_task_module_init(void)
+{
+ iopb_init();
+}
+
+void machine_task_init(new_task)
+ task_t new_task;
+{
+ new_task->machine.io_tss = 0;
+}
+
+void machine_task_terminate(task)
+ task_t task;
+{
+ if (task->machine.io_tss != 0)
+ iopb_destroy(task->machine.io_tss);
+}
+
+void machine_task_collect(task)
+ task_t task;
+{
+ /* TODO: compare io_tss with 0xff, XXX: not if it is still in use, and
+ * beware of races with threads adding io perms! */
+}
/*
* thread_setstatus:
@@ -508,28 +530,40 @@ 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;
+ register iopb_tss_t tss, old_tss;
+ task_t task;
if (count < i386_ISA_PORT_MAP_STATE_COUNT)
return(KERN_INVALID_ARGUMENT);
-#if 0
/*
* If the thread has no ktss yet,
* we must allocate one.
*/
state = (struct i386_isa_port_map_state *) tstate;
- tss = thread->pcb->ims.io_tss;
+ task = thread->task;
+ task_lock(task);
+ tss = task->machine.io_tss;
if (tss == 0) {
+ task_unlock(task);
tss = iopb_create();
- thread->pcb->ims.io_tss = tss;
+ task_lock(task);
+ old_tss = task->machine.io_tss;
+ if (old_tss == 0) {
+ task->machine.io_tss = tss;
+ } else {
+ task_unlock(task);
+ iopb_destroy(tss);
+ tss = old_tss;
+ task_lock(task);
+ }
}
bcopy((char *) state->pm,
(char *) tss->bitmap,
sizeof state->pm);
-#endif
+ task_unlock(task);
break;
}
@@ -666,16 +700,21 @@ 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;
+ task_t task;
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;
+ task = thread->task;
+ task_lock(task);
+ tss = task->machine.io_tss;
if (tss == 0) {
int i;
+ task_unlock(task);
+
/*
* The thread has no ktss, so no IO permissions.
*/
@@ -690,6 +729,7 @@ kern_return_t thread_getstatus(thread, f
bcopy((char *) tss->bitmap,
(char *) state->pm,
sizeof state->pm);
+ task_unlock(task);
}
*count = i386_ISA_PORT_MAP_STATE_COUNT;
diff -urp gnumach-mine-4-more_ports/i386/i386/io_emulate.c
gnumach-mine-5-io_per_task/i386/i386/io_emulate.c
--- gnumach-mine-4-more_ports/i386/i386/io_emulate.c 2006-01-02
18:41:46.000000000 +0100
+++ gnumach-mine-5-io_per_task/i386/i386/io_emulate.c 2005-12-28
17:40:28.000000000 +0100
@@ -102,7 +102,7 @@ emulate_io(regs, opcode, io_port)
* Make the thread use its IO_TSS to get the IO permissions;
* it may not have had one before this.
*/
- switch_ktss(thread->pcb);
+ switch_ktss(thread);
return EM_IO_RETRY;
}
diff -urp gnumach-mine-4-more_ports/i386/i386/thread.h
gnumach-mine-5-io_per_task/i386/i386/thread.h
--- gnumach-mine-4-more_ports/i386/i386/thread.h 2006-01-02
18:43:01.000000000 +0100
+++ gnumach-mine-5-io_per_task/i386/i386/thread.h 2005-12-28
17:44:13.000000000 +0100
@@ -157,12 +157,15 @@
*/
struct i386_machine_state {
- iopb_tss_t io_tss;
struct user_ldt * ldt;
struct i386_fpsave_state *ifps;
struct v86_assist_state v86s;
};
+typedef struct machine_task {
+ iopb_tss_t io_tss;
+} machine_task_t;
+
typedef struct pcb {
struct i386_interrupt_state iis[2]; /* interrupt and NMI */
struct i386_saved_state iss;
diff -urp gnumach-mine-4-more_ports/i386/i386/user_ldt.c
gnumach-mine-5-io_per_task/i386/i386/user_ldt.c
--- gnumach-mine-4-more_ports/i386/i386/user_ldt.c 2006-01-02
18:43:04.000000000 +0100
+++ gnumach-mine-5-io_per_task/i386/i386/user_ldt.c 2005-12-28
17:40:37.000000000 +0100
@@ -247,7 +247,7 @@ i386_set_ldt(thread, first_selector, des
* make sure it is properly set.
*/
if (thread == current_thread())
- switch_ktss(pcb);
+ switch_ktss(thread);
}
/*
- gnumach, task based IO ports,
Alfred M. Szmidt <=