diff --git a/headers/private/kernel/arch/m68k/arch_cpu.h b/headers/private/kernel/arch/m68k/arch_cpu.h index 4a8560012a..bdf71d5e37 100644 --- a/headers/private/kernel/arch/m68k/arch_cpu.h +++ b/headers/private/kernel/arch/m68k/arch_cpu.h @@ -5,10 +5,17 @@ #ifndef _KERNEL_ARCH_M68K_CPU_H #define _KERNEL_ARCH_M68K_CPU_H +#ifndef _ASSEMBLER #include #include +#endif // !_ASSEMBLER + + + + +#ifndef _ASSEMBLER /* 68k has many different possible stack frames, differentiated by a 4 bit number, * but they also depend on the cpu type. @@ -195,11 +202,83 @@ struct mc680x0_frame { }; }; +struct mc680x0_null_fpu_state { + uint8 version; // 0 + uint8 type; // undefined + uint16 dummy; +}; + +struct mc680x0_type_00_fpu_state { + uint8 version; + uint8 type; // 0 + uint16 dummy; +}; + +struct mc680x0_type_28_fpu_state { + uint8 version; + uint8 type; // 0x28 + uint16 dummy; + // XXX: replace dummies + uint32 dummies[0x28/4]; +}; + +struct mc680x0_type_60_fpu_state { + uint8 version; + uint8 type; // 0x60 + uint16 dummy; + // XXX: replace dummies + uint32 dummies[0x60/4]; +}; + +//XXX: those are 040, add others +// biggest known: +struct mc68882_type_d4_fpu_state { + uint8 version; + uint8 type; // 0xd4 + uint16 dummy; + // XXX: replace dummies + uint32 dummies[0xd4/4]; +}; + +struct mc680x0_fpu_state { + union { + struct { + uint8 version; + uint8 type; // 0x60 + uint16 dummy; + }; + struct mc680x0_null_fpu_state null; + struct mc680x0_type_00_fpu_state type_00; + struct mc680x0_type_28_fpu_state type_28; + struct mc680x0_type_60_fpu_state type_60; + struct mc68882_type_d4_fpu_state type_d4; + }; +}; + +// 96-bit format +struct mc680x0_fp_data_reg { + uint8 data[12]; +}; + +struct mc680x0_fp_control_regs { + uint32 fpcr; + uint32 fpsr; + uint32 fpiar; +}; + + + #warning M68K: check for missing regs/movem struct iframe { - // XXX: fp_frame ? + /* fpu data registers */ +#warning M68K: sizeof(fp*) + struct mc680x0_fp_data_reg fp[8]; + /* fpu control registers */ + struct mc680x0_fp_control_regs fpc; + /* fpu state */ + struct mc680x0_fpu_state fpu; + /* data and address registers */ - // XXX: order depends on movem uint32 d[8]; uint32 a[7]; /* cpu exception frame, including sr, pc, format and vector */ @@ -438,4 +517,6 @@ extern int arch_platform; SPRG3: TLS base pointer (only for userland threads) */ +#endif // !_ASSEMBLER + #endif /* _KERNEL_ARCH_PPC_CPU_H */ diff --git a/headers/private/kernel/arch/m68k/arch_thread_types.h b/headers/private/kernel/arch/m68k/arch_thread_types.h index 1723fbba26..91dac99e19 100644 --- a/headers/private/kernel/arch/m68k/arch_thread_types.h +++ b/headers/private/kernel/arch/m68k/arch_thread_types.h @@ -5,6 +5,8 @@ #ifndef KERNEL_ARCH_M68K_THREAD_TYPES_H #define KERNEL_ARCH_M68K_THREAD_TYPES_H +#include + #define IFRAME_TRACE_DEPTH 4 struct iframe_stack { diff --git a/src/system/kernel/arch/m68k/Jamfile b/src/system/kernel/arch/m68k/Jamfile index 3ea9241052..abb7046275 100644 --- a/src/system/kernel/arch/m68k/Jamfile +++ b/src/system/kernel/arch/m68k/Jamfile @@ -51,3 +51,6 @@ KernelMergeObject kernel_arch_m68k.o : : $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused ; + +CreateAsmStructOffsetsHeader asm_offsets.h : asm_offsets.cpp ; + diff --git a/src/system/kernel/arch/m68k/arch_asm.S b/src/system/kernel/arch/m68k/arch_asm.S index 4673531a9d..09d2913fa0 100644 --- a/src/system/kernel/arch/m68k/arch_asm.S +++ b/src/system/kernel/arch/m68k/arch_asm.S @@ -6,9 +6,9 @@ * Distributed under the terms of the NewOS License. */ -#define FUNCTION(x) .global x; .type x,@function; x +#include -#define MSR_EXCEPTIONS_ENABLED 15 +#define FUNCTION(x) .global x; .type x,@function; x .text diff --git a/src/system/kernel/arch/m68k/arch_exceptions.S b/src/system/kernel/arch/m68k/arch_exceptions.S index b20198d257..6f0f13c529 100644 --- a/src/system/kernel/arch/m68k/arch_exceptions.S +++ b/src/system/kernel/arch/m68k/arch_exceptions.S @@ -5,11 +5,25 @@ * Copyright 2003, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. */ + +#include "asm_offsets.h" + #define FUNCTION(x) .global x; .type x,@function; x #define LOCAL_FUNCTION(x) .type x,@function; x + + /* General exception handling concept: + Starting with 68020 the vector offset (=vector number * 4) is part + of the all exception frame types, so we can easily have a common + asm stub for all of them, which calls m68k_exception_entry in + arch_int.cpp. + Also, m68k doesn't disable the mmu on interrupt as ppc does, + which makes things simpler. + + ----ppc + The PPC architecture specifies entry point offsets for the various exceptions in the first two physical pages. We put a short piece of code (VEC_ENTRY()) into each exception vector. It calls exception_vector_common, @@ -72,6 +86,51 @@ /* exception vector definitions */ +/* this one just returns */ +FUNCTION(__m68k_exception_noop): + rte + +/* see arch_asm.S for ctx switch */ + +FUNCTION(__m68k_exception_common): + /* save regs */ + movem.l %d0-%d7/%a0-%a7,-(%sp) /* push the iframe address */ + /* save fp */ + sub.l #FPU_STATE_sizeof,%sp + fsave (%sp) + tst.b (%sp) /* check for a null state */ + beq null_sav_1 /* yes */ + + fmovem %fpcr/%fpsr/%fpiar,-(%sp) + fmovem %fp0-%fp7,-(%sp) + bra null_sav_2 +null_sav_1: + sub.l #IFRAME_fpu-IFRAME_fp,%sp +null_sav_2: + + bsr m68k_exception_entry /* call C entry */ + + /* restore fp */ + tst.b IFRAME_fpu-IFRAME_fp(%sp) /* check for a null state */ + beq null_res_1 /* yes */ + fmovem (%sp)+,%fp0-%fp7 + fmovem (%sp)+,%fpcr/%fpsr/%fpiar + bra null_res_2 +null_res_1: + add.l #IFRAME_fpu-IFRAME_fp,%sp +null_res_2: + /* restore fp */ + frestore (%sp) + add.l #FPU_STATE_sizeof,%sp + /* restore regs */ + movem.l (%sp)+,%d0-%d7/%a0-%a7 + + rte + + + +#if 0 /* PPC */ + /* code in each exception vector */ #define VEC_ENTRY() \ mtsprg1 %r1 ; /* temporarily save r1 in SPRG1 */ \ @@ -437,3 +496,4 @@ __restore_regs_and_rfi: /* return from interrupt */ rfi +#endif /* PPC */ diff --git a/src/system/kernel/arch/m68k/arch_int.cpp b/src/system/kernel/arch/m68k/arch_int.cpp index 4d2c3498fe..ca2db30eb4 100644 --- a/src/system/kernel/arch/m68k/arch_int.cpp +++ b/src/system/kernel/arch/m68k/arch_int.cpp @@ -28,11 +28,26 @@ #include #include #include - #include + #warning M68K: writeme! + +//#define TRACE_ARCH_INT +#ifdef TRACE_ARCH_INT +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +typedef void (*m68k_exception_handler)(void); +#define M68K_EXCEPTION_VECTOR_COUNT 256 +m68k_exception_handler gExceptionVectors[M68K_EXCEPTION_VECTOR_COUNT]; + // defined in arch_exceptions.S +extern "C" void __m68k_exception_noop(void); +extern "C" void __m68k_exception_common(void); + extern int __irqvec_start; extern int __irqvec_end; @@ -100,15 +115,16 @@ print_iframe(struct iframe *frame) } -extern "C" void m68k_exception_entry(int vector, struct iframe *iframe); +extern "C" void m68k_exception_entry(struct iframe *iframe); void -m68k_exception_entry(int vector, struct iframe *iframe) +m68k_exception_entry(struct iframe *iframe) { + int vector = iframe->cpu.vector >> 2; int ret = B_HANDLED_INTERRUPT; - if (vector != 0x900) { + if (vector != -1) { dprintf("m68k_exception_entry: time %lld vector 0x%x, iframe %p, " - "srr0: %p\n", system_time(), vector, iframe, (void*)iframe->srr0); + "pc: %p\n", system_time(), vector, iframe, (void*)iframe->cpu.pc); } struct thread *thread = thread_get_current_thread(); @@ -120,14 +136,11 @@ m68k_exception_entry(int vector, struct iframe *iframe) m68k_push_iframe(&gBootFrameStack, iframe); switch (vector) { - case 0x100: // system reset + case 0: // system reset panic("system reset exception\n"); break; - case 0x200: // machine check - panic("machine check exception\n"); - break; - case 0x300: // DSI - case 0x400: // ISI + case 2: // bus error + case 3: // address error { bool kernelDebugger = debug_debugger_running(); @@ -174,7 +187,16 @@ m68k_exception_entry(int vector, struct iframe *iframe) break; } - case 0x500: // external interrupt + case 24: // spurious interrupt + dprintf("spurious interrupt\n"); + break; + case 25: // autovector interrupt + case 26: // autovector interrupt + case 27: // autovector interrupt + case 28: // autovector interrupt + case 29: // autovector interrupt + case 30: // autovector interrupt + case 31: // autovector interrupt { if (!sPIC) { panic("m68k_exception_entry(): external interrupt although we " @@ -193,50 +215,10 @@ dprintf("handling I/O interrupts done\n"); break; } - case 0x600: // alignment exception - panic("alignment exception: unimplemented\n"); - break; - case 0x700: // program exception - panic("program exception: unimplemented\n"); - break; - case 0x800: // FP unavailable exception - panic("FP unavailable exception: unimplemented\n"); - break; - case 0x900: // decrementer exception - ret = timer_interrupt(); - break; - case 0xc00: // system call - panic("system call exception: unimplemented\n"); - break; - case 0xd00: // trace exception - panic("trace exception: unimplemented\n"); - break; - case 0xe00: // FP assist exception - panic("FP assist exception: unimplemented\n"); - break; - case 0xf00: // performance monitor exception - panic("performance monitor exception: unimplemented\n"); - break; - case 0xf20: // altivec unavailable exception - panic("alitivec unavailable exception: unimplemented\n"); - break; - case 0x1000: - case 0x1100: - case 0x1200: - panic("TLB miss exception: unimplemented\n"); - break; - case 0x1300: // instruction address exception - panic("instruction address exception: unimplemented\n"); - break; - case 0x1400: // system management exception - panic("system management exception: unimplemented\n"); - break; - case 0x1600: // altivec assist exception - panic("altivec assist exception: unimplemented\n"); - break; case 0x1700: // thermal management exception panic("thermal management exception: unimplemented\n"); break; + case 9: // trace default: dprintf("unhandled exception type 0x%x\n", vector); print_iframe(iframe); diff --git a/src/system/kernel/arch/m68k/asm_offsets.cpp b/src/system/kernel/arch/m68k/asm_offsets.cpp index 77ea318efd..ec2ceabe25 100644 --- a/src/system/kernel/arch/m68k/asm_offsets.cpp +++ b/src/system/kernel/arch/m68k/asm_offsets.cpp @@ -35,6 +35,14 @@ dummy() DEFINE_OFFSET_MACRO(THREAD, thread, kernel_stack_top); DEFINE_OFFSET_MACRO(THREAD, thread, fault_handler); + // struct iframe + DEFINE_OFFSET_MACRO(IFRAME, iframe, fp); + DEFINE_OFFSET_MACRO(IFRAME, iframe, fpc); + DEFINE_OFFSET_MACRO(IFRAME, iframe, fpu); + DEFINE_OFFSET_MACRO(IFRAME, iframe, d); + DEFINE_OFFSET_MACRO(IFRAME, iframe, a); + DEFINE_OFFSET_MACRO(IFRAME, iframe, cpu); +#if 0 // struct iframe DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); DEFINE_OFFSET_MACRO(IFRAME, iframe, eax); @@ -44,17 +52,13 @@ dummy() DEFINE_OFFSET_MACRO(IFRAME, iframe, eip); DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); DEFINE_OFFSET_MACRO(IFRAME, iframe, user_esp); +#endif - // struct vm86_iframe - DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); - DEFINE_OFFSET_MACRO(VM86_IFRAME, vm86_iframe, flags); + DEFINE_SIZEOF_MACRO(FPU_STATE, mc680x0_fpu_state); + DEFINE_SIZEOF_MACRO(FPU_DATA_REG, mc680x0_fp_data_reg); // struct syscall_info DEFINE_SIZEOF_MACRO(SYSCALL_INFO, syscall_info); DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, function); DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, parameter_size); - - // struct x86_optimized_functions - DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, - memcpy); }