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:
parent
074a16b53e
commit
2a6fbb7f88
@ -105,19 +105,19 @@ arch_cpu_init2(kernel_args *ka)
|
||||
|
||||
|
||||
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);
|
||||
if (tss_loaded[curr_cpu] == 0) {
|
||||
short seg = (0x28 + 8*curr_cpu);
|
||||
// dprintf("i386_set_kstack: kstack 0x%x, cpu %d\n", kstack, currentCPU);
|
||||
if (tss_loaded[currentCPU] == 0) {
|
||||
short seg = ((TSS_BASE_SEGMENT + currentCPU) << 3) | DPL_KERNEL;
|
||||
asm("movw %0, %%ax;"
|
||||
"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");
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <string.h>
|
||||
#include <Errors.h>
|
||||
#include <signal.h>
|
||||
#include <tls.h>
|
||||
|
||||
|
||||
// from arch_interrupts.S
|
||||
@ -37,13 +38,23 @@ i386_pop_iframe(struct thread *thread)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i386_set_fs_register(uint32 segment)
|
||||
static inline void
|
||||
set_fs_register(uint32 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
|
||||
arch_team_init_team_struct(struct team *p, bool kernel)
|
||||
{
|
||||
@ -66,7 +77,7 @@ arch_thread_init_thread_struct(struct thread *t)
|
||||
|
||||
|
||||
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_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
|
||||
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)
|
||||
{
|
||||
addr new_pgdir;
|
||||
|
||||
#if 0
|
||||
int i;
|
||||
|
||||
@ -133,13 +167,12 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
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));
|
||||
#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
|
||||
{
|
||||
int a = *(int *)(t_to->kernel_stack_base + KSTACK_SIZE - 4);
|
||||
}
|
||||
#endif
|
||||
// set TLS GDT entry to the current thread - since this action is
|
||||
// dependent on the current CPU, we have to do it here
|
||||
if (t_to->user_local_storage != NULL)
|
||||
set_tls_context(t_to);
|
||||
|
||||
if (t_from->team->_aspace_id >= 0 && t_to->team->_aspace_id >= 0) {
|
||||
// they are both uspace threads
|
||||
@ -159,36 +192,12 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
} else {
|
||||
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)
|
||||
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_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
|
||||
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",
|
||||
entry, args, ustack_top);
|
||||
|
||||
@ -219,7 +233,10 @@ arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <arch/x86/descriptors.h>
|
||||
|
||||
#define FUNCTION(x) .global x; .type x,@function; x
|
||||
|
||||
.text
|
||||
@ -182,10 +184,10 @@ FUNCTION(i386_enter_uspace):
|
||||
movl 4(%esp),%eax // get entry point
|
||||
movl 8(%esp),%edx // get arguments
|
||||
movl 12(%esp),%ebx // get user stack
|
||||
movw $0x23,%cx
|
||||
movw $USER_DATA_SEG,%cx
|
||||
movw %cx,%ds
|
||||
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
|
||||
|
||||
// copy exit stub to stack
|
||||
@ -203,10 +205,10 @@ _copy_more:
|
||||
movl %ebx,-8(%ebx) // fake return address to copied exit stub
|
||||
sub $8,%ebx
|
||||
|
||||
pushl $0x23 // user data segment
|
||||
pushl $USER_DATA_SEG // user data segment
|
||||
pushl %ebx // user stack
|
||||
pushl $(1 << 9) | 2 // user flags
|
||||
pushl $0x1b // user code segment
|
||||
pushl $USER_CODE_SEG // user code segment
|
||||
pushl %eax // user IP
|
||||
iret
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user