first version to support the FPU
- seems to work - currently, we didn't support SIMD instructions
This commit is contained in:
parent
ea19b15781
commit
7e0179f5f7
5 changed files with 42 additions and 10 deletions
|
@ -55,11 +55,15 @@ typedef struct i387_fxsave_struct {
|
|||
long padding[56];
|
||||
} i387_fxsave_t __attribute__ ((aligned (16)));
|
||||
|
||||
union fpu_union {
|
||||
union fpu_state {
|
||||
i387_fsave_t fsave;
|
||||
i387_fxsave_t fxsave;
|
||||
};
|
||||
|
||||
static inline void save_fpu_state(union fpu_state* state) {
|
||||
asm volatile ("fsave %0; fwait" : "=m"((*state).fsave));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -64,16 +64,19 @@ ALIGN 4
|
|||
stublet:
|
||||
; initialize stack pointer.
|
||||
mov esp, default_stack_pointer
|
||||
; enable cache and turn on FPU exceptions
|
||||
mov eax, cr0
|
||||
; enable cache
|
||||
and eax, 0x9fffffff
|
||||
; ...and turn on FPU exceptions
|
||||
or eax, 0x20
|
||||
; enable cache, disable paging and fpu emulation
|
||||
and eax, 0x3ffffffb
|
||||
; ...monitor coprocessor and turn on FPU exceptions
|
||||
or eax, 0x22
|
||||
mov cr0, eax
|
||||
; clears the current pgd entry
|
||||
xor eax, eax
|
||||
mov cr3, eax
|
||||
; disable SSE support (TODO)
|
||||
mov eax, cr4
|
||||
and eax, 0xfffbf9ff
|
||||
mov cr4, eax
|
||||
; interpret multiboot information
|
||||
extern multiboot_init
|
||||
push ebx
|
||||
|
|
|
@ -74,6 +74,7 @@ extern void isr30(void);
|
|||
extern void isr31(void);
|
||||
|
||||
static void fault_handler(struct state *s);
|
||||
static void fpu_handler(struct state *s);
|
||||
|
||||
/*
|
||||
* This is a very repetitive function... it's not hard, it's
|
||||
|
@ -158,6 +159,23 @@ void isrs_install(void)
|
|||
// install the default handler
|
||||
for(i=0; i<32; i++)
|
||||
irq_install_handler(i, fault_handler);
|
||||
|
||||
// set hanlder for fpu exceptions
|
||||
irq_uninstall_handler(7);
|
||||
irq_install_handler(7, fpu_handler);
|
||||
}
|
||||
|
||||
static void fpu_handler(struct state *s)
|
||||
{
|
||||
task_t* task = per_core(current_task);
|
||||
|
||||
kputs("got FPU exception\n");
|
||||
asm volatile ("clts"); // clear the TS flag of cr0
|
||||
if (!task->fpu_used) {
|
||||
task->fpu_used = 1;
|
||||
asm volatile ("finit");
|
||||
} else
|
||||
asm volatile ("frstor %0" :: "m"(task->fpu.fsave)); // restore fpu state
|
||||
}
|
||||
|
||||
/** @brief Exception messages
|
||||
|
@ -189,7 +207,7 @@ static void fault_handler(struct state *s)
|
|||
{
|
||||
if (s->int_no < 32) {
|
||||
kputs(exception_messages[s->int_no]);
|
||||
kputs(" Exception.\n");
|
||||
kprintf(" Exception. (%d)\n", s->int_no);
|
||||
|
||||
/* Now, we signalize that we have handled the interrupt */
|
||||
if (apic_is_enabled())
|
||||
|
|
|
@ -66,12 +66,14 @@ typedef struct task {
|
|||
spinlock_t vma_lock;
|
||||
/// List of VMAs
|
||||
vma_t* vma_list;
|
||||
/// Is set, when the FPU is used
|
||||
uint32_t fpu_used;
|
||||
/// Mail inbox
|
||||
mailbox_wait_msg_t inbox;
|
||||
/// Mail outbox array
|
||||
mailbox_wait_msg_t* outbox[MAX_TASKS];
|
||||
/// FPU state
|
||||
union fpu_union fpu_state;
|
||||
union fpu_state fpu;
|
||||
} __attribute__((packed)) task_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -48,7 +48,7 @@ DEFINE_PER_CORE(task_t*, current_task, NULL);
|
|||
* A task's id will be its position in this array.
|
||||
*/
|
||||
static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, ATOMIC_INIT(0), \
|
||||
SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL}};
|
||||
SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0}};
|
||||
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
|
||||
/** @brief helper function for the assembly code to determine the current task
|
||||
|
@ -67,6 +67,7 @@ int multitasking_init(void) {
|
|||
memset(task_table[0].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
per_core(current_task) = task_table+0;
|
||||
per_core(current_task)->pgd = get_boot_pgd();
|
||||
task_table[0].fpu_used = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -189,6 +190,7 @@ static int create_task(tid_t* id, entry_point_t ep, void* arg)
|
|||
|
||||
ret = create_default_frame(task_table+i, ep, arg);
|
||||
|
||||
task_table[i].fpu_used = 0;
|
||||
task_table[i].status = TASK_READY;
|
||||
break;
|
||||
}
|
||||
|
@ -250,6 +252,7 @@ int sys_fork(void)
|
|||
mailbox_wait_msg_init(&task_table[i].inbox);
|
||||
memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
task_table[i].outbox[per_core(current_task)->id] = &per_core(current_task)->inbox;
|
||||
task_table[i].fpu_used = 0x00;
|
||||
|
||||
ret = arch_fork(task_table+i);
|
||||
|
||||
|
@ -707,7 +710,9 @@ void scheduler(void)
|
|||
if (per_core(current_task)->status == TASK_RUNNING)
|
||||
per_core(current_task)->status = TASK_READY;
|
||||
task_table[new_id].status = TASK_RUNNING;
|
||||
|
||||
|
||||
if (per_core(current_task)->fpu_used)
|
||||
save_fpu_state(&(per_core(current_task)->fpu));
|
||||
per_core(current_task) = task_table+new_id;
|
||||
goto get_task_out;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue