[haiku-commits] haiku: hrev44796 - in src/system/kernel/arch/arm: . paging/32bit

  • From: ithamar.adema@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 7 Nov 2012 16:28:17 +0100 (CET)

hrev44796 adds 4 changesets to branch 'master'
old head: 0ba9bff27d88633aa0f9a6477342aa79fccbf4f7
new head: f86b5828486b661145eb15952ec14648c9bb8d9b

----------------------------------------------------------------------------

0e5d97e: ARM/vm: small formatting change and trace fix.
  
  Copy some minor changes over from the X86 paging implementation to keep
  the two reasonably aligned. Smaller diff ;-)

ff16358: ARM/threads: Disable debug output
  
  Tracing was accidently switched on by a previous commit.

0cf5ecb: ARM: Add asm_offsets.cpp
  
  This will generate asm_offsets.h which makes our assembly code
  easier to maintain by preventing hardcoded offsets for fields within 
structures.
  
  (copied from X86 and removed the X86 specifics)

f86b582: ARM: Cleanup of port support code.
  
  This also implements the fault handler correctly now, and cleans up the
  exception handling. Seems a lot more stable now, no unexpected panics or
  faults happening anymore.

                          [ Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

11 files changed, 462 insertions(+), 249 deletions(-)
headers/private/kernel/arch/arm/arch_cpu.h       |  22 +-
src/system/kernel/arch/arm/arch_asm.S            |  80 +++++-
src/system/kernel/arch/arm/arch_debug.cpp        |  23 +-
src/system/kernel/arch/arm/arch_exceptions.S     | 242 +++++++++++--------
src/system/kernel/arch/arm/arch_int.cpp          | 167 +++++++++----
src/system/kernel/arch/arm/arch_platform.cpp     |  43 +---
src/system/kernel/arch/arm/arch_thread.cpp       |   2 +-
src/system/kernel/arch/arm/arch_timer.cpp        |  14 +-
src/system/kernel/arch/arm/asm_offsets.cpp       |  62 +++++
.../arm/paging/32bit/ARMPagingMethod32Bit.cpp    |   7 +-
.../paging/32bit/ARMVMTranslationMap32Bit.cpp    |  49 ++--

############################################################################

Commit:      0e5d97e97e32eae4023d4223d6ac6527c76cabd7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0e5d97e
Author:      Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx>
Date:        Tue Nov  6 10:01:13 2012 UTC

ARM/vm: small formatting change and trace fix.

Copy some minor changes over from the X86 paging implementation to keep
the two reasonably aligned. Smaller diff ;-)

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp 
b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
index 9214286..cfcd630 100644
--- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
+++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
@@ -169,7 +169,8 @@ void
 ARMPagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
        addr_t virtualAddress)
 {
-       page_table_entry& pte = fPageTable[(virtualAddress - fVirtualBase) / 
B_PAGE_SIZE];
+       page_table_entry& pte = fPageTable[
+               (virtualAddress - fVirtualBase) / B_PAGE_SIZE];
        pte = (physicalAddress & ARM_PTE_ADDRESS_MASK)
                | ARM_PTE_TYPE_SMALL_PAGE;
 
@@ -298,7 +299,7 @@ ARMPagingMethod32Bit::Init(kernel_args* args,
                x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES);
        }
 #endif
-       TRACE("vm_translation_map_init: done\n");
+       TRACE("ARMPagingMethod32Bit::Init(): done\n");
 
        *_physicalPageMapper = fPhysicalPageMapper;
        return B_OK;

############################################################################

Commit:      ff163585ecf0e47c4b411129fdc13572db53cd9d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=ff16358
Author:      Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx>
Date:        Tue Nov  6 10:02:54 2012 UTC

ARM/threads: Disable debug output

Tracing was accidently switched on by a previous commit.

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/arm/arch_thread.cpp 
b/src/system/kernel/arch/arm/arch_thread.cpp
index 2ae92ae..3f7950e 100644
--- a/src/system/kernel/arch/arm/arch_thread.cpp
+++ b/src/system/kernel/arch/arm/arch_thread.cpp
@@ -28,7 +28,7 @@
 
 #include <string.h>
 
-#define TRACE_ARCH_THREAD
+//#define TRACE_ARCH_THREAD
 #ifdef TRACE_ARCH_THREAD
 #      define TRACE(x) dprintf x
 #else

############################################################################

Commit:      0cf5ecba126fe8215db0b079adfb1a6f9ac49e11
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0cf5ecb
Author:      Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx>
Date:        Tue Nov  6 10:06:04 2012 UTC

ARM: Add asm_offsets.cpp

This will generate asm_offsets.h which makes our assembly code
easier to maintain by preventing hardcoded offsets for fields within structures.

(copied from X86 and removed the X86 specifics)

----------------------------------------------------------------------------

diff --git a/src/system/kernel/arch/arm/asm_offsets.cpp 
b/src/system/kernel/arch/arm/asm_offsets.cpp
new file mode 100644
index 0000000..64e8505
--- /dev/null
+++ b/src/system/kernel/arch/arm/asm_offsets.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+// This file is used to get C structure offsets into assembly code.
+// The build system assembles the file and processes the output to create
+// a header file with macro definitions, that can be included from assembly
+// code.
+
+
+#include <computed_asm_macros.h>
+
+#include <arch_cpu.h>
+#include <cpu.h>
+#include <ksignal.h>
+#include <ksyscalls.h>
+#include <thread_types.h>
+
+
+#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value)
+
+#define DEFINE_OFFSET_MACRO(prefix, structure, member) \
+    DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member));
+
+#define DEFINE_SIZEOF_MACRO(prefix, structure) \
+    DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure));
+
+
+void
+dummy()
+{
+       // struct cpu_ent
+       DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler);
+       DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer);
+
+       // struct Thread
+       DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, user_time);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, last_time);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, flags);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top);
+       DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler);
+
+       // struct iframe
+       DEFINE_SIZEOF_MACRO(IFRAME, iframe);
+
+       // struct signal_frame_data
+       DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
+       DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info);
+       DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context);
+       DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data);
+       DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler);
+
+       // struct ucontext_t
+       DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext);
+
+       // struct siginfo_t
+       DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo);
+}

############################################################################

Revision:    hrev44796
Commit:      f86b5828486b661145eb15952ec14648c9bb8d9b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f86b582
Author:      Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx>
Date:        Tue Nov  6 10:41:12 2012 UTC

ARM: Cleanup of port support code.

This also implements the fault handler correctly now, and cleans up the
exception handling. Seems a lot more stable now, no unexpected panics or
faults happening anymore.

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/arm/arch_cpu.h 
b/headers/private/kernel/arch/arm/arch_cpu.h
index 97ae146..34364a8 100644
--- a/headers/private/kernel/arch/arm/arch_cpu.h
+++ b/headers/private/kernel/arch/arm/arch_cpu.h
@@ -12,6 +12,7 @@
 
 /* raw exception frames */
 struct iframe {
+       uint32 spsr;
        uint32 r0;
        uint32 r1;
        uint32 r2;
@@ -25,10 +26,11 @@ struct iframe {
        uint32 r10;
        uint32 r11;
        uint32 r12;
-       uint32 r13;
-       uint32 lr;
+       uint32 usr_sp;
+       uint32 usr_lr;
+       uint32 svc_sp;
+       uint32 svc_lr;
        uint32 pc;
-       uint32 cpsr;
 } _PACKED;
 
 typedef struct arch_cpu_info {
@@ -40,6 +42,20 @@ extern int arch_mmu_type;
 extern int arch_platform;
 extern int arch_machine;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern addr_t arm_get_far(void);
+extern int32 arm_get_fsr(void);
+
+extern int mmu_read_c1(void);
+extern int mmu_write_c1(int val);
+
+#ifdef __cplusplus
+};
+#endif
+
 #endif // !_ASSEMBLER
 
 #endif /* _KERNEL_ARCH_ARM_CPU_H */
diff --git a/src/system/kernel/arch/arm/arch_asm.S 
b/src/system/kernel/arch/arm/arch_asm.S
index c417a91..c51089c 100644
--- a/src/system/kernel/arch/arm/arch_asm.S
+++ b/src/system/kernel/arch/arm/arch_asm.S
@@ -10,21 +10,38 @@
 
 #include <asm_defs.h>
 
+#include "asm_offsets.h"
+
 .text
 
 
+/* int mmu_read_c1(void); */
+FUNCTION(mmu_read_c1):
+       mrc     p15, 0, r0, c1, c0, 0
+       bx      lr
+FUNCTION_END(mmu_read_c1)
+
+
+/* void mmu_write_c1(int val); */
+FUNCTION(mmu_write_c1):
+       mcr     p15, 0, r0, c1, c0, 0
+       bx      lr
+FUNCTION_END(mmu_write_c1)
+
+
+/* NOTE: the I bit in cpsr (bit 7) is *set* to disable... */
+
 
 /* void arch_int_enable_interrupts(void) */
 FUNCTION(arch_int_enable_interrupts):
         mrs     r0, cpsr
-        bic     r0, r0, #(1<<7)         /* clear the I bit */
+        bic     r0, r0, #(1<<7)
         msr     cpsr_c, r0
         bx      lr
 FUNCTION_END(arch_int_enable_interrupts)
 
 
-/* int arch_int_disable_interrupts(void) 
- */
+/* int arch_int_disable_interrupts(void) */
 FUNCTION(arch_int_disable_interrupts):
         mrs     r0, cpsr
         orr     r1, r0, #(1<<7)
@@ -33,8 +50,7 @@ FUNCTION(arch_int_disable_interrupts):
 FUNCTION_END(arch_int_disable_interrupts)
 
 
-/* void arch_int_restore_interrupts(int oldState) 
- */
+/* void arch_int_restore_interrupts(int oldState) */
 FUNCTION(arch_int_restore_interrupts):
        mrs     r1, cpsr
        and     r0, r0, #(1<<7)
@@ -65,3 +81,57 @@ FUNCTION(arm_context_switch):
        ldmfd   sp!, { r0-r12, lr }
        bx      lr
 FUNCTION_END(arm_context_switch)
+
+/* addr_t arm_get_fsr(void); */
+FUNCTION(arm_get_fsr):
+       mrc     p15, 0, r0, c5, c0, 0           @ get FSR
+       bx      lr
+FUNCTION_END(arm_get_fsr)
+
+/* addr_t arm_get_far(void); */
+FUNCTION(arm_get_far):
+       mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+       bx      lr
+FUNCTION_END(arm_get_far)
+
+/*!    \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
+               jmp_buf jumpBuffer, void (*function)(void*), void* parameter)
+
+       Called by debug_call_with_fault_handler() to do the dirty work of 
setting
+       the fault handler and calling the function. If the function causes a 
page
+       fault, the arch_debug_call_with_fault_handler() calls longjmp() with the
+       given \a jumpBuffer. Otherwise it returns normally.
+
+       debug_call_with_fault_handler() has already saved the CPU's 
fault_handler
+       and fault_handler_stack_pointer and will reset them later, so
+       arch_debug_call_with_fault_handler() doesn't need to care about it.
+
+       \param cpu The \c cpu_ent for the current CPU.
+       \param jumpBuffer Buffer to be used for longjmp().
+       \param function The function to be called.
+       \param parameter The parameter to be passed to the function to be 
called.
+*/
+FUNCTION(arch_debug_call_with_fault_handler):
+       stmfd   sp!, { r4, lr }
+
+       // Set fault handler address, and fault handler stack pointer address. 
We
+       // don't need to save the previous values, since that's done by the 
caller.
+       ldr     r4, =1f
+       str     r4, [ r0, #CPU_ENT_fault_handler ]
+       str     sp, [ r0, #CPU_ENT_fault_handler_stack_pointer ]
+       mov     r4, r1
+
+       // call the function
+       mov     r0, r3
+       blx     r2
+
+       // regular return
+       ldmfd   sp!, { r4, lr }
+       bx      lr
+
+       // fault -- return via longjmp(jumpBuffer, 1)
+1:
+       mov     r0, r4
+       mov     r1, #1
+       bl      longjmp
+FUNCTION_END(arch_debug_call_with_fault_handler)
diff --git a/src/system/kernel/arch/arm/arch_debug.cpp 
b/src/system/kernel/arch/arm/arch_debug.cpp
index 0b64490..daae859 100644
--- a/src/system/kernel/arch/arm/arch_debug.cpp
+++ b/src/system/kernel/arch/arm/arch_debug.cpp
@@ -251,14 +251,9 @@ arch_debug_stack_trace(void)
 void *
 arch_debug_get_caller(void)
 {
-#warning ARM:IMPLEMENT
-       // TODO: implement me
-       //return __builtin_frame_address(1);
-//     struct stack_frame *frame;
-       //frame = __builtin_frame_address(0);
-//     frame = get_current_stack_frame();
-//     return (void *)frame->previous->return_address;
-       return NULL;
+       /* Return the thread id as the kernel (for example the lock code) 
actually
+          gets a somewhat valid indication of the caller back. */
+       return (void*) thread_get_current_thread_id();
 }
 
 
@@ -316,17 +311,7 @@ arch_debug_init(kernel_args *args)
 }
 
 
-void
-arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
-       void (*function)(void*), void* parameter)
-{
-       // TODO: Implement fault handling! Most likely in assembly.
-       // (see src/system/kernel/arch/x86/arch_x86.S)
-
-       // For now, just call the function and hope we don't crash :P
-       function(parameter);
-}
-
+/* arch_debug_call_with_fault_handler is in arch_asm.S */
 
 void
 arch_debug_unset_current_thread(void)
diff --git a/src/system/kernel/arch/arm/arch_exceptions.S 
b/src/system/kernel/arch/arm/arch_exceptions.S
index cffb1f8..41a88d9 100644
--- a/src/system/kernel/arch/arm/arch_exceptions.S
+++ b/src/system/kernel/arch/arm/arch_exceptions.S
@@ -9,6 +9,49 @@
 
 #include <asm_defs.h>
 
+#define CPSR_MODE_MASK 0x1f
+#define CPSR_MODE_USR  0x10
+#define CPSR_MODE_FIQ  0x11
+#define CPSR_MODE_IRQ  0x12
+#define CPSR_MODE_SVC  0x13
+#define CPSR_MODE_ABT  0x17
+#define CPSR_MODE_UND  0x1b
+
+/* The following two macros are taken from FreeBSD... */
+
+       .macro PUSHFRAMEINSVC
+       stmdb   sp, {r0-r3}             /* Save 4 registers */
+       mov     r0, lr                  /* Save xxx32 r14 */
+       mov     r1, sp                  /* Save xxx32 sp */
+       mrs     r3, spsr                /* Save xxx32 spsr */
+       mrs     r2, cpsr                /* Get the CPSR */
+       bic     r2, r2, #(CPSR_MODE_MASK)/* Fix for SVC mode */
+       orr     r2, r2, #(CPSR_MODE_SVC)
+       msr     cpsr_c, r2              /* Punch into SVC mode */
+       mov     r2, sp                  /* Save SVC sp */
+       str     r0, [sp, #-4]!          /* Push return address */
+       str     lr, [sp, #-4]!          /* Push SVC lr */
+       str     r2, [sp, #-4]!          /* Push SVC sp */
+       msr     spsr_all, r3            /* Restore correct spsr */
+       ldmdb   r1, {r0-r3}             /* Restore 4 regs from xxx mode */
+       sub     sp, sp, #(4*15)         /* Adjust the stack pointer */
+       stmia   sp, {r0-r12}            /* Push the user mode registers */
+       add     r0, sp, #(4*13)         /* Adjust the stack pointer */
+       stmia   r0, {r13-r14}^          /* Push the user mode registers */
+       mov     r0, r0                  /* NOP for previous instruction */
+       mrs     r0, spsr_all
+       str     r0, [sp, #-4]!          /* Save spsr */
+       .endm
+
+       .macro PULLFRAMEFROMSVCANDEXIT
+       ldr     r0, [sp], #0x0004       /* Get the SPSR from stack */
+       msr     spsr_all, r0            /* restore SPSR */
+       ldmia   sp, {r0-r14}^           /* Restore registers (usr mode) */
+       mov     r0, r0                  /* NOP for previous instruction */
+       add     sp, sp, #(4*15)         /* Adjust the stack pointer */
+       ldmia   sp, {sp, lr, pc}^       /* Restore lr and exit */
+       .endm
+
        .text
 
 .globl _vectors_start
@@ -43,134 +86,139 @@ _vectors_end:
 
 
        .rept   64
-       .word   0xaabbccdd      
+       .word   0xdeadbeef
        .endr
 abort_stack:
-       .word   .
+       .word   . - 4
+       .word   0xdeadbeef
+
+       .rept   64
+       .word   0xcafebabe
+       .endr
+irq_stack:
+       .word   . - 4
+       .word   0xcafebabe
+
+       .rept   64
+       .word   0xaaaabbbb
+       .endr
+fiq_stack:
+       .word   . - 4
+       .word   0xaaaabbbb
+
+       .rept   64
+       .word   0xccccdddd
+       .endr
+und_stack:
+       .word   . - 4
+       .word   0xccccdddd
+
 
 FUNCTION(arm_undefined):
-       stmfd   sp!, { r0-r12, r14 }
-       sub             sp, sp, #12
-       mov             r0, sp
-       mrs             r1, spsr
-       stmia   r0, { r1, r13-r14 }
-       b               arch_arm_undefined
-       b               .
+       PUSHFRAMEINSVC
+
+       mov     r0, sp
+       bl      arch_arm_undefined
+
+       PULLFRAMEFROMSVCANDEXIT
+FUNCTION_END(arm_undefined)
+
 
 FUNCTION(arm_syscall):
-       stmfd   sp!, { r0-r12, r14 }
-       sub             sp, sp, #12
-       mov             r0, sp
-       mrs             r1, spsr
-       stmia   r0, { r1, r13-r14 }
-       b               arch_arm_syscall
-       b               .
-       
-FUNCTION(arm_prefetch_abort):
-       ldr     sp, abort_stack
-       stmfd   sp!, { r0-r12, r14 }
-       sub             sp, sp, #12
-       mov             r0, sp
-       mrs             r1, spsr
-       stmia   r0, { r1, r13-r14 }
-       b               arch_arm_prefetch_abort
-       b               .
+       PUSHFRAMEINSVC
 
-FUNCTION(arm_data_abort):
-       ldr     sp, abort_stack
-       /* XXX only deals with interrupting supervisor mode */
+       mov     r0, sp
+       bl      arch_arm_syscall
 
-       /* save r4-r6 and use as a temporary place to save while we switch into 
supervisor mode */
-       stmia   r13, { r4-r6 }
-       mov     r4, r13
-       sub     r5, lr, #8
-       mrs     r6, spsr
+       PULLFRAMEFROMSVCANDEXIT
+FUNCTION_END(arm_syscall)
 
-       /* move into supervisor mode. irq/fiq disabled */
-       msr     cpsr_c, #0x13
 
-       /* save the return address */
-       stmfd   sp!, { r5 }
+FUNCTION(arm_prefetch_abort):
+#ifdef __XSCALE__
+       nop                             /* Make absolutely sure any pending */
+       nop                             /* imprecise aborts have occurred. */
+#endif
+       add     lr, lr, #4
+       PUSHFRAMEINSVC
 
-       /* save C trashed regs, supervisor lr */
-       stmfd   sp!, { r0-r3, r12, lr }
+       mov     r0, sp
+       bl      arch_arm_prefetch_abort
 
-       /* save spsr */
-       stmfd   sp!, { r6 }
+       PULLFRAMEFROMSVCANDEXIT
+FUNCTION_END(arm_prefetch_abort)
 
-       /* restore r4-r6 */
-       ldmia   r4, { r4-r6 }
 
-       /* call into higher level code */
-        mrc     p15, 0, r2, c5, c0, 0           @ get FSR
-        mrc     p15, 0, r3, c6, c0, 0           @ get FAR
-       sub     sp, sp, #20
-       mov     r0, sp /* iframe */
-       stmia   r0, { r6,r2,r3,r4,r5 }
+FUNCTION(arm_data_abort):
+#ifdef __XSCALE__
+       nop                             /* Make absolutely sure any pending */
+       nop                             /* imprecise aborts have occurred. */
+#endif
+       sub     lr, lr, #8              /* Adjust the lr */
+       PUSHFRAMEINSVC
+
+       mov     r0, sp
        bl      arch_arm_data_abort
-       add     sp, sp, #20
 
-       /* restore spsr */
-       ldmfd   sp!, { r0 }
-       msr     spsr_cxsf, r0
+       PULLFRAMEFROMSVCANDEXIT
 
-       /* restore back to where we came from */
-       ldmfd   sp!, { r0-r3, r12, lr, pc }^
 
 FUNCTION(arm_reserved):
        b       .
-       
+FUNCTION_END(arm_reserved)
+
 FUNCTION(arm_irq):
-       ldr     sp, abort_stack
-       /* XXX only deals with interrupting supervisor mode */
+       sub     lr, lr, #4
+       PUSHFRAMEINSVC
 
-       /* save r4-r6 and use as a temporary place to save while we switch into 
supervisor mode */
-       stmia   r13, { r4-r6 }
-       mov     r4, r13
-       sub     r5, lr, #4
-       mrs     r6, spsr
+       mov     r0, sp /* iframe */
+       bl      arch_arm_irq
 
-       /* move into supervisor mode. irq/fiq disabled */
-       msr     cpsr_c, #(3<<6 | 0x13)
+       PULLFRAMEFROMSVCANDEXIT
+FUNCTION_END(arm_irq)
 
-       /* save the return address */
-       stmfd   sp!, { r5 }
 
-       /* save C trashed regs, supervisor lr */
-       stmfd   sp!, { r0-r3, r12, lr }
+FUNCTION(arm_fiq):
+       sub     lr, lr, #4
+       PUSHFRAMEINSVC
 
-       /* save spsr */
-       stmfd   sp!, { r6 }
+       mov     r0, sp /* iframe */
+       bl      arch_arm_fiq
+       
+       PULLFRAMEFROMSVCANDEXIT
+FUNCTION_END(arm_fiq)
 
-       /* restore r4-r6 */
-       ldmia   r4, { r4-r6 }
 
-       /* call into higher level code */
-       mov     r0, sp /* iframe */
-       bl      arch_arm_irq
 
-       /* restore spsr */
-       ldmfd   sp!, { r0 }
-       msr     spsr_cxsf, r0
+FUNCTION(arm_vector_init):
+       mrs     r1, cpsr
+       bic     r1, r1, #CPSR_MODE_MASK
 
-       /* restore back to where we came from */
-       ldmfd   sp!, { r0-r3, r12, lr, pc }^
+       /* move into modes and set initial sp */
+       mov     r0, r1
+       orr     r0, r0, #CPSR_MODE_FIQ
+       msr     cpsr_c, r0
+       ldr     sp, fiq_stack
 
-.bss
-.align 2
-       .global irq_save_spot
-irq_save_spot:
-       .word   0       /* r4 */
-       .word   0       /* r5 */
-       .word   0       /* r6 */
-       
-.text
-FUNCTION(arm_fiq):
+       mov     r0, r1
+       orr     r0, r0, #CPSR_MODE_IRQ
+       msr     cpsr_c, r0
+       ldr     sp, irq_stack
+
+       mov     r0, r1
+       orr     r0, r0, #CPSR_MODE_ABT
+       msr     cpsr_c, r0
        ldr     sp, abort_stack
-       sub     lr, lr, #4
-       stmfd   sp!, { r0-r3, r12, lr }
 
-       bl      arch_arm_fiq
-       
-       ldmfd   sp!, { r0-r3, r12, pc }^
+       mov     r0, r1
+       orr     r0, r0, #CPSR_MODE_UND
+       msr     cpsr_c, r0
+       ldr     sp, und_stack
+
+       /* ... and return back to supervisor mode */
+       mov     r0, r1
+       orr     r0, r0, #CPSR_MODE_SVC
+       msr     cpsr_c, r0
 
+       bx      lr
+FUNCTION_END(arm_vector_init)
diff --git a/src/system/kernel/arch/arm/arch_int.cpp 
b/src/system/kernel/arch/arm/arch_int.cpp
index 97a735a..f61298d 100644
--- a/src/system/kernel/arch/arm/arch_int.cpp
+++ b/src/system/kernel/arch/arm/arch_int.cpp
@@ -31,7 +31,7 @@
 #include <string.h>
 
 
-#define TRACE_ARCH_INT
+//#define TRACE_ARCH_INT
 #ifdef TRACE_ARCH_INT
 #      define TRACE(x) dprintf x
 #else
@@ -61,30 +61,11 @@ static void *sVectorPageAddress;
 static area_id sUserVectorPageArea;
 static void *sUserVectorPageAddress;
 
-// current fault handler
-addr_t gFaultHandler;
-
 // An iframe stack used in the early boot process when we don't have
 // threads yet.
 struct iframe_stack gBootFrameStack;
 
 
-uint32
-mmu_read_c1()
-{
-       uint32 controlReg = 0;
-       asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" 
(controlReg));
-       return controlReg;
-}
-
-
-void
-mmu_write_c1(uint32 value)
-{
-       asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
-}
-
-
 void
 arch_int_enable_io_interrupt(int irq)
 {
@@ -117,29 +98,32 @@ arch_int_disable_io_interrupt(int irq)
 
 
 static void
-print_iframe(struct iframe *frame)
+print_iframe(const char *event, struct iframe *frame)
 {
+       if (event)
+               dprintf("Exception: %s\n", event);
+
+       dprintf("R00=%08lx R01=%08lx R02=%08lx R03=%08lx\n"
+               "R04=%08lx R05=%08lx R06=%08lx R07=%08lx\n",
+               frame->r0, frame->r1, frame->r2, frame->r3,
+               frame->r4, frame->r5, frame->r6, frame->r7);
+       dprintf("R08=%08lx R09=%08lx R10=%08lx R11=%08lx\n"
+               "R12=%08lx R13=%08lx R14=%08lx CPSR=%08lx\n",
+               frame->r8, frame->r9, frame->r10, frame->r11,
+               frame->r12, frame->usr_sp, frame->usr_lr, frame->spsr);
 }
 
 
 status_t
 arch_int_init(kernel_args *args)
 {
-       // see if high vectors are enabled
-       if (mmu_read_c1() & (1<<13))
-               dprintf("High vectors already enabled\n");
-       else {
-               mmu_write_c1(mmu_read_c1() | (1<<13));
-
-               if (!(mmu_read_c1() & (1<<13)))
-                       dprintf("Unable to enable high vectors!\n");
-               else
-                       dprintf("Enabled high vectors\n");
-       }
-
        return B_OK;
 }
 
+
+extern "C" void arm_vector_init(void);
+
+
 status_t
 arch_int_init_post_vm(kernel_args *args)
 {
@@ -163,6 +147,20 @@ arch_int_init_post_vm(kernel_args *args)
        // copy vectors into the newly created area
        memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE);
 
+       arm_vector_init();
+
+       // see if high vectors are enabled
+       if (mmu_read_c1() & (1<<13))
+               dprintf("High vectors already enabled\n");
+       else {
+               mmu_write_c1(mmu_read_c1() | (1<<13));
+
+               if (!(mmu_read_c1() & (1<<13)))
+                       dprintf("Unable to enable high vectors!\n");
+               else
+                       dprintf("Enabled high vectors\n");
+       }
+
        sPxaInterruptArea = map_physical_memory("pxa_intc", 
PXA_INTERRUPT_PHYS_BASE,
                PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | 
B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase);
 
@@ -179,7 +177,6 @@ arch_int_init_post_vm(kernel_args *args)
 status_t
 arch_int_init_io(kernel_args* args)
 {
-       TRACE(("arch_int_init_io(%p)\n", args));
        return B_OK;
 }
 
@@ -193,35 +190,103 @@ arch_int_init_post_device_manager(struct kernel_args 
*args)
 
 extern "C" void arch_arm_undefined(struct iframe *iframe)
 {
-       panic("Undefined instruction!");
+       print_iframe("Undefined Instruction", iframe);
+       panic("not handled!");
 }
 
 extern "C" void arch_arm_syscall(struct iframe *iframe)
 {
-       panic("Software interrupt!\n");
+       print_iframe("Software interrupt", iframe);
 }
 
-extern "C" void arch_arm_data_abort(struct iframe *iframe)
+extern "C" void arch_arm_data_abort(struct iframe *frame)
 {
-       addr_t newip;
-       status_t res = vm_page_fault(iframe->r2 /* FAR */, iframe->r4 /* lr */,
-               true /* TODO how to determine read/write? */,
-               false /* only kernelspace for now */,
-               &newip);
-
-       if (res != B_HANDLED_INTERRUPT) {
-               panic("Data Abort: %08x %08x %08x %08x (res=%lx)", iframe->r0 
/* spsr */, 
-                       iframe->r1 /* FSR */, iframe->r2 /* FAR */,
-                       iframe->r4 /* lr */,
-                       res);
-       } else {
-               //panic("vm_page_fault was ok (%08lx/%08lx)!", iframe->r2 /* 
FAR */, iframe->r0 /* spsr */);
+       Thread *thread = thread_get_current_thread();
+       bool isUser = (frame->spsr & 0x1f) == 0x10;
+       addr_t far = arm_get_far();
+       bool isWrite = true;
+       addr_t newip = 0;
+
+#ifdef TRACE_ARCH_INT
+       print_iframe("Data Abort", frame);
+#endif
+
+       if (debug_debugger_running()) {
+               // If this CPU or this thread has a fault handler, we're 
allowed to be
+               // here.
+               if (thread != NULL) {
+                       cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
+
+                       if (cpu->fault_handler != 0) {
+                               kprintf("CPU fault handler set! %p %p\n",
+                                       (void*)cpu->fault_handler, 
(void*)cpu->fault_handler_stack_pointer);
+                               debug_set_page_fault_info(far, frame->pc,
+                                       isWrite ? DEBUG_PAGE_FAULT_WRITE : 0);
+                               frame->svc_sp = 
cpu->fault_handler_stack_pointer;
+                               frame->pc = cpu->fault_handler;
+                               return;
+                       }
+
+                       if (thread->fault_handler != 0) {
+                               kprintf("ERROR: thread::fault_handler used in 
kernel "
+                                       "debugger!\n");
+                               debug_set_page_fault_info(far, frame->pc,
+                                               isWrite ? 
DEBUG_PAGE_FAULT_WRITE : 0);
+                               frame->pc = thread->fault_handler;
+                               return;
+                       }
+               }
+
+               // otherwise, not really
+               panic("page fault in debugger without fault handler! Touching "
+                       "address %p from pc %p\n", (void *)far, (void 
*)frame->pc);
+               return;
+       } else if ((frame->spsr & (1 << 7)) != 0) {
+               // interrupts disabled
+
+               // If a page fault handler is installed, we're allowed to be 
here.
+               // TODO: Now we are generally allowing user_memcpy() with 
interrupts
+               // disabled, which in most cases is a bug. We should add some 
thread
+               // flag allowing to explicitly indicate that this handling is 
desired.
+               if (thread && thread->fault_handler != 0) {
+                       if (frame->pc != thread->fault_handler) {
+                               frame->pc = thread->fault_handler;
+                               return;
+                       }
+
+                       // The fault happened at the fault handler address. 
This is a
+                       // certain infinite loop.
+                       panic("page fault, interrupts disabled, fault handler 
loop. "
+                               "Touching address %p from pc %p\n", (void*)far,
+                               (void*)frame->pc);
+               }
+
+               // If we are not running the kernel startup the page fault was 
not
+               // allowed to happen and we must panic.
+               panic("page fault, but interrupts were disabled. Touching 
address "
+                       "%p from pc %p\n", (void *)far, (void *)frame->pc);
+               return;
+       } else if (thread != NULL && thread->page_faults_allowed < 1) {
+               panic("page fault not allowed at this place. Touching address "
+                       "%p from pc %p\n", (void *)far, (void *)frame->pc);
+               return;
+       }
+
+       enable_interrupts();
+
+       vm_page_fault(far, frame->pc, isWrite, isUser, &newip);
+
+       if (newip != 0) {
+               // the page fault handler wants us to modify the iframe to set 
the
+               // IP the cpu will return to to be this ip
+               frame->pc = newip;
        }
 }
 
 extern "C" void arch_arm_prefetch_abort(struct iframe *iframe)
 {
-       panic("Prefetch Abort: %08x %08x %08x", iframe->r0, iframe->r1, 
iframe->r2);
+       print_iframe("Prefetch Abort", iframe);
+       panic("not handled!");
 }
 
 extern "C" void arch_arm_irq(struct iframe *iframe)
diff --git a/src/system/kernel/arch/arm/arch_platform.cpp 
b/src/system/kernel/arch/arm/arch_platform.cpp
index f3721a6..a018654 100644
--- a/src/system/kernel/arch/arm/arch_platform.cpp
+++ b/src/system/kernel/arch/arm/arch_platform.cpp
@@ -6,52 +6,17 @@
  * All rights reserved. Distributed under the terms of the MIT License.
  */
 
-//#include <arch_platform.h>
-
-#include <new>
-
 #include <KernelExport.h>
 #include <arch/platform.h>
 #include <boot/kernel_args.h>
-//#include <platform/openfirmware/openfirmware.h>
 #include <real_time_clock.h>
 #include <util/kernel_cpp.h>
-
-
-#if 0
-static M68KPlatform *sM68KPlatform;
-
-
-// constructor
-M68KPlatform::M68KPlatform(platform_type platformType,
-       m68k_platform_type m68kPlatformType)
-       : fPlatformType(platformType),
-       fM68KPlatformType(m68kPlatformType)
-{
-}
-
-
-// destructor
-M68KPlatform::~M68KPlatform()
-{
-}
-
-
-// Default
-M68KPlatform *
-M68KPlatform::Default()
-{
-       return sM68KPlatform;
-}
-
-
-// # pragma mark -
-#endif
+#include <kernel/debug.h>
 
 status_t
 arch_platform_init(struct kernel_args *kernelArgs)
 {
-       #warning ARM:WRITEME
+       // NOTE: dprintf() is off-limits here, too early...
        return B_OK;
 }
 
@@ -59,8 +24,7 @@ arch_platform_init(struct kernel_args *kernelArgs)
 status_t
 arch_platform_init_post_vm(struct kernel_args *kernelArgs)
 {
-       #warning ARM:WRITEME
-       //sM68KPlatform->InitPostVM(kernelArgs);
+       // now we can use the heap and create areas
        return B_OK;
 }
 
@@ -68,5 +32,6 @@ arch_platform_init_post_vm(struct kernel_args *kernelArgs)
 status_t
 arch_platform_init_post_thread(struct kernel_args *kernelArgs)
 {
+       // now we can create and use semaphores
        return B_OK;
 }
diff --git a/src/system/kernel/arch/arm/arch_timer.cpp 
b/src/system/kernel/arch/arm/arch_timer.cpp
index 2bda040..5cf8574 100644
--- a/src/system/kernel/arch/arm/arch_timer.cpp
+++ b/src/system/kernel/arch/arm/arch_timer.cpp
@@ -19,6 +19,15 @@
 #include <arch/timer.h>
 #include <arch/cpu.h>
 
+
+//#define TRACE_ARCH_TIMER
+#ifdef TRACE_ARCH_TIMER
+#      define TRACE(x) dprintf x
+#else
+#      define TRACE(x) ;
+#endif
+
+
 #define PXA_TIMERS_PHYS_BASE   0x40A00000
 #define PXA_TIMERS_SIZE                0x000000C0
 #define PXA_TIMERS_INTERRUPT   7 /* OST_4_11 */
@@ -29,7 +38,6 @@
 #define PXA_OSMR4              0x20
 #define PXA_OMCR4              0x30
 
-#define TRACE(x)       //dprintf x
 
 static area_id sPxaTimersArea;
 static uint32 *sPxaTimersBase;
@@ -48,7 +56,7 @@ pxa_timer_interrupt(void *data)
 void
 arch_timer_set_hardware_timer(bigtime_t timeout)
 {
-       TRACE(("arch_timer_set_hardware_timer(%lld): %p\n", timeout, 
sPxaTimersBase));
+       TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout));
 
        if (sPxaTimersBase) {
                sPxaTimersBase[PXA_OIER] |= (1 << 4);
@@ -62,7 +70,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
 void
 arch_timer_clear_hardware_timer()
 {
-       TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase));
+       TRACE(("arch_timer_clear_hardware_timer\n"));
 
        if (sPxaTimersBase) {
                sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp 
b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
index cfcd630..91bfa29 100644
--- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
+++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp
@@ -30,7 +30,7 @@
 #include "paging/arm_physical_page_mapper_large_memory.h"
 
 
-#define TRACE_ARM_PAGING_METHOD_32_BIT
+//#define TRACE_ARM_PAGING_METHOD_32_BIT
 #ifdef TRACE_ARM_PAGING_METHOD_32_BIT
 #      define TRACE(x...) dprintf(x)
 #else
diff --git 
a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp 
b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp
index 2d19cb8..ba70d0f 100644
--- a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp
+++ b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp
@@ -249,14 +249,12 @@ ARMVMTranslationMap32Bit::Unmap(addr_t start, addr_t end)
                                        ARM_PTE_TYPE_MASK);
                        fMapCount--;
 
-#if 0 /* IRA */
-                       if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
+                       if (true /* (oldEntry & ARM_PTE_ACCESSED) != 0*/) {
                                // Note, that we only need to invalidate the 
address, if the
                                // accessed flags was set, since only then the 
entry could have
                                // been in any TLB.
                                InvalidatePage(start);
                        }
-#endif
                }
        } while (start != 0 && start < end);
 
@@ -301,8 +299,8 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t 
address,
 
        fMapCount--;
 
-#if 0 //IRA
-       if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
+
+       if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA
                // Note, that we only need to invalidate the address, if the
                // accessed flags was set, since only then the entry could have 
been
                // in any TLB.
@@ -320,14 +318,14 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t 
address,
                // Interestingly FreeBSD seems to ignore this problem as well
                // (cf. pmap_remove_all()), unless I've missed something.
        }
-#endif
+
        locker.Detach();
                // PageUnmapped() will unlock for us
-#if 0 //IRA
+
        PageUnmapped(area, (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE,
-               (oldEntry & ARM_PTE_ACCESSED) != 0, (oldEntry & ARM_PTE_DIRTY) 
!= 0,
+               true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/, true /*(oldEntry & 
ARM_PTE_DIRTY) != 0*/,
                updatePageQueue);
-#endif
+
        return B_OK;
 }
 
@@ -375,14 +373,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t 
base, size_t size,
 
                        fMapCount--;
 
-#if 0 //IRA
-                       if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
+                       if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // 
XXX IRA
                                // Note, that we only need to invalidate the 
address, if the
                                // accessed flags was set, since only then the 
entry could have
                                // been in any TLB.
                                InvalidatePage(start);
                        }
-#endif
+
                        if (area->cache_type != CACHE_TYPE_DEVICE) {
                                // get the page
                                vm_page* page = vm_lookup_page(
@@ -390,13 +387,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t 
base, size_t size,
                                ASSERT(page != NULL);
 
                                DEBUG_PAGE_ACCESS_START(page);
-#if 0
+
                                // transfer the accessed/dirty flags to the page
-                               if ((oldEntry & ARM_PTE_ACCESSED) != 0)
+                               if (/*(oldEntry & ARM_PTE_ACCESSED) != 0*/ 
true) // XXX IRA
                                        page->accessed = true;
-                               if ((oldEntry & ARM_PTE_DIRTY) != 0)
+                               if (/*(oldEntry & ARM_PTE_DIRTY) != 0 */ true)
                                        page->modified = true;
-#endif
+
                                // remove the mapping object/decrement the 
wired_count of the
                                // page
                                if (area->wiring == B_NO_LOCK) {
@@ -512,19 +509,19 @@ ARMVMTranslationMap32Bit::UnmapArea(VMArea* area, bool 
deletingAddressSpace,
                                        "has no page table entry", page, area, 
address);
                                continue;
                        }
-#if 0
+
                        // transfer the accessed/dirty flags to the page and 
invalidate
                        // the mapping, if necessary
-                       if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
+                       if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // 
XXX IRA
                                page->accessed = true;
 
                                if (!deletingAddressSpace)
                                        InvalidatePage(address);
                        }
 
-                       if ((oldEntry & ARM_PTE_DIRTY) != 0)
+                       if (true /*(oldEntry & ARM_PTE_DIRTY) != 0*/)
                                page->modified = true;
-#endif
+
                        if (pageFullyUnmapped) {
                                DEBUG_PAGE_ACCESS_START(page);
 
@@ -640,7 +637,7 @@ ARMVMTranslationMap32Bit::QueryInterrupt(addr_t va, 
phys_addr_t *_physical,
                | ((entry & ARM_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0)
                | ((entry & ARM_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0);
 #else
-       *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA;
+       *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA | PAGE_PRESENT;
 #endif
        return B_OK;
 }
@@ -752,7 +749,7 @@ ARMVMTranslationMap32Bit::ClearFlags(addr_t va, uint32 
flags)
 
        pinner.Unlock();
 
-       if ((oldEntry & flagsToClear) != 0)
+       //XXX IRA if ((oldEntry & flagsToClear) != 0)
                InvalidatePage(va);
 
        return B_OK;
@@ -820,10 +817,9 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* 
area, addr_t address,
 
        pinner.Unlock();
 
-#if 0 //IRA
-       _modified = (oldEntry & ARM_PTE_DIRTY) != 0;
+       _modified = true /* (oldEntry & ARM_PTE_DIRTY) != 0 */; // XXX IRA
 
-       if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
+       if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) {
                // Note, that we only need to invalidate the address, if the
                // accessed flags was set, since only then the entry could have 
been
                // in any TLB.
@@ -833,9 +829,6 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* 
area, addr_t address,
 
                return true;
        }
-#else
-       _modified = false;
-#endif
 
        if (!unmapIfUnaccessed)
                return false;


Other related posts:

  • » [haiku-commits] haiku: hrev44796 - in src/system/kernel/arch/arm: . paging/32bit - ithamar . adema