Index: kernel/arch/arm32/src/ras.c
===================================================================
--- kernel/arch/arm32/src/ras.c	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/arch/arm32/src/ras.c	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -38,5 +38,4 @@
 #include <mm/frame.h>
 #include <mm/page.h>
-#include <mm/km.h>
 #include <mm/tlb.h>
 #include <mm/asid.h>
@@ -51,16 +50,18 @@
 void ras_init(void)
 {
-	uintptr_t frame;
-
-	frame = (uintptr_t) frame_alloc(ONE_FRAME,
-	    FRAME_ATOMIC | FRAME_HIGHMEM);
-	if (!frame)
-		frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_LOWMEM);
-	ras_page = (uintptr_t *) km_map(frame,
-	    PAGE_SIZE, PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_CACHEABLE);
-
-	memsetb(ras_page, PAGE_SIZE, 0); 
+	ras_page = frame_alloc(ONE_FRAME, FRAME_KA);
+	memsetb(ras_page, FRAME_SIZE, 0); 
 	ras_page[RAS_START] = 0;
 	ras_page[RAS_END] = 0xffffffff;
+	/*
+	 * Userspace needs to be able to write to this page. The page is 
+	 * cached in TLB as PAGE_KERNEL. Purge it from TLB and map it
+	 * read/write PAGE_USER.
+	 */
+	tlb_invalidate_pages(ASID_KERNEL, (uintptr_t)ras_page, 1);
+	page_table_lock(AS, true);
+	page_mapping_insert(AS, (uintptr_t)ras_page, (uintptr_t)KA2PA(ras_page),
+	    PAGE_READ | PAGE_WRITE | PAGE_USER);
+	page_table_unlock(AS, true);
 }
 
Index: kernel/genarch/src/acpi/acpi.c
===================================================================
--- kernel/genarch/src/acpi/acpi.c	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/genarch/src/acpi/acpi.c	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -39,6 +39,6 @@
 #include <genarch/acpi/madt.h>
 #include <arch/bios/bios.h>
+#include <mm/as.h>
 #include <mm/page.h>
-#include <mm/km.h>
 #include <print.h>
 
@@ -96,20 +96,11 @@
 }
 
-static struct acpi_sdt_header *map_sdt(struct acpi_sdt_header *psdt)
-{
-	struct acpi_sdt_header *vhdr;
-	struct acpi_sdt_header *vsdt;
-
-	/* Start with mapping the header only. */
-	vhdr = (struct acpi_sdt_header *) km_map_structure((uintptr_t) psdt,
-	    sizeof(struct acpi_sdt_header), PAGE_READ | PAGE_NOT_CACHEABLE); 
-
-	/* Now we can map the entire structure. */
-	vsdt = (struct acpi_sdt_header *) km_map_structure((uintptr_t) psdt,
-	    vhdr->length, PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	
-	// TODO: do not leak vtmp
-
-	return vsdt; 
+static void map_sdt(struct acpi_sdt_header *sdt)
+{
+	page_table_lock(AS_KERNEL, true);
+	page_mapping_insert(AS_KERNEL, (uintptr_t) sdt, (uintptr_t) sdt,
+	    PAGE_NOT_CACHEABLE | PAGE_WRITE);
+	map_structure((uintptr_t) sdt, sdt->length);
+	page_table_unlock(AS_KERNEL, true);
 }
 
@@ -127,10 +118,10 @@
 			    (struct acpi_sdt_header *) (sysarg_t) acpi_rsdt->entry[i];
 			
-			struct acpi_sdt_header *vhdr = map_sdt(hdr);
-			if (CMP_SIGNATURE(vhdr->signature, signature_map[j].signature)) {
-				if (!acpi_sdt_check((uint8_t *) vhdr))
+			map_sdt(hdr);
+			if (CMP_SIGNATURE(hdr->signature, signature_map[j].signature)) {
+				if (!acpi_sdt_check((uint8_t *) hdr))
 					break;
 				
-				*signature_map[j].sdt_ptr = vhdr;
+				*signature_map[j].sdt_ptr = hdr;
 				LOG("%p: ACPI %s", *signature_map[j].sdt_ptr,
 				    signature_map[j].description);
@@ -153,10 +144,10 @@
 			    (struct acpi_sdt_header *) ((uintptr_t) acpi_xsdt->entry[i]);
 			
-			struct acpi_sdt_header *vhdr = map_sdt(hdr);
-			if (CMP_SIGNATURE(vhdr->signature, signature_map[j].signature)) {
-				if (!acpi_sdt_check((uint8_t *) vhdr))
+			map_sdt(hdr);
+			if (CMP_SIGNATURE(hdr->signature, signature_map[j].signature)) {
+				if (!acpi_sdt_check((uint8_t *) hdr))
 					break;
 				
-				*signature_map[j].sdt_ptr = vhdr;
+				*signature_map[j].sdt_ptr = hdr;
 				LOG("%p: ACPI %s", *signature_map[j].sdt_ptr,
 				    signature_map[j].description);
@@ -196,17 +187,13 @@
 	LOG("%p: ACPI Root System Description Pointer", acpi_rsdp);
 	
-	uintptr_t acpi_rsdt_p = (uintptr_t) acpi_rsdp->rsdt_address;
-	uintptr_t acpi_xsdt_p = 0;
-
+	acpi_rsdt = (struct acpi_rsdt *) ((uintptr_t) acpi_rsdp->rsdt_address);
 	if (acpi_rsdp->revision)
-		acpi_xsdt_p = (uintptr_t) acpi_rsdp->xsdt_address;
-	
-	if (acpi_rsdt_p)
-		acpi_rsdt = (struct acpi_rsdt *) map_sdt(
-		    (struct acpi_sdt_header *) acpi_rsdt_p);
-	
-	if (acpi_xsdt_p)
-		acpi_xsdt = (struct acpi_xsdt *) map_sdt(
-		    (struct acpi_sdt_header *) acpi_xsdt_p);
+		acpi_xsdt = (struct acpi_xsdt *) ((uintptr_t) acpi_rsdp->xsdt_address);
+	
+	if (acpi_rsdt)
+		map_sdt((struct acpi_sdt_header *) acpi_rsdt);
+	
+	if (acpi_xsdt)
+		map_sdt((struct acpi_sdt_header *) acpi_xsdt);
 	
 	if ((acpi_rsdt) && (!acpi_sdt_check((uint8_t *) acpi_rsdt))) {
Index: kernel/generic/include/mm/km.h
===================================================================
--- kernel/generic/include/mm/km.h	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/generic/include/mm/km.h	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -50,5 +50,4 @@
 
 extern uintptr_t km_map(uintptr_t, size_t, unsigned int);
-extern uintptr_t km_map_structure(uintptr_t, size_t, unsigned int);
 
 extern uintptr_t km_temporary_page_get(uintptr_t *, frame_flags_t);
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/generic/include/mm/page.h	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -64,4 +64,5 @@
 extern pte_t *page_table_create(unsigned int);
 extern void page_table_destroy(pte_t *);
+extern void map_structure(uintptr_t, size_t);
 
 extern int page_find_mapping(uintptr_t, void **);
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/generic/src/mm/km.c	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -145,12 +145,4 @@
 }
 
-uintptr_t km_map_structure(uintptr_t paddr, size_t size, unsigned int flags)
-{
-	size_t offs = paddr - ALIGN_DOWN(paddr, FRAME_SIZE); 
-	uintptr_t page;
-
-	page = km_map(ALIGN_DOWN(paddr, FRAME_SIZE), size + offs, flags);
-	return page + offs;
-}
 
 /** Unmap kernen non-identity page.
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/generic/src/mm/page.c	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -84,4 +84,28 @@
 }
 
+/** Map memory structure
+ *
+ * Identity-map memory structure
+ * considering possible crossings
+ * of page boundaries.
+ *
+ * @param addr Address of the structure.
+ * @param size Size of the structure.
+ *
+ */
+void map_structure(uintptr_t addr, size_t size)
+{
+	size_t length = size + (addr - (addr & ~(PAGE_SIZE - 1)));
+	size_t cnt = length / PAGE_SIZE + (length % PAGE_SIZE > 0);
+	
+	size_t i;
+	for (i = 0; i < cnt; i++)
+		page_mapping_insert(AS_KERNEL, addr + i * PAGE_SIZE,
+		    addr + i * PAGE_SIZE, PAGE_NOT_CACHEABLE | PAGE_WRITE);
+	
+	/* Repel prefetched accesses to the old mapping. */
+	memory_barrier();
+}
+
 /** Insert mapping of page to frame.
  *
Index: kernel/test/mm/mapping1.c
===================================================================
--- kernel/test/mm/mapping1.c	(revision 7b3b57171e1a38631bd24e5ecdf71edd3f1926f4)
+++ kernel/test/mm/mapping1.c	(revision 9970a5a5a1c127d9512cdf9695ac5f4384f1fde4)
@@ -31,55 +31,76 @@
 #include <mm/page.h>
 #include <mm/frame.h>
+#include <mm/as.h>
 #include <arch/mm/page.h>
-#include <mm/km.h>
 #include <typedefs.h>
 #include <debug.h>
 #include <arch.h>
 
-#define TEST_MAGIC  UINT32_C(0x01234567)
+#define PAGE0  0x10000000
+#define PAGE1  (PAGE0 + PAGE_SIZE)
+
+#define VALUE0  UINT32_C(0x01234567)
+#define VALUE1  UINT32_C(0x89abcdef)
 
 const char *test_mapping1(void)
 {
-	uintptr_t page0, page1;
-	uintptr_t frame;
-	uint32_t v;
-	int i;
+	uintptr_t frame0, frame1;
+	uint32_t v0, v1;
 	
-	frame = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_NONE);
+	frame0 = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_KA);
+	frame1 = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_KA);
+	
+	TPRINTF("Writing %#" PRIx32 " to physical address %p.\n",
+	    (uint32_t) VALUE0, (void *) KA2PA(frame0));
+	*((uint32_t *) frame0) = VALUE0;
+	
+	TPRINTF("Writing %#" PRIx32 " to physical address %p.\n",
+	    (uint32_t) VALUE1, (void *) KA2PA(frame1));
+	*((uint32_t *) frame1) = VALUE1;
+	
+	page_table_lock(AS, true);
 
-	page0 = km_map(frame, FRAME_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
-	TPRINTF("Virtual address %p mapped to physical address %p.\n",
-	    (void *) page0, (void *) frame);
-	page1 = km_map(frame, FRAME_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
-	TPRINTF("Virtual address %p mapped to physical address %p.\n",
-	    (void *) page1, (void *) frame);
+	TPRINTF("Mapping virtual address %p to physical address %p.\n",
+	    (void *) PAGE0, (void *) KA2PA(frame0));
+	page_mapping_insert(AS_KERNEL, PAGE0, KA2PA(frame0), PAGE_PRESENT | PAGE_WRITE);
 	
-	for (i = 0; i < 2; i++) {
-		TPRINTF("Writing magic using the first virtual address.\n");
+	TPRINTF("Mapping virtual address %p to physical address %p.\n",
+	    (void *) PAGE1, (void *) KA2PA(frame1));
+	page_mapping_insert(AS_KERNEL, PAGE1, KA2PA(frame1), PAGE_PRESENT | PAGE_WRITE);
 
-		*((uint32_t *) page0) = TEST_MAGIC;
-
-		TPRINTF("Reading magic using the second virtual address.\n");
-
-		v = *((uint32_t *) page1);
+	page_table_unlock(AS, true);
 	
-		if (v != TEST_MAGIC)
-			return "Criss-cross read does not match the value written.";
-
-		TPRINTF("Writing zero using the second virtual address.\n");
+	v0 = *((uint32_t *) PAGE0);
+	v1 = *((uint32_t *) PAGE1);
+	TPRINTF("Value at virtual address %p is %#" PRIx32 ".\n",
+	    (void *) PAGE0, v0);
+	TPRINTF("Value at virtual address %p is %#" PRIx32 ".\n",
+	    (void *) PAGE1, v1);
 	
-		*((uint32_t *) page1) = 0;
-
-		TPRINTF("Reading zero using the first virtual address.\n");
+	if (v0 != VALUE0)
+		return "Value at v0 not equal to VALUE0";
+	if (v1 != VALUE1)
+		return "Value at v1 not equal to VALUE1";
 	
-		v = *((uint32_t *) page0);
+	TPRINTF("Writing %#" PRIx32 " to virtual address %p.\n",
+	    (uint32_t) 0, (void *) PAGE0);
+	*((uint32_t *) PAGE0) = 0;
 	
-		if (v != 0)
-			return "Criss-cross read does not match the value written.";
-	}
-
-	// FIXME: do not leak frame, page0 and page1
+	TPRINTF("Writing %#" PRIx32 " to virtual address %p.\n",
+	    (uint32_t) 0, (void *) PAGE1);
+	*((uint32_t *) PAGE1) = 0;
+	
+	v0 = *((uint32_t *) PAGE0);
+	v1 = *((uint32_t *) PAGE1);
+	
+	TPRINTF("Value at virtual address %p is %#" PRIx32 ".\n",
+	    (void *) PAGE0, *((uint32_t *) PAGE0));
+	TPRINTF("Value at virtual address %p is %#" PRIx32 ".\n",
+	    (void *) PAGE1, *((uint32_t *) PAGE1));
+	
+	if (v0 != 0)
+		return "Value at v0 not equal to 0";
+	if (v1 != 0)
+		return "Value at v1 not equal to 0";
 	
 	return NULL;
