Removed some hard-coded values with definitions (mostly USER_x_SEG in arch_x86.S,

and TSS_BASE_SEGMENT in i386_set_tss_and_kstack() (thanks Daniel for pointing this
out)).
Added a arch_thread_init_tls() function which fills the reserved slots - the find_thread()
inline asm in OS.h is finally working.
Added some more comments, resolved the ToDo items from last time :-)
arch_thread_context_switch() now calls set_tls_context() at the correct location.
arch_thread_enter_uspace() now calls set_tls_context() as there is no context
switch in this case for the current thread after TLS has been set up, and it
now gets a pointer to the thread structure directly, and calculates the user
stack top itself, rather than the callee.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2380 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2003-01-07 09:33:30 +00:00
parent 074a16b53e
commit 2a6fbb7f88
3 changed files with 65 additions and 46 deletions
+7 -7
View File
@@ -105,19 +105,19 @@ arch_cpu_init2(kernel_args *ka)
void void
i386_set_kstack(addr kstack) i386_set_tss_and_kstack(addr kstack)
{ {
int curr_cpu = smp_get_current_cpu(); int currentCPU = smp_get_current_cpu();
// dprintf("i386_set_kstack: kstack 0x%x, cpu %d\n", kstack, curr_cpu); // dprintf("i386_set_kstack: kstack 0x%x, cpu %d\n", kstack, currentCPU);
if (tss_loaded[curr_cpu] == 0) { if (tss_loaded[currentCPU] == 0) {
short seg = (0x28 + 8*curr_cpu); short seg = ((TSS_BASE_SEGMENT + currentCPU) << 3) | DPL_KERNEL;
asm("movw %0, %%ax;" asm("movw %0, %%ax;"
"ltr %%ax;" : : "r" (seg) : "eax"); "ltr %%ax;" : : "r" (seg) : "eax");
tss_loaded[curr_cpu] = 1; tss_loaded[currentCPU] = 1;
} }
tss[curr_cpu]->sp0 = kstack; tss[currentCPU]->sp0 = kstack;
// dprintf("done\n"); // dprintf("done\n");
} }
+52 -35
View File
@@ -15,6 +15,7 @@
#include <string.h> #include <string.h>
#include <Errors.h> #include <Errors.h>
#include <signal.h> #include <signal.h>
#include <tls.h>
// from arch_interrupts.S // from arch_interrupts.S
@@ -37,13 +38,23 @@ i386_pop_iframe(struct thread *thread)
} }
static void static inline void
i386_set_fs_register(uint32 segment) set_fs_register(uint32 segment)
{ {
asm("movl %0,%%fs" :: "r" (segment)); asm("movl %0,%%fs" :: "r" (segment));
} }
static void
set_tls_context(struct thread *thread)
{
int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT;
set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage);
set_fs_register((entry << 3) | DPL_USER);
}
int int
arch_team_init_team_struct(struct team *p, bool kernel) arch_team_init_team_struct(struct team *p, bool kernel)
{ {
@@ -66,7 +77,7 @@ arch_thread_init_thread_struct(struct thread *t)
int int
arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void)) arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
{ {
unsigned int *kstack = (unsigned int *)t->kernel_stack_base; unsigned int *kstack = (unsigned int *)t->kernel_stack_base;
unsigned int kstack_size = KSTACK_SIZE; unsigned int kstack_size = KSTACK_SIZE;
@@ -109,6 +120,28 @@ arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(void),
} }
/** Initializes the user-space TLS local storage pointer in
* the thread structure, and the reserved TLS slots.
*
* Is called from _create_user_thread_kentry().
*/
void
arch_thread_init_tls(struct thread *thread)
{
uint32 *tls;
thread->user_local_storage = thread->user_stack_base + STACK_SIZE;
tls = (uint32 *)thread->user_local_storage;
tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
tls[TLS_THREAD_ID_SLOT] = thread->id;
tls[TLS_ERRNO_SLOT] = 0;
set_tls_context(thread);
}
void void
arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*func)(void *), void *arg) arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*func)(void *), void *arg)
{ {
@@ -120,6 +153,7 @@ void
arch_thread_context_switch(struct thread *t_from, struct thread *t_to) arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
{ {
addr new_pgdir; addr new_pgdir;
#if 0 #if 0
int i; int i;
@@ -133,13 +167,12 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
for (i = 0; i < 11; i++) for (i = 0; i < 11; i++)
dprintf("*esp[%d] (0x%x) = 0x%x\n", i, ((unsigned int *)new_at->esp + i), *((unsigned int *)new_at->esp + i)); dprintf("*esp[%d] (0x%x) = 0x%x\n", i, ((unsigned int *)new_at->esp + i), *((unsigned int *)new_at->esp + i));
#endif #endif
i386_set_kstack(t_to->kernel_stack_base + KSTACK_SIZE); i386_set_tss_and_kstack(t_to->kernel_stack_base + KSTACK_SIZE);
#if 0 // set TLS GDT entry to the current thread - since this action is
{ // dependent on the current CPU, we have to do it here
int a = *(int *)(t_to->kernel_stack_base + KSTACK_SIZE - 4); if (t_to->user_local_storage != NULL)
} set_tls_context(t_to);
#endif
if (t_from->team->_aspace_id >= 0 && t_to->team->_aspace_id >= 0) { if (t_from->team->_aspace_id >= 0 && t_to->team->_aspace_id >= 0) {
// they are both uspace threads // they are both uspace threads
@@ -159,36 +192,12 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
} else { } else {
new_pgdir = vm_translation_map_get_pgdir(&t_to->team->aspace->translation_map); new_pgdir = vm_translation_map_get_pgdir(&t_to->team->aspace->translation_map);
} }
#if 0
dprintf("new_pgdir is 0x%x\n", new_pgdir);
#endif
#if 0
{
int a = *(int *)(t_to->arch_info.current_stack.esp - 4);
}
#endif
if ((new_pgdir % PAGE_SIZE) != 0) if ((new_pgdir % PAGE_SIZE) != 0)
panic("arch_thread_context_switch: bad pgdir 0x%lx\n", new_pgdir); panic("arch_thread_context_switch: bad pgdir 0x%lx\n", new_pgdir);
i386_fsave_swap(t_from->arch_info.fpu_state, t_to->arch_info.fpu_state); i386_fsave_swap(t_from->arch_info.fpu_state, t_to->arch_info.fpu_state);
i386_context_switch(&t_from->arch_info, &t_to->arch_info, new_pgdir); i386_context_switch(&t_from->arch_info, &t_to->arch_info, new_pgdir);
// set TLS GDT entry to the current thread - since this action is
// dependent on the current CPU, we have to do it here
{
int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT;
// ToDo: the TLS storage is currently located simply at the bottom of the user stack
// perhaps we want to put it somewhere else, in a safe place?
// very strange: the user_stack_base pointer seg faults, (+ PAGE_SIZE) improves
// the situation, but the main thread still don't work correctly...
// Also have a look at the stack addresses: the main thread is located at
// 0x7ffd600, the ones of the others are at 0x0062b000 and following
set_segment_descriptor_base(&gGDT[entry], t_to->user_stack_base + PAGE_SIZE);
i386_set_fs_register((entry << 3) | DPL_USER);
}
} }
@@ -203,9 +212,14 @@ arch_thread_dump_info(void *info)
} }
/** Sets up initial thread context and enters user space
*/
void void
arch_thread_enter_uspace(addr entry, void *args, addr ustack_top) arch_thread_enter_uspace(struct thread *t, addr entry, void *args)
{ {
addr ustack_top = t->user_stack_base + STACK_SIZE;
dprintf("arch_thread_enter_uspace: entry 0x%lx, args %p, ustack_top 0x%lx\n", dprintf("arch_thread_enter_uspace: entry 0x%lx, args %p, ustack_top 0x%lx\n",
entry, args, ustack_top); entry, args, ustack_top);
@@ -219,7 +233,10 @@ arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
disable_interrupts(); disable_interrupts();
i386_set_kstack(thread_get_current_thread()->kernel_stack_base + KSTACK_SIZE); i386_set_tss_and_kstack(t->kernel_stack_base + KSTACK_SIZE);
// set the CPU dependent GDT entry for TLS
set_tls_context(t);
i386_enter_uspace(entry, args, ustack_top - 4); i386_enter_uspace(entry, args, ustack_top - 4);
} }
+6 -4
View File
@@ -4,6 +4,8 @@
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
*/ */
#include <arch/x86/descriptors.h>
#define FUNCTION(x) .global x; .type x,@function; x #define FUNCTION(x) .global x; .type x,@function; x
.text .text
@@ -182,10 +184,10 @@ FUNCTION(i386_enter_uspace):
movl 4(%esp),%eax // get entry point movl 4(%esp),%eax // get entry point
movl 8(%esp),%edx // get arguments movl 8(%esp),%edx // get arguments
movl 12(%esp),%ebx // get user stack movl 12(%esp),%ebx // get user stack
movw $0x23,%cx movw $USER_DATA_SEG,%cx
movw %cx,%ds movw %cx,%ds
movw %cx,%es movw %cx,%es
//movw %cx,%fs // fs points to the TLS storage (CPU dependent segment) //movw $0x33 + cpu_num,%fs -> fs points to the TLS storage (CPU dependent segment)
movw %cx,%gs movw %cx,%gs
// copy exit stub to stack // copy exit stub to stack
@@ -203,10 +205,10 @@ _copy_more:
movl %ebx,-8(%ebx) // fake return address to copied exit stub movl %ebx,-8(%ebx) // fake return address to copied exit stub
sub $8,%ebx sub $8,%ebx
pushl $0x23 // user data segment pushl $USER_DATA_SEG // user data segment
pushl %ebx // user stack pushl %ebx // user stack
pushl $(1 << 9) | 2 // user flags pushl $(1 << 9) | 2 // user flags
pushl $0x1b // user code segment pushl $USER_CODE_SEG // user code segment
pushl %eax // user IP pushl %eax // user IP
iret iret