Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/arch/arm32/Makefile.inc	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -33,5 +33,5 @@
 ATSIGN = %
 
-GCC_CFLAGS += -march=armv4
+GCC_CFLAGS += -march=armv4 -fno-omit-frame-pointer -mapcs-frame
 
 BITS = 32
Index: kernel/arch/arm32/include/istate.h
===================================================================
--- kernel/arch/arm32/include/istate.h	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/arch/arm32/include/istate.h	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -49,4 +49,5 @@
 /** Struct representing CPU state saved when an exception occurs. */
 typedef struct istate {
+	uint32_t dummy;
 	uint32_t spsr;
 	uint32_t sp;
Index: kernel/arch/arm32/src/exc_handler.S
===================================================================
--- kernel/arch/arm32/src/exc_handler.S	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/arch/arm32/src/exc_handler.S	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -130,7 +130,9 @@
 	stmfd r13!, {r2}
 2:
+	sub sp, sp, #4
 .endm
 
 .macro LOAD_REGS_FROM_STACK
+	add sp, sp, #4
 	ldmfd r13!, {r0}
 	msr spsr, r0
Index: kernel/arch/arm32/src/exception.c
===================================================================
--- kernel/arch/arm32/src/exception.c	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/arch/arm32/src/exception.c	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -123,5 +123,5 @@
 	
 	asm volatile (
-		"mrc p15, 0, %[control_reg], c1, c1"
+		"mrc p15, 0, %[control_reg], c1, c0"
 		: [control_reg] "=r" (control_reg)
 	);
@@ -131,5 +131,5 @@
 	
 	asm volatile (
-		"mcr p15, 0, %[control_reg], c1, c1"
+		"mcr p15, 0, %[control_reg], c1, c0"
 		:: [control_reg] "r" (control_reg)
 	);
Index: kernel/arch/arm32/src/mm/page_fault.c
===================================================================
--- kernel/arch/arm32/src/mm/page_fault.c	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/arch/arm32/src/mm/page_fault.c	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -77,49 +77,4 @@
 }
 
-/** Decides whether the instruction is load/store or not.
- *
- * @param instr Instruction
- *
- * @return true when instruction is load/store, false otherwise
- *
- */
-static inline bool is_load_store_instruction(instruction_t instr)
-{
-	/* load store immediate offset */
-	if (instr.type == 0x2)
-		return true;
-	
-	/* load store register offset */
-	if ((instr.type == 0x3) && (instr.bit4 == 0))
-		return true;
-	
-	/* load store multiple */
-	if (instr.type == 0x4)
-		return true;
-	
-	/* oprocessor load/store */
-	if (instr.type == 0x6)
-		return true;
-	
-	return false;
-}
-
-/** Decides whether the instruction is swap or not.
- *
- * @param instr Instruction
- *
- * @return true when instruction is swap, false otherwise
- */
-static inline bool is_swap_instruction(instruction_t instr)
-{
-	/* swap, swapb instruction */
-	if ((instr.type == 0x0) &&
-	    ((instr.opcode == 0x8) || (instr.opcode == 0xa)) &&
-	    (instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1))
-		return true;
-	
-	return false;
-}
-
 /** Decides whether read or write into memory is requested.
  *
@@ -128,5 +83,5 @@
  *
  * @return Type of access into memory, PF_ACCESS_EXEC if no memory access is
- * 	   requested.
+ *	   requested.
  */
 static pf_access_t get_memory_access_type(uint32_t instr_addr,
@@ -146,23 +101,38 @@
 	}
 
-	/* load store instructions */
-	if (is_load_store_instruction(instr)) {
-		if (instr.access == 1) {
-			return PF_ACCESS_READ;
-		} else {
-			return PF_ACCESS_WRITE;
+	/* See ARM Architecture reference manual ARMv7-A and ARMV7-R edition
+	 * A5.3 (PDF p. 206) */
+	static const struct {
+		uint32_t mask;
+		uint32_t value;
+		pf_access_t access;
+	} ls_inst[] = {
+		/* Store word/byte */
+		{ 0x0e100000, 0x04000000, PF_ACCESS_WRITE }, /*STR(B) imm*/
+		{ 0x0e100010, 0x06000000, PF_ACCESS_WRITE }, /*STR(B) reg*/
+		/* Load word/byte */
+		{ 0x0e100000, 0x04100000, PF_ACCESS_READ }, /*LDR(B) imm*/
+		{ 0x0e100010, 0x06100000, PF_ACCESS_READ }, /*LDR(B) reg*/
+		/* Store half-word/dual  A5.2.8 */
+		{ 0x0e1000b0, 0x000000b0, PF_ACCESS_WRITE }, /*STRH imm reg*/
+		/* Load half-word/dual A5.2.8 */
+		{ 0x0e0000f0, 0x000000d0, PF_ACCESS_READ }, /*LDRH imm reg*/
+		{ 0x0e1000b0, 0x001000b0, PF_ACCESS_READ }, /*LDRH imm reg*/
+		/* Block data transfer, Store */
+		{ 0x0e100000, 0x08000000, PF_ACCESS_WRITE }, /* STM variants */
+		{ 0x0e100000, 0x08100000, PF_ACCESS_READ },  /* LDM variants */
+		/* Swap */
+		{ 0x0fb00000, 0x01000000, PF_ACCESS_WRITE },
+	};
+	const uint32_t inst = *(uint32_t*)instr_addr;
+	for (unsigned i = 0; i < sizeof(ls_inst) / sizeof(ls_inst[0]); ++i) {
+		if ((inst & ls_inst[i].mask) == ls_inst[i].value) {
+			return ls_inst[i].access;
 		}
-	}
-
-	/* swap, swpb instruction */
-	if (is_swap_instruction(instr)) {
-		return PF_ACCESS_WRITE;
 	}
 
 	panic("page_fault - instruction doesn't access memory "
 	    "(instr_code: %#0" PRIx32 ", badvaddr:%p).",
-	    instr_union.pc, (void *) badvaddr);
-
-	return PF_ACCESS_EXEC;
+	    inst, (void *) badvaddr);
 }
 
Index: kernel/genarch/include/drivers/arm926_uart/arm926_uart.h
===================================================================
--- kernel/genarch/include/drivers/arm926_uart/arm926_uart.h	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/genarch/include/drivers/arm926_uart/arm926_uart.h	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -35,6 +35,6 @@
  */
 
-#ifndef KERN_S3C24XX_UART_H_
-#define KERN_S3C24XX_UART_H_
+#ifndef KERN_ARM926_UART_H_
+#define KERN_ARM926_UART_H_
 
 #include <ddi/irq.h>
Index: kernel/genarch/include/multiboot/multiboot.h
===================================================================
--- kernel/genarch/include/multiboot/multiboot.h	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/genarch/include/multiboot/multiboot.h	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -99,4 +99,5 @@
 
 extern void multiboot_extract_command(char *, size_t, const char *);
+extern void multiboot_extract_argument(char *, size_t, const char *);
 extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
 
Index: kernel/genarch/src/multiboot/multiboot.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot.c	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -71,4 +71,33 @@
 }
 
+/** Extract arguments from the multiboot module command line.
+ *
+ * @param buf      Destination buffer (will be always NULL-terminated).
+ * @param size     Size of destination buffer (in bytes).
+ * @param cmd_line Input string (the command line).
+ *
+ */
+void multiboot_extract_argument(char *buf, size_t size, const char *cmd_line)
+{
+	/* Start after first space. */
+	const char *start = str_chr(cmd_line, ' ');
+	if (start == NULL) {
+		str_cpy(buf, size, "");
+		return;
+	}
+
+	const char *end = cmd_line + str_size(cmd_line);
+
+	/* Skip the space(s). */
+	while (start != end) {
+		if (start[0] == ' ')
+			start++;
+		else
+			break;
+	}
+
+	str_ncpy(buf, size, start, (size_t) (end - start));
+}
+
 static void multiboot_modules(uint32_t count, multiboot_module_t *mods)
 {
@@ -84,6 +113,10 @@
 			multiboot_extract_command(init.tasks[init.cnt].name,
 			    CONFIG_TASK_NAME_BUFLEN, MULTIBOOT_PTR(mods[i].string));
-		} else
+			multiboot_extract_argument(init.tasks[init.cnt].arguments,
+			    CONFIG_TASK_ARGUMENTS_BUFLEN, MULTIBOOT_PTR(mods[i].string));
+		} else {
 			init.tasks[init.cnt].name[0] = 0;
+			init.tasks[init.cnt].arguments[0] = 0;
+		}
 		
 		init.cnt++;
Index: kernel/genarch/src/multiboot/multiboot2.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot2.c	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/genarch/src/multiboot/multiboot2.c	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -49,4 +49,6 @@
 		multiboot_extract_command(init.tasks[init.cnt].name,
 		    CONFIG_TASK_NAME_BUFLEN, module->string);
+		multiboot_extract_argument(init.tasks[init.cnt].arguments,
+		    CONFIG_TASK_ARGUMENTS_BUFLEN, module->string);
 		
 		init.cnt++;
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/generic/include/config.h	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -47,4 +47,5 @@
 #define CONFIG_INIT_TASKS        32
 #define CONFIG_TASK_NAME_BUFLEN  32
+#define CONFIG_TASK_ARGUMENTS_BUFLEN 64
 
 /**
@@ -62,4 +63,5 @@
 	size_t size;
 	char name[CONFIG_TASK_NAME_BUFLEN];
+	char arguments[CONFIG_TASK_ARGUMENTS_BUFLEN];
 } init_task_t;
 
Index: kernel/generic/include/lib/elf_load.h
===================================================================
--- kernel/generic/include/lib/elf_load.h	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/generic/include/lib/elf_load.h	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -42,16 +42,15 @@
  * ELF error return codes
  */
-#define EE_OK			0	/* No error */
-#define EE_INVALID		1	/* Invalid ELF image */
-#define	EE_MEMORY		2	/* Cannot allocate address space */
-#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_LOADER		5	/* The image is actually a program loader. */
-#define EE_IRRECOVERABLE	6
+#define EE_OK             0  /* No error */
+#define EE_INVALID        1  /* Invalid ELF image */
+#define EE_MEMORY         2  /* Cannot allocate address space */
+#define EE_INCOMPATIBLE   3  /* ELF image is not compatible with current architecture */
+#define EE_UNSUPPORTED    4  /* Non-supported ELF (e.g. dynamic ELFs) */
+#define EE_LOADER         5  /* The image is actually a program loader. */
+#define EE_IRRECOVERABLE  6  /* Irrecoverable error. */
 
 /**
  * This flags is passed when running the loader, otherwise elf_load()
  * would return with a EE_LOADER error code.
- *
  */
 #define ELD_F_NONE    0
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision e9fe33ba87039a87dbdc0f1053e6dcc06931593e)
+++ kernel/generic/src/main/kinit.c	(revision 9ab27144f671d13ed76e2e885acabcdcd64ce303)
@@ -69,4 +69,5 @@
 #include <str.h>
 #include <sysinfo/stats.h>
+#include <sysinfo/sysinfo.h>
 #include <align.h>
 
@@ -179,4 +180,26 @@
 	program_t programs[CONFIG_INIT_TASKS];
 	
+	// FIXME: do not propagate arguments through sysinfo
+	// but pass them directly to the tasks
+	for (i = 0; i < init.cnt; i++) {
+		const char *arguments = init.tasks[i].arguments;
+		if (str_length(arguments) == 0)
+			continue;
+		if (str_length(init.tasks[i].name) == 0)
+			continue;
+		size_t arguments_size = str_size(arguments);
+
+		void *arguments_copy = malloc(arguments_size, 0);
+		if (arguments_copy == NULL)
+			continue;
+		memcpy(arguments_copy, arguments, arguments_size);
+
+		char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
+		snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
+		    "init_args.%s", init.tasks[i].name);
+
+		sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
+	}
+
 	for (i = 0; i < init.cnt; i++) {
 		if (init.tasks[i].paddr % FRAME_SIZE) {
