Fixed double fault handler. Personally I disclaim all responsiblity
for these changes. I was mostly just staring in amazement at the screen while Axel and Thomas were discussing IA32 internals. A particularly fascinating moment was when Thomas produced the cause of a bug we had been trying to track down for hours off the top of his head (of course iret behaves specially when the NT bit is set :-). His slowness must be excused though, since he hadn't slept for more then 30 hours. ;-) The code doesn't wholeheartedly deal with multi-processor machines yet. Axel will certainly do some cleanup... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12239 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -75,6 +75,8 @@ void i386_fxrstor(const void *fpu_state);
|
|||||||
void i386_fsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
void i386_fsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
||||||
void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state);
|
||||||
void x86_set_task_gate(int32 n, int32 segment);
|
void x86_set_task_gate(int32 n, int32 segment);
|
||||||
|
struct tss *x86_get_main_tss(void);
|
||||||
|
|
||||||
|
|
||||||
#define read_ebp(value) \
|
#define read_ebp(value) \
|
||||||
__asm__("movl %%ebp,%0" : "=r" (value))
|
__asm__("movl %%ebp,%0" : "=r" (value))
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
// this file can also be included from assembler as well
|
// this file can also be included from assembler as well
|
||||||
// (and is in arch_interrupts.S)
|
// (and is in arch_interrupts.S)
|
||||||
|
|
||||||
#define DOUBLE_FAULT_TSS_SEGMENT 5
|
#define DOUBLE_FAULT_TSS_BASE_SEGMENT 5
|
||||||
#define TSS_BASE_SEGMENT 6
|
#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus())
|
||||||
#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus())
|
#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus())
|
||||||
|
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit)
|
|||||||
desc->privilege_level = DPL_KERNEL;
|
desc->privilege_level = DPL_KERNEL;
|
||||||
|
|
||||||
desc->present = 1;
|
desc->present = 1;
|
||||||
desc->granularity = 1; // 4 GB size (in page size steps)
|
desc->granularity = 0; // 1 Byte granularity
|
||||||
desc->available = 0; // system available bit is currently not used
|
desc->available = 0; // system available bit is currently not used
|
||||||
desc->d_b = 0;
|
desc->d_b = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
#ifndef _NEWOS_KERNEL_ARCH_I386_FAULTS
|
#ifndef _NEWOS_KERNEL_ARCH_I386_FAULTS
|
||||||
#define _NEWOS_KERNEL_ARCH_I386_FAULTS
|
#define _NEWOS_KERNEL_ARCH_I386_FAULTS
|
||||||
|
|
||||||
|
struct iframe;
|
||||||
|
|
||||||
int i386_general_protection_fault(int errorcode);
|
int i386_general_protection_fault(int errorcode);
|
||||||
int i386_double_fault(int errorcode);
|
int i386_double_fault(struct iframe *frame);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,14 @@
|
|||||||
#define _NEWOS_KERNEL_ARCH_I386_INTERRUPTS_H
|
#define _NEWOS_KERNEL_ARCH_I386_INTERRUPTS_H
|
||||||
|
|
||||||
void trap0();void trap1();void trap2();void trap3();void trap4();void trap5();
|
void trap0();void trap1();void trap2();void trap3();void trap4();void trap5();
|
||||||
void trap6();void trap7();void trap8();void trap9();void trap10();void trap11();
|
void trap6();void trap7();void trap9();void trap10();void trap11();
|
||||||
void trap12();void trap13();void trap14();void trap16();void trap17();void trap18();
|
void trap12();void trap13();void trap14();void trap16();void trap17();void trap18();
|
||||||
void trap32();void trap33();void trap34();void trap35();void trap36();void trap37();
|
void trap32();void trap33();void trap34();void trap35();void trap36();void trap37();
|
||||||
void trap38();void trap39();void trap40();void trap41();void trap42();void trap43();
|
void trap38();void trap39();void trap40();void trap41();void trap42();void trap43();
|
||||||
void trap44();void trap45();void trap46();void trap47();
|
void trap44();void trap45();void trap46();void trap47();
|
||||||
|
|
||||||
|
void double_fault(); // int 8
|
||||||
|
|
||||||
void trap99();
|
void trap99();
|
||||||
|
|
||||||
void trap251();void trap252();void trap253();void trap254();void trap255();
|
void trap251();void trap252();void trap253();void trap254();void trap255();
|
||||||
|
|||||||
@@ -23,34 +23,51 @@ extern void reboot(void);
|
|||||||
// from arch_x86.S
|
// from arch_x86.S
|
||||||
|
|
||||||
static struct tss **sTSS;
|
static struct tss **sTSS;
|
||||||
|
//static struct tss **sDoubleFaultTSS;
|
||||||
|
struct tss **sDoubleFaultTSS;
|
||||||
static int *sIsTSSLoaded;
|
static int *sIsTSSLoaded;
|
||||||
|
|
||||||
segment_descriptor *gGDT = NULL;
|
segment_descriptor *gGDT = NULL;
|
||||||
|
|
||||||
/* Some specials for the double fault handler */
|
/* Some specials for the double fault handler */
|
||||||
static struct tss sDoubleFaultTSS;
|
//static struct tss sDoubleFaultTSS;
|
||||||
static uint32 sDoubleFaultStack[1024];
|
static uint32 sDoubleFaultStack[10240];
|
||||||
|
|
||||||
|
|
||||||
|
struct tss *
|
||||||
|
x86_get_main_tss(void)
|
||||||
|
{
|
||||||
|
int cpuNum = smp_get_current_cpu();
|
||||||
|
|
||||||
|
return sTSS[cpuNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_double_fault(void)
|
init_double_fault(int cpuNum)
|
||||||
{
|
{
|
||||||
/* set up the double fault tss */
|
/* set up the double fault tss */
|
||||||
memset(&sDoubleFaultTSS, 0, sizeof(struct tss));
|
/* TODO: Axel - fix SMP support */
|
||||||
sDoubleFaultTSS.sp0 = (uint32)sDoubleFaultStack + sizeof(sDoubleFaultStack);
|
struct tss *tss = sDoubleFaultTSS[cpuNum];
|
||||||
sDoubleFaultTSS.ss0 = KERNEL_DATA_SEG;
|
|
||||||
read_cr3(sDoubleFaultTSS.cr3); // copy the current cr3 to the double fault cr3
|
memset(tss, 0, sizeof(struct tss));
|
||||||
sDoubleFaultTSS.eip = (uint32)&trap8;
|
tss->sp0 = (uint32)sDoubleFaultStack + sizeof(sDoubleFaultStack);
|
||||||
sDoubleFaultTSS.es = KERNEL_DATA_SEG;
|
tss->ss0 = KERNEL_DATA_SEG;
|
||||||
sDoubleFaultTSS.cs = KERNEL_CODE_SEG;
|
read_cr3(tss->cr3); // copy the current cr3 to the double fault cr3
|
||||||
sDoubleFaultTSS.ss = KERNEL_DATA_SEG;
|
tss->eip = (uint32)&double_fault;
|
||||||
sDoubleFaultTSS.ds = KERNEL_DATA_SEG;
|
tss->es = KERNEL_DATA_SEG;
|
||||||
sDoubleFaultTSS.fs = KERNEL_DATA_SEG;
|
tss->cs = KERNEL_CODE_SEG;
|
||||||
sDoubleFaultTSS.gs = KERNEL_DATA_SEG;
|
tss->ss = KERNEL_DATA_SEG;
|
||||||
sDoubleFaultTSS.ldt_seg_selector = KERNEL_DATA_SEG;
|
tss->esp = tss->sp0;
|
||||||
|
tss->ds = KERNEL_DATA_SEG;
|
||||||
|
tss->fs = KERNEL_DATA_SEG;
|
||||||
|
tss->gs = KERNEL_DATA_SEG;
|
||||||
|
tss->ldt_seg_selector = 0;
|
||||||
|
|
||||||
set_tss_descriptor(&gGDT[DOUBLE_FAULT_TSS_SEGMENT], (addr_t)&sDoubleFaultTSS, sizeof(struct tss));
|
// add TSS descriptor for this new TSS
|
||||||
x86_set_task_gate(8, DOUBLE_FAULT_TSS_SEGMENT << 3);
|
set_tss_descriptor(&gGDT[DOUBLE_FAULT_TSS_BASE_SEGMENT + cpuNum], (addr_t)tss, sizeof(struct tss));
|
||||||
|
|
||||||
|
// set_tss_descriptor(&gGDT[DOUBLE_FAULT_TSS_SEGMENT + cpuNum], (addr_t)sDoubleFaultTSS[cpuNum], sizeof(struct tss));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,6 +110,12 @@ arch_cpu_init_post_vm(kernel_args *args)
|
|||||||
panic("arch_cpu_init_post_vm: could not allocate buffer for tss pointers\n");
|
panic("arch_cpu_init_post_vm: could not allocate buffer for tss pointers\n");
|
||||||
return B_NO_MEMORY;
|
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);
|
sIsTSSLoaded = malloc(sizeof(int) * args->num_cpus);
|
||||||
if (sIsTSSLoaded == NULL) {
|
if (sIsTSSLoaded == NULL) {
|
||||||
@@ -102,9 +125,10 @@ arch_cpu_init_post_vm(kernel_args *args)
|
|||||||
memset(sIsTSSLoaded, 0, sizeof(int) * args->num_cpus);
|
memset(sIsTSSLoaded, 0, sizeof(int) * args->num_cpus);
|
||||||
|
|
||||||
for (i = 0; i < args->num_cpus; i++) {
|
for (i = 0; i < args->num_cpus; i++) {
|
||||||
char tssName[16];
|
char tssName[32];
|
||||||
area_id area;
|
area_id area;
|
||||||
|
|
||||||
|
// create standard tasks
|
||||||
sprintf(tssName, "tss%lu", i);
|
sprintf(tssName, "tss%lu", i);
|
||||||
area = create_area(tssName, (void **)&sTSS[i], B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE,
|
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);
|
B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
@@ -119,7 +143,30 @@ arch_cpu_init_post_vm(kernel_args *args)
|
|||||||
|
|
||||||
// add TSS descriptor for this new TSS
|
// 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)sTSS[i], 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
|
||||||
|
init_double_fault(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Axel - call on all CPUs */
|
||||||
|
{
|
||||||
|
short seg = ((TSS_BASE_SEGMENT + 0) << 3) | DPL_KERNEL;
|
||||||
|
asm("movw %0, %%ax;"
|
||||||
|
"ltr %%ax;" : : "r" (seg) : "eax");
|
||||||
|
sIsTSSLoaded[0] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
x86_set_task_gate(8, DOUBLE_FAULT_TSS_BASE_SEGMENT << 3);
|
||||||
|
|
||||||
// setup TLS descriptors (one for every CPU)
|
// setup TLS descriptors (one for every CPU)
|
||||||
|
|
||||||
@@ -127,8 +174,7 @@ arch_cpu_init_post_vm(kernel_args *args)
|
|||||||
set_segment_descriptor(&gGDT[TLS_BASE_SEGMENT + i], 0, TLS_SIZE,
|
set_segment_descriptor(&gGDT[TLS_BASE_SEGMENT + i], 0, TLS_SIZE,
|
||||||
DT_DATA_WRITEABLE, DPL_USER);
|
DT_DATA_WRITEABLE, DPL_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_double_fault();
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <faults_priv.h>
|
#include <faults_priv.h>
|
||||||
#include <boot/kernel_args.h>
|
#include <boot/kernel_args.h>
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
#include <arch/faults.h>
|
#include <arch/faults.h>
|
||||||
|
|
||||||
// XXX this module is largely outdated. Will probably be removed later.
|
// XXX this module is largely outdated. Will probably be removed later.
|
||||||
@@ -22,11 +23,17 @@ int i386_general_protection_fault(int errorcode)
|
|||||||
return general_protection_fault(errorcode);
|
return general_protection_fault(errorcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i386_double_fault(int errorcode)
|
int i386_double_fault(struct iframe *frame)
|
||||||
{
|
{
|
||||||
kprintf("double fault! errorcode = 0x%x\n", errorcode);
|
struct tss *tss = x86_get_main_tss();
|
||||||
dprintf("double fault! errorcode = 0x%x\n", errorcode);
|
|
||||||
for(;;);
|
frame->cs = tss->cs;
|
||||||
|
frame->eip = tss->eip;
|
||||||
|
frame->esp = tss->esp;
|
||||||
|
frame->flags = tss->eflags;
|
||||||
|
|
||||||
|
panic("double fault! errorcode = 0x%x\n", frame->error_code);
|
||||||
|
|
||||||
return B_HANDLED_INTERRUPT;
|
return B_HANDLED_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ i386_handle_trap(struct iframe frame)
|
|||||||
ret = i386_handle_breakpoint_exception(&frame);
|
ret = i386_handle_breakpoint_exception(&frame);
|
||||||
break;
|
break;
|
||||||
case 8: // double fault
|
case 8: // double fault
|
||||||
ret = i386_double_fault(frame.error_code);
|
ret = i386_double_fault(&frame);
|
||||||
break;
|
break;
|
||||||
case 13: // general protection fault
|
case 13: // general protection fault
|
||||||
ret = i386_general_protection_fault(frame.error_code);
|
ret = i386_general_protection_fault(frame.error_code);
|
||||||
|
|||||||
@@ -42,7 +42,21 @@ TRAP(trap4, 4)
|
|||||||
TRAP(trap5, 5)
|
TRAP(trap5, 5)
|
||||||
TRAP(trap6, 6)
|
TRAP(trap6, 6)
|
||||||
TRAP(trap7, 7)
|
TRAP(trap7, 7)
|
||||||
TRAP_ERRC(trap8, 8)
|
|
||||||
|
.globl double_fault;
|
||||||
|
.align 8;
|
||||||
|
double_fault:
|
||||||
|
pushl $-1; // user-ss
|
||||||
|
pushl $-1; // user-esp
|
||||||
|
pushl $-1; // flags
|
||||||
|
pushl $KERNEL_CODE_SEG; // cs
|
||||||
|
pushl $-1; // eip
|
||||||
|
pushl $0; // error-code
|
||||||
|
pushl $8;
|
||||||
|
pushl $-1;
|
||||||
|
pushl $-1;
|
||||||
|
jmp int_bottom
|
||||||
|
|
||||||
TRAP(trap9, 9)
|
TRAP(trap9, 9)
|
||||||
TRAP_ERRC(trap10, 10)
|
TRAP_ERRC(trap10, 10)
|
||||||
TRAP_ERRC(trap11, 11)
|
TRAP_ERRC(trap11, 11)
|
||||||
|
|||||||
Reference in New Issue
Block a user