Index: kernel/arch/abs32le/include/arch/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/abs32le/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -92,7 +92,7 @@
 	get_pt_flags((pte_t *) (ptl0), (size_t) (i))
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
 	get_pt_flags((pte_t *) (ptl3), (size_t) (i))
@@ -121,7 +121,10 @@
 #define PTE_GET_FRAME_ARCH(p) \
 	((p)->frame_address << FRAME_WIDTH)
+#define PTE_READABLE_ARCH(p) \
+	1
 #define PTE_WRITABLE_ARCH(p) \
 	((p)->writeable != 0)
-#define PTE_EXECUTABLE_ARCH(p)  1
+#define PTE_EXECUTABLE_ARCH(p) \
+	1
 
 #include <mm/mm.h>
@@ -154,5 +157,5 @@
 	return (
 	    ((unsigned int) (!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT) |
-	    ((unsigned int) (!p->present) << PAGE_PRESENT_SHIFT) |
+	    ((unsigned int) (!p->present) << PAGE_NOT_PRESENT_SHIFT) |
 	    ((unsigned int) p->uaccessible << PAGE_USER_SHIFT) |
 	    (1 << PAGE_READ_SHIFT) |
@@ -172,5 +175,5 @@
 	p->present = !(flags & PAGE_NOT_PRESENT);
 	p->uaccessible = (flags & PAGE_USER) != 0;
-	p->writeable = (flags & PAGE_WRITE) != 0;
+	p->writeable = (flags & _PAGE_WRITE) != 0;
 	p->global = (flags & PAGE_GLOBAL) != 0;
 
Index: kernel/arch/amd64/include/arch/mm/page.h
===================================================================
--- kernel/arch/amd64/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/amd64/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -157,4 +157,6 @@
 	((((uintptr_t) (p)->addr_12_31) << 12) | \
 	    ((uintptr_t) (p)->addr_32_51 << 32))
+#define PTE_READABLE_ARCH(p) \
+	1
 #define PTE_WRITABLE_ARCH(p) \
 	((p)->writeable != 0)
@@ -211,7 +213,7 @@
 	pte_t *p = &pt[i];
 
-	return ((!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT |
-	    (!p->present) << PAGE_PRESENT_SHIFT |
-	    p->uaccessible << PAGE_USER_SHIFT |
+	return ((p->page_cache_disable ? PAGE_NOT_CACHEABLE : PAGE_CACHEABLE) |
+	    (!p->present) << PAGE_NOT_PRESENT_SHIFT |
+	    (!p->uaccessible)  << PAGE_KERNEL_SHIFT |
 	    1 << PAGE_READ_SHIFT |
 	    p->writeable << PAGE_WRITE_SHIFT |
@@ -234,7 +236,7 @@
 	p->page_cache_disable = !(flags & PAGE_CACHEABLE);
 	p->present = !(flags & PAGE_NOT_PRESENT);
-	p->uaccessible = (flags & PAGE_USER) != 0;
-	p->writeable = (flags & PAGE_WRITE) != 0;
-	p->no_execute = (flags & PAGE_EXEC) == 0;
+	p->uaccessible = !(flags & PAGE_KERNEL);
+	p->writeable = (flags & _PAGE_WRITE) != 0;
+	p->no_execute = (flags & _PAGE_EXEC) == 0;
 	p->global = (flags & PAGE_GLOBAL) != 0;
 
Index: kernel/arch/amd64/src/mm/page.c
===================================================================
--- kernel/arch/amd64/src/mm/page.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/amd64/src/mm/page.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -55,6 +55,6 @@
 
 	uintptr_t cur;
-	unsigned int identity_flags =
-	    PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_EXEC | PAGE_WRITE | PAGE_READ;
+	unsigned int identity_flags = PAGE_READ_WRITE_EXECUTE |
+	    PAGE_CACHEABLE | PAGE_KERNEL | PAGE_GLOBAL;
 
 	page_mapping_operations = &pt_mapping_operations;
Index: kernel/arch/amd64/src/vreg.c
===================================================================
--- kernel/arch/amd64/src/vreg.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/amd64/src/vreg.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -67,5 +67,5 @@
 
 	page = (uint64_t *) km_map(frame, PAGE_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_USER | PAGE_CACHEABLE);
 
 	write_msr(AMD_MSR_FS, (uintptr_t) page);
Index: kernel/arch/arm32/include/arch/mm/page.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -108,7 +108,7 @@
         get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-        PAGE_PRESENT
+        PAGE_NEXT_LEVEL_PT
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-        PAGE_PRESENT
+        PAGE_NEXT_LEVEL_PT
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
         get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
Index: kernel/arch/arm32/include/arch/mm/page_armv4.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page_armv4.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/include/arch/mm/page_armv4.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -49,4 +49,6 @@
 #define PTE_GET_FRAME_ARCH(pte) \
 	(((uintptr_t) ((pte_t *) (pte))->l1.frame_base_addr) << FRAME_WIDTH)
+#define PTE_READABLE_ARCH(pte) \
+	1
 #define PTE_WRITABLE_ARCH(pte) \
 	(((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW)
@@ -138,7 +140,5 @@
 	int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
 
-	return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) |
-	    (1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) |
-	    (1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT);
+	return (np << PAGE_NOT_PRESENT_SHIFT) | PAGE_NEXT_LEVEL_PT;
 }
 
@@ -156,5 +156,5 @@
 	int ap = p->access_permission_0;
 
-	return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) |
+	return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_NOT_PRESENT_SHIFT) |
 	    ((ap == PTE_AP_USER_RO_KERNEL_RW) << PAGE_READ_SHIFT) |
 	    ((ap == PTE_AP_USER_RW_KERNEL_RW) << PAGE_READ_SHIFT) |
@@ -164,5 +164,5 @@
 	    ((ap == PTE_AP_USER_NO_KERNEL_RW) << PAGE_WRITE_SHIFT) |
 	    (1 << PAGE_EXEC_SHIFT) |
-	    (p->bufferable << PAGE_CACHEABLE);
+	    (p->bufferable ? PAGE_CACHEABLE : PAGE_NOT_CACHEABLE);
 }
 
@@ -220,10 +220,10 @@
 
 	if (flags & PAGE_USER)  {
-		if (flags & PAGE_READ) {
+		if (flags & _PAGE_READ) {
 			p->access_permission_0 = p->access_permission_1 =
 			    p->access_permission_2 = p->access_permission_3 =
 			    PTE_AP_USER_RO_KERNEL_RW;
 		}
-		if (flags & PAGE_WRITE) {
+		if (flags & _PAGE_WRITE) {
 			p->access_permission_0 = p->access_permission_1 =
 			    p->access_permission_2 = p->access_permission_3 =
Index: kernel/arch/arm32/include/arch/mm/page_armv6.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -49,4 +49,6 @@
 #define PTE_GET_FRAME_ARCH(pte) \
 	(((uintptr_t) ((pte_t *) (pte))->l1.frame_base_addr) << FRAME_WIDTH)
+#define PTE_READABLE_ARCH(pte) \
+	1
 #define PTE_WRITABLE_ARCH(pte) \
 	(((pte_t *) (pte))->l1.access_permission_1 != PTE_AP1_RO)
@@ -171,7 +173,5 @@
 	const unsigned np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
 
-	return (np << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) |
-	    (1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) |
-	    (1 << PAGE_EXEC_SHIFT) | (1 << PAGE_CACHEABLE_SHIFT);
+	return (np << PAGE_NOT_PRESENT_SHIFT) | PAGE_NEXT_LEVEL_PT;
 }
 
@@ -190,5 +190,5 @@
 	const unsigned ap1 = p->access_permission_1;
 
-	return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_PRESENT_SHIFT) |
+	return ((dt == PTE_DESCRIPTOR_NOT_PRESENT) << PAGE_NOT_PRESENT_SHIFT) |
 	    ((dt != PTE_DESCRIPTOR_SMALL_PAGE_NX) << PAGE_EXEC_SHIFT) |
 	    ((ap0 == PTE_AP0_USER_LIMITED_KERNEL_FULL) << PAGE_READ_SHIFT) |
@@ -198,5 +198,5 @@
 	    (((ap1 != PTE_AP1_RO) && (ap0 == PTE_AP0_USER_FULL_KERNEL_FULL)) << PAGE_WRITE_SHIFT) |
 	    (((ap1 != PTE_AP1_RO) && (ap0 == PTE_AP0_USER_NO_KERNEL_FULL)) << PAGE_WRITE_SHIFT) |
-	    (p->bufferable << PAGE_CACHEABLE);
+	    (p->bufferable ? PAGE_CACHEABLE : PAGE_NOT_CACHEABLE);
 }
 
@@ -249,5 +249,5 @@
 		p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
 	} else {
-		if (flags & PAGE_EXEC)
+		if (flags & _PAGE_EXEC)
 			p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
 		else
@@ -288,11 +288,10 @@
 	p->access_permission_0 = PTE_AP0_USER_NO_KERNEL_FULL;
 
-	if (flags & PAGE_USER) {
+	if (flags & PAGE_USER)
 		p->access_permission_0 = PTE_AP0_USER_FULL_KERNEL_FULL;
-		// TODO Fix kernel to use PAGE_WRITE flag properly and
-		// apply this for kernel pages as well.
-		if (!(flags & PAGE_WRITE))
-			p->access_permission_1 = PTE_AP1_RO;
-	}
+
+	if (!(flags & _PAGE_WRITE))
+		p->access_permission_1 = PTE_AP1_RO;
+
 	pt_coherence(p);
 }
Index: kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c
===================================================================
--- kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -101,5 +101,5 @@
 	beagleboard.irc_addr =
 	    (void *) km_map(AMDM37x_IRC_BASE_ADDRESS, AMDM37x_IRC_SIZE,
-	    PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	assert(beagleboard.irc_addr);
 	omap_irc_init(beagleboard.irc_addr);
Index: kernel/arch/arm32/src/mach/beaglebone/beaglebone.c
===================================================================
--- kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -87,14 +87,18 @@
 {
 	bbone.irc_addr = (void *) km_map(AM335x_IRC_BASE_ADDRESS,
-	    AM335x_IRC_SIZE, PAGE_NOT_CACHEABLE);
+	    AM335x_IRC_SIZE,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	bbone.cm_per_addr = (void *) km_map(AM335x_CM_PER_BASE_ADDRESS,
-	    AM335x_CM_PER_SIZE, PAGE_NOT_CACHEABLE);
+	    AM335x_CM_PER_SIZE,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	bbone.cm_dpll_addr = (void *) km_map(AM335x_CM_DPLL_BASE_ADDRESS,
-	    AM335x_CM_DPLL_SIZE, PAGE_NOT_CACHEABLE);
+	    AM335x_CM_DPLL_SIZE,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	bbone.ctrl_module = (void *) km_map(AM335x_CTRL_MODULE_BASE_ADDRESS,
-	    AM335x_CTRL_MODULE_SIZE, PAGE_NOT_CACHEABLE);
+	    AM335x_CTRL_MODULE_SIZE,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	assert(bbone.irc_addr != NULL);
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -103,7 +103,7 @@
 
 	gta02_timer = (void *) km_map(S3C24XX_TIMER_ADDRESS, PAGE_SIZE,
-	    PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	irqc_regs = (void *) km_map(S3C24XX_IRQC_ADDRESS, PAGE_SIZE,
-	    PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	/* Initialize interrupt controller. */
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -135,11 +135,12 @@
 {
 	icp.hw_map.uart = km_map(ICP_UART, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	icp.hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE, PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+	icp.hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	icp.hw_map.kbd_stat = icp.hw_map.kbd_ctrl + ICP_KBD_STAT;
 	icp.hw_map.kbd_data = icp.hw_map.kbd_ctrl + ICP_KBD_DATA;
 	icp.hw_map.kbd_intstat = icp.hw_map.kbd_ctrl + ICP_KBD_INTR_STAT;
 	icp.hw_map.rtc = km_map(ICP_RTC, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	icp.hw_map.rtc1_load = icp.hw_map.rtc + ICP_RTC1_LOAD_OFFSET;
 	icp.hw_map.rtc1_read = icp.hw_map.rtc + ICP_RTC1_READ_OFFSET;
@@ -150,12 +151,12 @@
 
 	icp.hw_map.irqc = km_map(ICP_IRQC, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	icp.hw_map.irqc_mask = icp.hw_map.irqc + ICP_IRQC_MASK_OFFSET;
 	icp.hw_map.irqc_unmask = icp.hw_map.irqc + ICP_IRQC_UNMASK_OFFSET;
 	icp.hw_map.cmcr = km_map(ICP_CMCR, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	icp.hw_map.sdramcr = icp.hw_map.cmcr + ICP_SDRAMCR_OFFSET;
 	icp.hw_map.vga = km_map(ICP_VGA, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	hw_map_init_called = true;
Index: kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c
===================================================================
--- kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -102,5 +102,5 @@
 	/* Initialize interrupt controller */
 	raspi.irc = (void *) km_map(BCM2835_IRC_ADDR, sizeof(bcm2835_irc_t),
-				    PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	assert(raspi.irc);
 	bcm2835_irc_init(raspi.irc);
@@ -108,6 +108,6 @@
 	/* Initialize system timer */
 	raspi.timer = (void *) km_map(BCM2835_TIMER_ADDR,
-				      sizeof(bcm2835_timer_t),
-				      PAGE_NOT_CACHEABLE);
+	      sizeof(bcm2835_timer_t),
+	      PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 }
 
Index: kernel/arch/arm32/src/mm/page.c
===================================================================
--- kernel/arch/arm32/src/mm/page.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/mm/page.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -52,5 +52,5 @@
 void page_arch_init(void)
 {
-	int flags = PAGE_CACHEABLE | PAGE_EXEC;
+	int flags = PAGE_READ_WRITE_EXECUTE | PAGE_KERNEL | PAGE_CACHEABLE;
 	page_mapping_operations = &pt_mapping_operations;
 
Index: kernel/arch/arm32/src/ras.c
===================================================================
--- kernel/arch/arm32/src/ras.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/arm32/src/ras.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -57,5 +57,5 @@
 
 	ras_page = (uintptr_t *) km_map(frame,
-	    PAGE_SIZE, PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_CACHEABLE);
+	    PAGE_SIZE, PAGE_READ_WRITE | PAGE_USER | PAGE_CACHEABLE);
 
 	memsetb(ras_page, PAGE_SIZE, 0);
Index: kernel/arch/ia32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ia32/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia32/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -109,7 +109,7 @@
 	get_pt_flags((pte_t *) (ptl0), (size_t) (i))
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
 	get_pt_flags((pte_t *) (ptl3), (size_t) (i))
@@ -138,7 +138,10 @@
 #define PTE_GET_FRAME_ARCH(p) \
 	((p)->frame_address << FRAME_WIDTH)
+#define PTE_READABLE_ARCH(p) \
+	1
 #define PTE_WRITABLE_ARCH(p) \
 	((p)->writeable != 0)
-#define PTE_EXECUTABLE_ARCH(p)  1
+#define PTE_EXECUTABLE_ARCH(p) \
+	1
 
 #ifndef __ASSEMBLER__
@@ -184,10 +187,10 @@
 	pte_t *p = &pt[i];
 
-	return ((!p->page_cache_disable) << PAGE_CACHEABLE_SHIFT |
-	    (!p->present) << PAGE_PRESENT_SHIFT |
-	    p->uaccessible << PAGE_USER_SHIFT |
-	    1 << PAGE_READ_SHIFT |
+	return ((p->page_cache_disable ? PAGE_NOT_CACHEABLE : PAGE_CACHEABLE) |
+	    (!p->present) << PAGE_NOT_PRESENT_SHIFT |
+	    (p->uaccessible ? PAGE_USER : PAGE_KERNEL) |
+	    _PAGE_READ |
 	    p->writeable << PAGE_WRITE_SHIFT |
-	    1 << PAGE_EXEC_SHIFT |
+	    _PAGE_EXEC |
 	    p->global << PAGE_GLOBAL_SHIFT);
 }
@@ -199,6 +202,6 @@
 	p->page_cache_disable = !(flags & PAGE_CACHEABLE);
 	p->present = !(flags & PAGE_NOT_PRESENT);
-	p->uaccessible = (flags & PAGE_USER) != 0;
-	p->writeable = (flags & PAGE_WRITE) != 0;
+	p->uaccessible = !(flags & PAGE_KERNEL);
+	p->writeable = (flags & _PAGE_WRITE) != 0;
 	p->global = (flags & PAGE_GLOBAL) != 0;
 
Index: kernel/arch/ia32/src/mm/page.c
===================================================================
--- kernel/arch/ia32/src/mm/page.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia32/src/mm/page.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -70,5 +70,5 @@
 	for (cur = 0; cur < min(config.identity_size, config.physmem_end);
 	    cur += FRAME_SIZE) {
-		flags = PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_WRITE | PAGE_READ;
+		flags = PAGE_READ_WRITE | PAGE_KERNEL | PAGE_GLOBAL | PAGE_CACHEABLE;
 		page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
 	}
Index: kernel/arch/ia32/src/smp/smp.c
===================================================================
--- kernel/arch/ia32/src/smp/smp.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia32/src/smp/smp.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -75,8 +75,10 @@
 
 	if (config.cpu_count > 1) {
-		l_apic = (uint32_t *) km_map((uintptr_t) l_apic, PAGE_SIZE,
-		    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-		io_apic = (uint32_t *) km_map((uintptr_t) io_apic, PAGE_SIZE,
-		    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+		l_apic = (uint32_t *) km_map((uintptr_t) l_apic,
+		    PAGE_SIZE,
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+		io_apic = (uint32_t *) km_map((uintptr_t) io_apic,
+		    PAGE_SIZE,
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	}
 }
Index: kernel/arch/ia32/src/vreg.c
===================================================================
--- kernel/arch/ia32/src/vreg.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia32/src/vreg.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -68,5 +68,5 @@
 
 	page = (uint32_t *) km_map(frame, PAGE_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_USER | PAGE_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_USER | PAGE_CACHEABLE);
 
 	gdt_setbase(&gdt_p[VREG_DES], (uintptr_t) page);
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia64/src/ia64.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -106,5 +106,5 @@
 {
 	uintptr_t IOSAPIC = km_map(iosapic_base, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	int i;
 
@@ -135,5 +135,5 @@
 		/* Map the page with legacy I/O. */
 		legacyio_virt_base = km_map(LEGACYIO_PHYS_BASE, LEGACYIO_SIZE,
-		    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 		iosapic_init();
Index: kernel/arch/ia64/src/mm/page.c
===================================================================
--- kernel/arch/ia64/src/mm/page.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ia64/src/mm/page.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -246,6 +246,6 @@
 	v->present.d = false;  /* not dirty */
 	v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL;
-	v->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ;
-	v->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0;
+	v->present.ar = (flags & _PAGE_WRITE) ? AR_WRITE : AR_READ;
+	v->present.ar |= (flags & _PAGE_EXEC) ? AR_EXECUTE : 0;
 	v->present.ppn = frame >> PPN_SHIFT;
 	v->present.ed = false;  /* exception not deffered */
Index: kernel/arch/mips32/include/arch/mm/page.h
===================================================================
--- kernel/arch/mips32/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/mips32/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -114,7 +114,7 @@
 	get_pt_flags((pte_t *) (ptl0), (size_t) (i))
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
 	get_pt_flags((pte_t *) (ptl3), (size_t) (i))
@@ -140,4 +140,5 @@
 #define PTE_PRESENT_ARCH(pte)		((pte)->p != 0)
 #define PTE_GET_FRAME_ARCH(pte)		((pte)->pfn << 12)
+#define PTE_READABLE_ARCH(pte)		1
 #define PTE_WRITABLE_ARCH(pte)		((pte)->w != 0)
 #define PTE_EXECUTABLE_ARCH(pte)	1
@@ -147,4 +148,6 @@
 #include <mm/mm.h>
 #include <arch/exception.h>
+
+// FIXME: PAGE_USER / PAGE_KERNEL handling?
 
 /** Page Table Entry. */
@@ -167,5 +170,5 @@
 
 	return ((p->cacheable << PAGE_CACHEABLE_SHIFT) |
-	    ((!p->p) << PAGE_PRESENT_SHIFT) |
+	    ((!p->p) << PAGE_NOT_PRESENT_SHIFT) |
 	    (1 << PAGE_USER_SHIFT) |
 	    (1 << PAGE_READ_SHIFT) |
@@ -182,5 +185,5 @@
 	p->p = !(flags & PAGE_NOT_PRESENT);
 	p->g = (flags & PAGE_GLOBAL) != 0;
-	p->w = (flags & PAGE_WRITE) != 0;
+	p->w = (flags & _PAGE_WRITE) != 0;
 
 	/*
Index: kernel/arch/ppc32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ppc32/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -111,8 +111,8 @@
 
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 
 #define GET_PTL3_FLAGS_ARCH(ptl2, i) \
-	PAGE_PRESENT
+	PAGE_NEXT_LEVEL_PT
 
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
@@ -143,4 +143,5 @@
 #define PTE_PRESENT_ARCH(pte)     ((pte)->present != 0)
 #define PTE_GET_FRAME_ARCH(pte)   ((pte)->pfn << 12)
+#define PTE_READABLE_ARCH(pte)    1
 #define PTE_WRITABLE_ARCH(pte)    1
 #define PTE_EXECUTABLE_ARCH(pte)  1
@@ -167,5 +168,5 @@
 
 	return (((!entry->page_cache_disable) << PAGE_CACHEABLE_SHIFT) |
-	    ((!entry->present) << PAGE_PRESENT_SHIFT) |
+	    ((!entry->present) << PAGE_NOT_PRESENT_SHIFT) |
 	    (1 << PAGE_USER_SHIFT) |
 	    (1 << PAGE_READ_SHIFT) |
Index: kernel/arch/ppc32/src/drivers/pic.c
===================================================================
--- kernel/arch/ppc32/src/drivers/pic.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ppc32/src/drivers/pic.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -42,5 +42,6 @@
 void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg)
 {
-	pic = (uint32_t *) km_map(base, size, PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	pic = (uint32_t *) km_map(base, size,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	*cir = pic_ack_interrupt;
 	*cir_arg = NULL;
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/ppc32/src/ppc32.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -242,5 +242,5 @@
 
 		cuda_t *cuda = (cuda_t *) (km_map(aligned_addr, offset + size,
-		    PAGE_WRITE | PAGE_NOT_CACHEABLE) + offset);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE) + offset);
 
 		/* Initialize I/O controller */
Index: kernel/arch/riscv64/include/arch/mm/page.h
===================================================================
--- kernel/arch/riscv64/include/arch/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/riscv64/include/arch/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -82,5 +82,5 @@
 
 /* Flags mask for non-leaf page table entries */
-#define NON_LEAF_MASK  (~(PAGE_READ | PAGE_WRITE | PAGE_EXEC))
+#define NON_LEAF_MASK  (~(_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC))
 
 /* Get PTE address accessors for each level. */
@@ -156,4 +156,5 @@
 #define PTE_PRESENT_ARCH(pte)     ((pte)->valid != 0)
 #define PTE_GET_FRAME_ARCH(pte)   ((uintptr_t) (pte)->pfn << 12)
+#define PTE_READABLE_ARCH(pte)    ((pte)->readable != 0)
 #define PTE_WRITABLE_ARCH(pte)    ((pte)->writable != 0)
 #define PTE_EXECUTABLE_ARCH(pte)  ((pte)->executable != 0)
@@ -183,5 +184,5 @@
 	pte_t *entry = &pt[i];
 
-	return (((!entry->valid) << PAGE_PRESENT_SHIFT) |
+	return (((!entry->valid) << PAGE_NOT_PRESENT_SHIFT) |
 	    (entry->user << PAGE_USER_SHIFT) |
 	    (entry->readable << PAGE_READ_SHIFT) |
@@ -196,7 +197,7 @@
 
 	entry->valid = !(flags & PAGE_NOT_PRESENT);
-	entry->readable = (flags & PAGE_READ) != 0;
-	entry->writable = (flags & PAGE_WRITE) != 0;
-	entry->executable = (flags & PAGE_EXEC) != 0;
+	entry->readable = (flags & _PAGE_READ) != 0;
+	entry->writable = (flags & _PAGE_WRITE) != 0;
+	entry->executable = (flags & _PAGE_EXEC) != 0;
 	entry->user = (flags & PAGE_USER) != 0;
 	entry->global = (flags & PAGE_GLOBAL) != 0;
Index: kernel/arch/riscv64/src/mm/page.c
===================================================================
--- kernel/arch/riscv64/src/mm/page.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/riscv64/src/mm/page.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -63,5 +63,5 @@
 		    cur += FRAME_SIZE)
 			page_mapping_insert(AS_KERNEL, PA2KA(cur), cur,
-			    PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_EXEC | PAGE_WRITE | PAGE_READ);
+			    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_GLOBAL | PAGE_CACHEABLE);
 
 		page_table_unlock(AS_KERNEL, true);
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -119,5 +119,5 @@
 
 	ioport8_t *ns16550 = (ioport8_t *) (km_map(aligned_addr, offset + size,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE) + offset);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE) + offset);
 
 	ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, 0, inr, cir,
Index: kernel/arch/sparc64/src/drivers/pci.c
===================================================================
--- kernel/arch/sparc64/src/drivers/pci.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/arch/sparc64/src/drivers/pci.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -110,5 +110,5 @@
 	pci->op = &pci_sabre_ops;
 	pci->reg = (uint64_t *) km_map(paddr, reg[SABRE_INTERNAL_REG].size,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	return pci;
@@ -152,5 +152,5 @@
 	pci->op = &pci_psycho_ops;
 	pci->reg = (uint64_t *) km_map(paddr, reg[PSYCHO_INTERNAL_REG].size,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	return pci;
Index: kernel/genarch/include/genarch/drivers/amdm37x/gpt.h
===================================================================
--- kernel/genarch/include/genarch/drivers/amdm37x/gpt.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/include/genarch/drivers/amdm37x/gpt.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -208,5 +208,6 @@
 	// TODO find a nicer way to setup 32kHz clock source for timer1
 	// reg 0x48004C40 is CM_CLKSEL_WKUP see page 485 of the manual
-	ioport32_t *clksel = (void*) km_map(0x48004C40, 4, PAGE_NOT_CACHEABLE);
+	ioport32_t *clksel = (void*) km_map(0x48004C40, 4,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	*clksel &= ~1;
 	km_unmap((uintptr_t)clksel, 4);
@@ -214,5 +215,6 @@
 	assert(timer);
 	/* Map control register */
-	timer->regs = (void*) km_map(ioregs, iosize, PAGE_NOT_CACHEABLE);
+	timer->regs = (void*) km_map(ioregs, iosize,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	/* Reset the timer */
Index: kernel/genarch/include/genarch/mm/page_pt.h
===================================================================
--- kernel/genarch/include/genarch/mm/page_pt.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/include/genarch/mm/page_pt.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -136,5 +136,5 @@
 #define PTE_PRESENT(p)     PTE_PRESENT_ARCH((p))
 #define PTE_GET_FRAME(p)   PTE_GET_FRAME_ARCH((p))
-#define PTE_READABLE(p)    1
+#define PTE_READABLE(p)    PTE_READABLE_ARCH((p))
 #define PTE_WRITABLE(p)    PTE_WRITABLE_ARCH((p))
 #define PTE_EXECUTABLE(p)  PTE_EXECUTABLE_ARCH((p))
Index: kernel/genarch/src/acpi/acpi.c
===================================================================
--- kernel/genarch/src/acpi/acpi.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/acpi/acpi.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -104,9 +104,11 @@
 	/* Start with mapping the header only. */
 	vhdr = (struct acpi_sdt_header *) km_map((uintptr_t) psdt,
-	    sizeof(struct acpi_sdt_header), PAGE_READ | PAGE_NOT_CACHEABLE);
+	    sizeof(struct acpi_sdt_header),
+	    PAGE_READ_ONLY | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	/* Now we can map the entire structure. */
 	vsdt = (struct acpi_sdt_header *) km_map((uintptr_t) psdt,
-	    vhdr->length, PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    vhdr->length,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	// TODO: do not leak vtmp
Index: kernel/genarch/src/drivers/am335x/timer.c
===================================================================
--- kernel/genarch/src/drivers/am335x/timer.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/am335x/timer.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -100,5 +100,6 @@
 	size = regs_map[id].size;
 
-	timer->regs = (void *) km_map(base_addr, size, PAGE_NOT_CACHEABLE);
+	timer->regs = (void *) km_map(base_addr, size,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	assert(timer->regs != NULL);
 
Index: kernel/genarch/src/drivers/bcm2835/mbox.c
===================================================================
--- kernel/genarch/src/drivers/bcm2835/mbox.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/bcm2835/mbox.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -91,5 +91,5 @@
 
 	fb_mbox = (void *) km_map(BCM2835_MBOX0_ADDR, sizeof(bcm2835_mbox_t),
-				  PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	fb_desc->width = 640;
Index: kernel/genarch/src/drivers/ega/ega.c
===================================================================
--- kernel/genarch/src/drivers/ega/ega.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/ega/ega.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -601,5 +601,5 @@
 	instance->base = base;
 	instance->addr = (uint8_t *) km_map(addr, EGA_VRAM_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	if (!instance->addr) {
 		LOG("Unable to EGA video memory.");
Index: kernel/genarch/src/drivers/omap/uart.c
===================================================================
--- kernel/genarch/src/drivers/omap/uart.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/omap/uart.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -87,5 +87,6 @@
 {
 	assert(uart);
-	uart->regs = (void *)km_map(addr, size, PAGE_NOT_CACHEABLE);
+	uart->regs = (void *)km_map(addr, size,
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	assert(uart->regs);
Index: kernel/genarch/src/drivers/pl011/pl011.c
===================================================================
--- kernel/genarch/src/drivers/pl011/pl011.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/pl011/pl011.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -100,5 +100,5 @@
 	assert(uart);
 	uart->regs = (void*)km_map(addr, sizeof(pl011_uart_regs_t),
-				   PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	assert(uart->regs);
 
Index: kernel/genarch/src/drivers/s3c24xx/uart.c
===================================================================
--- kernel/genarch/src/drivers/s3c24xx/uart.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/drivers/s3c24xx/uart.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -117,5 +117,5 @@
 
 	uart->io = (s3c24xx_uart_io_t *) km_map(paddr, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	uart->indev = NULL;
 
Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/fb/fb.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -610,5 +610,5 @@
 
 	instance->addr = (uint8_t *) km_map((uintptr_t) props->addr, fbsize,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 	if (!instance->addr) {
 		LOG("Unable to map framebuffer.");
Index: kernel/genarch/src/mm/page_ht.c
===================================================================
--- kernel/genarch/src/mm/page_ht.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/mm/page_ht.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -61,5 +61,5 @@
 static void ht_mapping_remove(as_t *, uintptr_t);
 static bool ht_mapping_find(as_t *, uintptr_t, bool, pte_t *);
-static void ht_mapping_update(as_t *, uintptr_t, bool, pte_t *);
+static void ht_mapping_update(as_t *, uintptr_t, bool, const pte_t *);
 static void ht_mapping_make_global(uintptr_t, size_t);
 
@@ -168,6 +168,6 @@
 
 		pte->g = (flags & PAGE_GLOBAL) != 0;
-		pte->x = (flags & PAGE_EXEC) != 0;
-		pte->w = (flags & PAGE_WRITE) != 0;
+		pte->x = (flags & _PAGE_EXEC) != 0;
+		pte->w = (flags & _PAGE_WRITE) != 0;
 		pte->k = !(flags & PAGE_USER);
 		pte->c = (flags & PAGE_CACHEABLE) != 0;
@@ -268,5 +268,5 @@
  * @param pte      New PTE.
  */
-void ht_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+void ht_mapping_update(as_t *as, uintptr_t page, bool nolock, const pte_t *pte)
 {
 	irq_spinlock_lock(&page_ht_lock, true);
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/genarch/src/mm/page_pt.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -55,5 +55,5 @@
 static void pt_mapping_remove(as_t *, uintptr_t);
 static bool pt_mapping_find(as_t *, uintptr_t, bool, pte_t *pte);
-static void pt_mapping_update(as_t *, uintptr_t, bool, pte_t *pte);
+static void pt_mapping_update(as_t *, uintptr_t, bool, const pte_t *pte);
 static void pt_mapping_make_global(uintptr_t, size_t);
 
@@ -90,6 +90,5 @@
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
-		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
-		    PAGE_WRITE);
+		    PAGE_NOT_PRESENT | PAGE_NEXT_LEVEL_PT);
 		/*
 		 * Make sure that a concurrent hardware page table walk or
@@ -109,6 +108,5 @@
 		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
 		SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
-		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
-		    PAGE_WRITE);
+		    PAGE_NOT_PRESENT | PAGE_NEXT_LEVEL_PT);
 		/*
 		 * Make the new PTL2 visible only after it is fully initialized.
@@ -126,6 +124,5 @@
 		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
 		SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
-		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
-		    PAGE_WRITE);
+		    PAGE_NOT_PRESENT | PAGE_NEXT_LEVEL_PT);
 		/*
 		 * Make the new PTL3 visible only after it is fully initialized.
@@ -353,5 +350,5 @@
  * @param[in] pte  New PTE.
  */
-void pt_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+void pt_mapping_update(as_t *as, uintptr_t page, bool nolock, const pte_t *pte)
 {
 	pte_t *t = pt_mapping_find_internal(as, page, nolock);
@@ -431,6 +428,5 @@
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
-		    PAGE_PRESENT | PAGE_USER | PAGE_CACHEABLE |
-		    PAGE_EXEC | PAGE_WRITE | PAGE_READ);
+		    PAGE_NEXT_LEVEL_PT);
 	}
 }
Index: kernel/generic/include/mm/mm.h
===================================================================
--- kernel/generic/include/mm/mm.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/include/mm/mm.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -36,29 +36,114 @@
 #define KERN_MM_H_
 
-#define PAGE_CACHEABLE_SHIFT		0
-#define PAGE_NOT_CACHEABLE_SHIFT	PAGE_CACHEABLE_SHIFT
-#define PAGE_PRESENT_SHIFT		1
-#define PAGE_NOT_PRESENT_SHIFT		PAGE_PRESENT_SHIFT
-#define PAGE_USER_SHIFT			2
-#define PAGE_KERNEL_SHIFT		PAGE_USER_SHIFT
+#include <assert.h>
+#include <stdbool.h>
+
+#define PAGE_NOT_CACHEABLE_SHIFT	0
+#define PAGE_CACHEABLE_SHIFT		1
+#define PAGE_NOT_PRESENT_SHIFT		2
 #define PAGE_READ_SHIFT			3
 #define PAGE_WRITE_SHIFT		4
 #define PAGE_EXEC_SHIFT			5
 #define PAGE_GLOBAL_SHIFT		6
+#define PAGE_USER_SHIFT			7
+#define PAGE_KERNEL_SHIFT		8
 
-#define PAGE_NOT_CACHEABLE		(0 << PAGE_CACHEABLE_SHIFT)
+/* Cacheability.
+ * Platform-independent code should always use PAGE_CACHEABLE for normal memory,
+ * and PAGE_NOT_CACHEABLE for I/O memory.
+ * In particular, setting PAGE_NOT_CACHEABLE on normal memory does not prevent
+ * caching on all platforms. You have been warned.
+ * Exactly one must be present for leaf pages.
+ * None may be present for non-leaf entries.
+ */
+
+#define PAGE_NOT_CACHEABLE		(1 << PAGE_NOT_CACHEABLE_SHIFT)
 #define PAGE_CACHEABLE			(1 << PAGE_CACHEABLE_SHIFT)
 
-#define PAGE_PRESENT			(0 << PAGE_PRESENT_SHIFT)
-#define PAGE_NOT_PRESENT		(1 << PAGE_PRESENT_SHIFT)
 
-#define PAGE_USER			(1 << PAGE_USER_SHIFT)
-#define PAGE_KERNEL			(0 << PAGE_USER_SHIFT)
+/* Discriminant, exactly one of the following seven must be set for
+ * the flags to be valid. Furthermore, the first two are only legal
+ * for setting individual page table entries. Setting an entry
+ * to PAGE_NOT_PRESENT renders the entry eligible for removal.
+ * In an earlier iteration of this interface, page could be not
+ * present but valid, preventing removal. This has been changed, and
+ * if future iterations allow kernel to hide data (e.g. swap identifiers)
+ * in page tables, it should be achieved by adding a separate discriminant.
+ */
+#define PAGE_NOT_PRESENT          (1 << PAGE_NOT_PRESENT_SHIFT)
 
-#define PAGE_READ			(1 << PAGE_READ_SHIFT)
-#define PAGE_WRITE			(1 << PAGE_WRITE_SHIFT)
-#define PAGE_EXEC			(1 << PAGE_EXEC_SHIFT)
+// TODO: This will be a separate flag.
+#define PAGE_NEXT_LEVEL_PT        (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC | PAGE_USER | PAGE_CACHEABLE)
 
-#define PAGE_GLOBAL			(1 << PAGE_GLOBAL_SHIFT)
+#define PAGE_READ_ONLY            (_PAGE_READ)
+#define PAGE_READ_EXECUTE         (_PAGE_READ | _PAGE_EXEC)
+#define PAGE_READ_WRITE           (_PAGE_READ | _PAGE_WRITE)
+#define PAGE_READ_WRITE_EXECUTE   (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
+#define PAGE_EXECUTE_ONLY         (_PAGE_EXEC)
+
+/* Individual permissions.
+ * Only used when the flags are tested or translated from other
+ * format. In constant flags, use one of the combinations above.
+ */
+#define _PAGE_READ                (1 << PAGE_READ_SHIFT)
+#define _PAGE_WRITE               (1 << PAGE_WRITE_SHIFT)
+#define _PAGE_EXEC                (1 << PAGE_EXEC_SHIFT)
+
+/* Global page. Can be combined with anything except PAGE_NOT_PRESENT.
+ * PAGE_GLOBAL on non-leaf entry means all the leaf entries under it are global,
+ * even if they don't have the PAGE_GLOBAL flag themselves.
+ */
+#define PAGE_GLOBAL               (1 << PAGE_GLOBAL_SHIFT)
+
+/* Protection.
+ * PAGE_USER for memory accessible to userspace programs, PAGE_KERNEL for
+ * memory accessible only to the kernel. Note that on some platforms,
+ * PAGE_USER pages are accessible to kernel, while on others, they are not.
+ * For non-leaf entries, PAGE_USER means that all of the lower-level pages
+ * are PAGE_USER, likewise with PAGE_KERNEL. Exactly one of these two must be
+ * used for leaf entries, but it may be omitted for non-leaf entries.
+ */
+#define PAGE_USER                 (1 << PAGE_USER_SHIFT)
+#define PAGE_KERNEL               (1 << PAGE_KERNEL_SHIFT)
+
+
+
+static inline bool PAGE_FLAGS_VALID(unsigned flags) {
+	// TODO
+
+	/* Empty entry supports no flags. */
+	if (flags & PAGE_NOT_PRESENT)
+		return flags == PAGE_NOT_PRESENT;
+
+	/* PAGE_USER and PAGE_KERNEL are mutually exclusive. */
+	if ((flags & PAGE_USER) && (flags & PAGE_KERNEL))
+		return false;
+
+	/* Check allowed flags for non-leaf entry. */
+	if (flags & PAGE_NEXT_LEVEL_PT)
+		return flags == (flags & (PAGE_NEXT_LEVEL_PT | PAGE_GLOBAL | PAGE_USER | PAGE_KERNEL));
+
+	/* Leaf entries only. */
+
+	/* Check that at least one permission is set. */
+	if (!(flags & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)))
+		return false;
+
+	/* Check that write implies read. */
+	if ((flags & _PAGE_WRITE) && !(flags & _PAGE_READ))
+		return false;
+
+	/* One of PAGE_USER and PAGE_KERNEL must be used. */
+	if (!(flags & (PAGE_USER | PAGE_KERNEL)))
+		return false;
+
+	/* One of PAGE_CACHEABLE and PAGE_NOT_CACHEABLE must be used. */
+	if ((flags & PAGE_CACHEABLE) && (flags & PAGE_NOT_CACHEABLE))
+		return false;
+	if (!(flags & (PAGE_CACHEABLE | PAGE_NOT_CACHEABLE)))
+		return false;
+
+	return true;
+}
 
 #endif
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/include/mm/page.h	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -49,5 +49,5 @@
 	void (*mapping_remove)(as_t *, uintptr_t);
 	bool (*mapping_find)(as_t *, uintptr_t, bool, pte_t *);
-	void (*mapping_update)(as_t *, uintptr_t, bool, pte_t *);
+	void (*mapping_update)(as_t *, uintptr_t, bool, const pte_t *);
 	void (*mapping_make_global)(uintptr_t, size_t);
 } page_mapping_operations_t;
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/src/console/cmd.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -727,6 +727,7 @@
 	else
 #endif
-		ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
-		    PAGE_NOT_CACHEABLE);
+		ptr = (uint8_t *) km_map(
+		    argv[0].intval, sizeof(uint8_t),
+		    PAGE_READ_ONLY | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	const uint8_t val = pio_read_8(ptr);
@@ -749,4 +750,97 @@
  */
 static int cmd_pio_read_16(cmd_arg_t *argv)
+{
+	uint16_t *ptr = NULL;
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		ptr = (void *) argv[0].intval;
+	else
+#endif
+		ptr = (uint16_t *) km_map(
+		    argv[0].intval, sizeof(uint16_t),
+		    PAGE_READ_ONLY | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+
+	const uint16_t val = pio_read_16(ptr);
+	printf("read %" PRIxn ": %" PRIx16 "\n", argv[0].intval, val);
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		return 1;
+#endif
+
+	km_unmap((uintptr_t) ptr, sizeof(uint16_t));
+	return 1;
+}
+
+/** Read 4 bytes from phys memory or io port.
+ *
+ * @param argv Argument vector.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+static int cmd_pio_read_32(cmd_arg_t *argv)
+{
+	uint32_t *ptr = NULL;
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		ptr = (void *) argv[0].intval;
+	else
+#endif
+		ptr = (uint32_t *) km_map(
+		    argv[0].intval, sizeof(uint32_t),
+		    PAGE_READ_ONLY | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+
+	const uint32_t val = pio_read_32(ptr);
+	printf("read %" PRIxn ": %" PRIx32 "\n", argv[0].intval, val);
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		return 1;
+#endif
+
+	km_unmap((uintptr_t) ptr, sizeof(uint32_t));
+	return 1;
+}
+
+/** Write 1 byte to phys memory or io port.
+ *
+ * @param argv Argument vector.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+static int cmd_pio_write_8(cmd_arg_t *argv)
+{
+	uint8_t *ptr = NULL;
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		ptr = (void *) argv[0].intval;
+	else
+#endif
+		ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+
+	printf("write %" PRIxn ": %" PRIx8 "\n", argv[0].intval,
+	    (uint8_t) argv[1].intval);
+	pio_write_8(ptr, (uint8_t) argv[1].intval);
+
+#ifdef IO_SPACE_BOUNDARY
+	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
+		return 1;
+#endif
+
+	km_unmap((uintptr_t) ptr, sizeof(uint8_t));
+	return 1;
+}
+
+/** Write 2 bytes to phys memory or io port.
+ *
+ * @param argv Argument vector.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+static int cmd_pio_write_16(cmd_arg_t *argv)
 {
 	uint16_t *ptr = NULL;
@@ -758,8 +852,9 @@
 #endif
 		ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
-		    PAGE_NOT_CACHEABLE);
-
-	const uint16_t val = pio_read_16(ptr);
-	printf("read %" PRIxn ": %" PRIx16 "\n", argv[0].intval, val);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+
+	printf("write %" PRIxn ": %" PRIx16 "\n", argv[0].intval,
+	    (uint16_t) argv[1].intval);
+	pio_write_16(ptr, (uint16_t) argv[1].intval);
 
 #ifdef IO_SPACE_BOUNDARY
@@ -772,5 +867,5 @@
 }
 
-/** Read 4 bytes from phys memory or io port.
+/** Write 4 bytes to phys memory or io port.
  *
  * @param argv Argument vector.
@@ -778,5 +873,5 @@
  * @return 0 on failure, 1 on success.
  */
-static int cmd_pio_read_32(cmd_arg_t *argv)
+static int cmd_pio_write_32(cmd_arg_t *argv)
 {
 	uint32_t *ptr = NULL;
@@ -788,97 +883,5 @@
 #endif
 		ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
-		    PAGE_NOT_CACHEABLE);
-
-	const uint32_t val = pio_read_32(ptr);
-	printf("read %" PRIxn ": %" PRIx32 "\n", argv[0].intval, val);
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		return 1;
-#endif
-
-	km_unmap((uintptr_t) ptr, sizeof(uint32_t));
-	return 1;
-}
-
-/** Write 1 byte to phys memory or io port.
- *
- * @param argv Argument vector.
- *
- * @return 0 on failure, 1 on success.
- */
-static int cmd_pio_write_8(cmd_arg_t *argv)
-{
-	uint8_t *ptr = NULL;
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		ptr = (void *) argv[0].intval;
-	else
-#endif
-		ptr = (uint8_t *) km_map(argv[0].intval, sizeof(uint8_t),
-		    PAGE_NOT_CACHEABLE);
-
-	printf("write %" PRIxn ": %" PRIx8 "\n", argv[0].intval,
-	    (uint8_t) argv[1].intval);
-	pio_write_8(ptr, (uint8_t) argv[1].intval);
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		return 1;
-#endif
-
-	km_unmap((uintptr_t) ptr, sizeof(uint8_t));
-	return 1;
-}
-
-/** Write 2 bytes to phys memory or io port.
- *
- * @param argv Argument vector.
- *
- * @return 0 on failure, 1 on success.
- */
-static int cmd_pio_write_16(cmd_arg_t *argv)
-{
-	uint16_t *ptr = NULL;
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		ptr = (void *) argv[0].intval;
-	else
-#endif
-		ptr = (uint16_t *) km_map(argv[0].intval, sizeof(uint16_t),
-		    PAGE_NOT_CACHEABLE);
-
-	printf("write %" PRIxn ": %" PRIx16 "\n", argv[0].intval,
-	    (uint16_t) argv[1].intval);
-	pio_write_16(ptr, (uint16_t) argv[1].intval);
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		return 1;
-#endif
-
-	km_unmap((uintptr_t) ptr, sizeof(uint16_t));
-	return 1;
-}
-
-/** Write 4 bytes to phys memory or io port.
- *
- * @param argv Argument vector.
- *
- * @return 0 on failure, 1 on success.
- */
-static int cmd_pio_write_32(cmd_arg_t *argv)
-{
-	uint32_t *ptr = NULL;
-
-#ifdef IO_SPACE_BOUNDARY
-	if ((void *) argv->intval < IO_SPACE_BOUNDARY)
-		ptr = (void *) argv[0].intval;
-	else
-#endif
-		ptr = (uint32_t *) km_map(argv[0].intval, sizeof(uint32_t),
-		    PAGE_NOT_CACHEABLE);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 
 	printf("write %" PRIxn ": %" PRIx32 "\n", argv[0].intval,
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/src/ipc/irq.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -93,5 +93,5 @@
 #endif
 		ranges[i].base = km_map(pbase[i], ranges[i].size,
-		    PAGE_READ | PAGE_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_NOT_CACHEABLE);
 		if (!ranges[i].base) {
 			ranges_unmap(ranges, i);
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/src/main/kinit.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -250,5 +250,5 @@
 		uintptr_t page = km_map(init.tasks[i].paddr,
 		    init.tasks[i].size,
-		    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_CACHEABLE);
 		assert(page);
 
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/src/mm/as.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -1217,17 +1217,19 @@
 NO_TRACE static unsigned int area_flags_to_page_flags(unsigned int aflags)
 {
-	unsigned int flags = PAGE_USER | PAGE_PRESENT;
+	unsigned int flags = PAGE_USER;
 
 	if (aflags & AS_AREA_READ)
-		flags |= PAGE_READ;
+		flags |= _PAGE_READ;
 
 	if (aflags & AS_AREA_WRITE)
-		flags |= PAGE_WRITE;
+		flags |= _PAGE_WRITE;
 
 	if (aflags & AS_AREA_EXEC)
-		flags |= PAGE_EXEC;
+		flags |= _PAGE_EXEC;
 
 	if (aflags & AS_AREA_CACHEABLE)
 		flags |= PAGE_CACHEABLE;
+	else
+		flags |= PAGE_NOT_CACHEABLE;
 
 	return flags;
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/generic/src/mm/km.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -257,5 +257,5 @@
 	if (frame) {
 		page = km_map(frame, PAGE_SIZE,
-		    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
+		    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_CACHEABLE);
 		if (!page) {
 			frame_free(frame, 1);
Index: kernel/test/mm/mapping1.c
===================================================================
--- kernel/test/mm/mapping1.c	(revision 67f11a04d9b9007cff6be59c182bd35c4f3ee076)
+++ kernel/test/mm/mapping1.c	(revision 94d211e1f212626c420cf42c22b056ac1db9c0f1)
@@ -44,10 +44,10 @@
 
 	uintptr_t page0 = km_map(frame, FRAME_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_CACHEABLE);
 	TPRINTF("Virtual address %p mapped to physical address %p.\n",
 	    (void *) page0, (void *) frame);
 
 	uintptr_t page1 = km_map(frame, FRAME_SIZE,
-	    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
+	    PAGE_READ_WRITE | PAGE_KERNEL | PAGE_CACHEABLE);
 	TPRINTF("Virtual address %p mapped to physical address %p.\n",
 	    (void *) page1, (void *) frame);
