From dfb5375d18ecb62038ad999e2af23fe584354c3d Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Wed, 14 Feb 2007 06:24:59 +0000 Subject: [PATCH] clean up TSS initialization. Now two complete tss structures exist within the per-cpu structure. Instead of having to create a seperate area per each one, initialize them in place. Also, the old mechanism to getting all of the cpus to get initialized was subtly broken, but still managed to work. Now, just force all the cpus to initialize at boot, which makes the actual swapping of esp0 somewhat simpler. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20131 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_cpu.h | 6 +- src/system/kernel/arch/x86/arch_cpu.c | 90 ++++------------------ src/system/kernel/arch/x86/arch_int.c | 5 +- 3 files changed, 24 insertions(+), 77 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index db15611f4a..1f901c94f5 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -158,6 +158,7 @@ enum x86_vendors { }; typedef struct arch_cpu_info { + // saved cpu info enum x86_vendors vendor; enum x86_feature_type feature[FEATURE_NUM]; char model_name[49]; @@ -167,6 +168,10 @@ typedef struct arch_cpu_info { int stepping; int model; char feature_string[256]; + + // local TSS for this cpu + struct tss tss; + struct tss double_fault_tss; } arch_cpu_info; #ifdef __cplusplus @@ -203,7 +208,6 @@ uint32 x86_count_mtrrs(void); void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); status_t x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type); bool x86_check_feature(uint32 feature, enum x86_feature_type type); -struct tss *x86_get_main_tss(void); #define read_cr3(value) \ diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index 1e61ea4942..5675cc5fdf 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -65,10 +65,6 @@ extern void reboot(void); void (*gX86SwapFPUFunc)(void *oldState, const void *newState); bool gHasSSE = false; -static struct tss **sTSS; -//static struct tss **sDoubleFaultTSS; -struct tss **sDoubleFaultTSS; -static int *sIsTSSLoaded; static vint32 sWaitAllCPUs; segment_descriptor *gGDT = NULL; @@ -79,15 +75,6 @@ static uint32 sDoubleFaultStack[10240]; static x86_cpu_module_info *sCpuModule; - -struct tss * -x86_get_main_tss(void) -{ - int cpuNum = smp_get_current_cpu(); - return sTSS[cpuNum]; -} - - /** Disable CPU caches, and invalidate them. */ static void @@ -208,13 +195,11 @@ init_sse(void) static void -load_tss(void *data, int cpu) +load_tss(int cpu) { short seg = ((TSS_BASE_SEGMENT + cpu) << 3) | DPL_KERNEL; asm("movw %0, %%ax;" "ltr %%ax;" : : "r" (seg) : "eax"); - - sIsTSSLoaded[cpu] = true; } @@ -223,7 +208,7 @@ init_double_fault(int cpuNum) { /* set up the double fault tss */ /* TODO: Axel - fix SMP support */ - struct tss *tss = sDoubleFaultTSS[cpuNum]; + struct tss *tss = &gCPU[cpuNum].arch.tss; memset(tss, 0, sizeof(struct tss)); tss->sp0 = (uint32)sDoubleFaultStack + sizeof(sDoubleFaultStack); @@ -462,6 +447,11 @@ arch_cpu_init_percpu(kernel_args *args, int curr_cpu) { detect_cpu(args, curr_cpu); + // load the TSS for this cpu + // note the main cpu gets initialized in arch_cpu_init_post_vm() + if (curr_cpu != 0) + load_tss(curr_cpu); + return 0; } @@ -490,60 +480,20 @@ arch_cpu_init_post_vm(kernel_args *args) //i386_selector_init(gGDT); // pass the new gdt // setup task-state segments - - sTSS = malloc(sizeof(struct tss *) * args->num_cpus); - if (sTSS == NULL) { - panic("arch_cpu_init_post_vm: could not allocate buffer for tss pointers\n"); - return B_NO_MEMORY; - } - - sDoubleFaultTSS = malloc(sizeof(struct tss *) * args->num_cpus); - if (sDoubleFaultTSS == NULL) { - panic("arch_cpu_init_post_vm: could not allocate buffer for double fault tss pointers\n"); - return B_NO_MEMORY; - } - - sIsTSSLoaded = malloc(sizeof(int) * args->num_cpus); - if (sIsTSSLoaded == NULL) { - panic("arch_cpu_init_post_vm: could not allocate buffer for tss booleans\n"); - return B_NO_MEMORY; - } - memset(sIsTSSLoaded, 0, sizeof(int) * args->num_cpus); - for (i = 0; i < args->num_cpus; i++) { - char tssName[32]; - area_id area; - - // create standard tasks - sprintf(tssName, "tss%lu", i); - area = create_area(tssName, (void **)&sTSS[i], B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, - B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - if (area < 0) { - panic("arch_cpu_init2: unable to create region for tss\n"); - return B_NO_MEMORY; - } - - // initialize TSS - memset(sTSS[i], 0, sizeof(struct tss)); - sTSS[i]->ss0 = KERNEL_DATA_SEG; + // initialize the regular and double fault tss stored in the per-cpu structure + memset(&gCPU[i].arch.tss, 0, sizeof(struct tss)); + gCPU[i].arch.tss.ss0 = KERNEL_DATA_SEG; // add TSS descriptor for this new TSS - set_tss_descriptor(&gGDT[TSS_BASE_SEGMENT + i], (addr_t)sTSS[i], sizeof(struct tss)); + set_tss_descriptor(&gGDT[TSS_BASE_SEGMENT + i], (addr_t)&gCPU[i].arch.tss, sizeof(struct tss)); - // create double-fault task - sprintf(tssName, "double_fault_tss%lu", i); - area = create_area(tssName, (void **)&sDoubleFaultTSS[i], B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, - B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - if (area < 0) { - panic("arch_cpu_init2: unable to create region for tss\n"); - return B_NO_MEMORY; - } - - // initialize TSS + // initialize the double fault tss init_double_fault(i); } - call_all_cpus(&load_tss, NULL); + // set the current hardware task on cpu 0 + load_tss(0); x86_set_task_gate(8, DOUBLE_FAULT_TSS_BASE_SEGMENT << 3); @@ -590,19 +540,9 @@ arch_cpu_init_post_modules(kernel_args *args) void i386_set_tss_and_kstack(addr_t kstack) { - int32 currentCPU = smp_get_current_cpu(); - - if (!sIsTSSLoaded[currentCPU]) { - short seg = ((TSS_BASE_SEGMENT + currentCPU) << 3) | DPL_KERNEL; - asm("movw %0, %%ax;" - "ltr %%ax;" : : "r" (seg) : "eax"); - sIsTSSLoaded[currentCPU] = true; - } - - sTSS[currentCPU]->sp0 = kstack; + get_cpu_struct()->arch.tss.sp0 = kstack; } - void arch_cpu_global_TLB_invalidate(void) { diff --git a/src/system/kernel/arch/x86/arch_int.c b/src/system/kernel/arch/x86/arch_int.c index a4153c4f4b..ccb623150e 100644 --- a/src/system/kernel/arch/x86/arch_int.c +++ b/src/system/kernel/arch/x86/arch_int.c @@ -386,13 +386,16 @@ i386_handle_trap(struct iframe frame) case 8: // Double Fault Exception (#DF) { +#if 0 + // XXX what is this supposed to do? struct tss *tss = x86_get_main_tss(); frame.cs = tss->cs; frame.eip = tss->eip; frame.esp = tss->esp; frame.flags = tss->eflags; - +#endif + panic("double fault! errorcode = 0x%lx\n", frame.error_code); break;