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;