Index: kernel/arch/arm32/src/mm/page_fault.c
===================================================================
--- kernel/arch/arm32/src/mm/page_fault.c	(revision 1dbc43f1c037ded959f69e4b6346df8bf12e2431)
+++ kernel/arch/arm32/src/mm/page_fault.c	(revision 21b703f70e52446c541890949b2732680e7da003)
@@ -42,27 +42,124 @@
 #include <print.h>
 
-/** Returns value stored in fault status register.
+
+/**
+ * FSR encoding ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.
+ *
+ * B3.13.3 page B3-1406 (PDF page 1406)
+ */
+typedef enum {
+	DFSR_SOURCE_ALIGN = 0x0001,
+	DFSR_SOURCE_CACHE_MAINTENANCE = 0x0004,
+	DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1 = 0x000c,
+	DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2 = 0x000e,
+	DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1 = 0x040c,
+	DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2 = 0x040e,
+	DFSR_SOURCE_TRANSLATION_L1 = 0x0005,
+	DFSR_SOURCE_TRANSLATION_L2 = 0x0007,
+	DFSR_SOURCE_ACCESS_FLAG_L1 = 0x0003,  /**< @note: This used to be alignment enc. */
+	DFSR_SOURCE_ACCESS_FLAG_L2 = 0x0006,
+	DFSR_SOURCE_DOMAIN_L1 = 0x0009,
+	DFSR_SOURCE_DOMAIN_L2 = 0x000b,
+	DFSR_SOURCE_PERMISSION_L1 = 0x000d,
+	DFSR_SOURCE_PERMISSION_L2 = 0x000f,
+	DFSR_SOURCE_DEBUG = 0x0002,
+	DFSR_SOURCE_SYNC_EXTERNAL = 0x0008,
+	DFSR_SOURCE_TLB_CONFLICT = 0x0400,
+	DFSR_SOURCE_LOCKDOWN = 0x0404, /**< @note: Implementation defined */
+	DFSR_SOURCE_COPROCESSOR = 0x040a, /**< @note Implementation defined */
+	DFSR_SOURCE_SYNC_PARITY = 0x0409,
+	DFSR_SOURCE_ASYNC_EXTERNAL = 0x0406,
+	DFSR_SOURCE_ASYNC_PARITY = 0x0408,
+	DFSR_SOURCE_MASK = 0x0000040f,
+} dfsr_source_t;
+
+static inline const char * dfsr_source_to_str(dfsr_source_t source)
+{
+	switch (source)	{
+	case DFSR_SOURCE_TRANSLATION_L1:
+		return "Translation fault L1";
+	case DFSR_SOURCE_TRANSLATION_L2:
+		return "Translation fault L2";
+	case DFSR_SOURCE_PERMISSION_L1:
+		return "Permission fault L1";
+	case DFSR_SOURCE_PERMISSION_L2:
+		return "Permission fault L2";
+	case DFSR_SOURCE_ALIGN:
+		return "Alignment fault";
+	case DFSR_SOURCE_CACHE_MAINTENANCE:
+		return "Instruction cache maintenance fault";
+	case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
+		return "Synchronous external abort on translation table walk level 1";
+	case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
+		return "Synchronous external abort on translation table walk level 2";
+	case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
+		return "Synchronous parity error on translation table walk level 1";
+	case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
+		return "Synchronous parity error on translation table walk level 2";
+	case DFSR_SOURCE_ACCESS_FLAG_L1:
+		return "Access flag fault L1";
+	case DFSR_SOURCE_ACCESS_FLAG_L2:
+		return "Access flag fault L2";
+	case DFSR_SOURCE_DOMAIN_L1:
+		return "Domain fault L1";
+	case DFSR_SOURCE_DOMAIN_L2:
+		return "Domain flault L2";
+	case DFSR_SOURCE_DEBUG:
+		return "Debug event";
+	case DFSR_SOURCE_SYNC_EXTERNAL:
+		return "Synchronous external abort";
+	case DFSR_SOURCE_TLB_CONFLICT:
+		return "TLB conflict abort";
+	case DFSR_SOURCE_LOCKDOWN:
+		return "Lockdown (Implementation defined)";
+	case DFSR_SOURCE_COPROCESSOR:
+		return "Coprocessor abort (Implementation defined)";
+	case DFSR_SOURCE_SYNC_PARITY:
+		return "Synchronous parity error on memory access";
+	case DFSR_SOURCE_ASYNC_EXTERNAL:
+		return "Asynchronous external abort";
+	case DFSR_SOURCE_ASYNC_PARITY:
+		return "Asynchronous parity error on memory access";
+	case DFSR_SOURCE_MASK:
+		break;
+	}
+	return "Unknown data abort";
+}
+
+
+/** Returns value stored in comnbined/data fault status register.
  *
  *  @return Value stored in CP15 fault status register (FSR).
- */
-static inline fault_status_t read_fault_status_register(void)
-{
-	fault_status_union_t fsu;
+ *
+ *  "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR.
+ *  It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of
+ *  the architecture. A write flag (bit[11] of the DFSR) has also been
+ *  introduced."
+ *  ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719)
+ *
+ *  See ch. B4.9.6 for location of data/instruction FSR.
+ *
+ */
+static inline fault_status_t read_data_fault_status_register(void)
+{
+	fault_status_t fsu;
 	
-	/* fault status is stored in CP15 register 5 */
+	/* Combined/Data fault status is stored in CP15 register 5, c0. */
 	asm volatile (
 		"mrc p15, 0, %[dummy], c5, c0, 0"
-		: [dummy] "=r" (fsu.dummy)
+		: [dummy] "=r" (fsu.raw)
 	);
 	
-	return fsu.fs;
-}
-
-/** Returns FAR (fault address register) content.
- *
- * @return FAR (fault address register) content (address that caused a page
+	return fsu;
+}
+
+/** Returns DFAR (fault address register) content.
+ *
+ * This register is equivalent to FAR on pre armv6 machines.
+ *
+ * @return DFAR (fault address register) content (address that caused a page
  *         fault)
  */
-static inline uintptr_t read_fault_address_register(void)
+static inline uintptr_t read_data_fault_address_register(void)
 {
 	uintptr_t ret;
@@ -77,4 +174,5 @@
 }
 
+#if defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
 /** Decides whether read or write into memory is requested.
  *
@@ -97,5 +195,5 @@
 		panic("page_fault - instruction does not access memory "
 		    "(instr_code: %#0" PRIx32 ", badvaddr:%p).",
-		    instr_union.pc, (void *) badvaddr);
+		    *(uint32_t*)instr_union.instr, (void *) badvaddr);
 		return PF_ACCESS_EXEC;
 	}
@@ -136,4 +234,5 @@
 	    inst, (void *) badvaddr);
 }
+#endif
 
 /** Handles "data abort" exception (load or store at invalid address).
@@ -145,10 +244,49 @@
 void data_abort(unsigned int exc_no, istate_t *istate)
 {
-	fault_status_t fsr __attribute__ ((unused)) =
-	    read_fault_status_register();
-	uintptr_t badvaddr = read_fault_address_register();
-
-	pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
-
+	const uintptr_t badvaddr = read_data_fault_address_register();
+	const fault_status_t fsr = read_data_fault_status_register();
+	const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK;
+
+	switch (source)	{
+	case DFSR_SOURCE_TRANSLATION_L1:
+	case DFSR_SOURCE_TRANSLATION_L2:
+	case DFSR_SOURCE_PERMISSION_L1:
+	case DFSR_SOURCE_PERMISSION_L2:
+		/* Page fault is handled further down */
+		break;
+	case DFSR_SOURCE_ALIGN:
+	case DFSR_SOURCE_CACHE_MAINTENANCE:
+	case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L1:
+	case DFSR_SOURCE_SYNC_EXTERNAL_TRANSLATION_L2:
+	case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L1:
+	case DFSR_SOURCE_SYNC_PARITY_TRANSLATION_L2:
+	case DFSR_SOURCE_ACCESS_FLAG_L1:
+	case DFSR_SOURCE_ACCESS_FLAG_L2:
+	case DFSR_SOURCE_DOMAIN_L1:
+	case DFSR_SOURCE_DOMAIN_L2:
+	case DFSR_SOURCE_DEBUG:
+	case DFSR_SOURCE_SYNC_EXTERNAL:
+	case DFSR_SOURCE_TLB_CONFLICT:
+	case DFSR_SOURCE_LOCKDOWN:
+	case DFSR_SOURCE_COPROCESSOR:
+	case DFSR_SOURCE_SYNC_PARITY:
+	case DFSR_SOURCE_ASYNC_EXTERNAL:
+	case DFSR_SOURCE_ASYNC_PARITY:
+	case DFSR_SOURCE_MASK:
+		/* Weird abort stuff */
+		fault_if_from_uspace(istate, "Unhandled abort %s at address: "
+		    "%#x.", dfsr_source_to_str(source), badvaddr);
+		panic("Unhandled abort %s at address: %#x.",
+		    dfsr_source_to_str(source), badvaddr);
+	}
+
+#if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a)
+	const pf_access_t access =
+	    fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ;
+#elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
+	const pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
+#else
+#error "Unsupported architecture"
+#endif
 	as_page_fault(badvaddr, access, istate);
 }
