diff --git a/kernel/Makefile b/kernel/Makefile
index 3b061d6..b3680f7 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -12,11 +12,16 @@ ASMINCS = sys/bootinfo.inc \
 			sys/register.inc
 
 KERNEL	= vmstupid.sys
+
+MM_SRCS = bootstrap.inc \
+			mm.inc \
+			pmm.inc \
+			vmm.inc
+
 SRCS	= kernel.asm \
 			const.inc \
 			klog.inc \
-			mm/mm.old.inc \
-			mm/pmm.old.inc \
+			$(addprefix mm/, $(MM_SRCS)) \
 			lock.inc \
 			gdt.inc \
 			isr.inc \
diff --git a/kernel/const.inc.in b/kernel/const.inc.in
index 8aa4da9..f0d66f2 100644
--- a/kernel/const.inc.in
+++ b/kernel/const.inc.in
@@ -16,3 +16,7 @@ BUILD_DATE     equ "@DATE@"
 ; ------------- OTHER -----------
 CR   = 0x0D
 LF   = 0x0A
+
+
+CONFIG_COMPAT_I386 = 0
+CONFIG_TRACE_PMM = 1
diff --git a/kernel/dev/at/cga.inc b/kernel/dev/at/cga.inc
index b8ee9ad..b5fd1c5 100644
--- a/kernel/dev/at/cga.inc
+++ b/kernel/dev/at/cga.inc
@@ -11,6 +11,40 @@ CGA_CURSOR_LOW  = 0xF
 CGA_COLUMNS = 80
 CGA_LINES = 24
 
+CGA_COLOR_FG_BLACK         = 0x00
+CGA_COLOR_FG_BLUE          = 0x01
+CGA_COLOR_FG_GREEN         = 0x02
+CGA_COLOR_FG_CYAN          = 0x03
+CGA_COLOR_FG_RED           = 0x04
+CGA_COLOR_FG_MAGENTA       = 0x05
+CGA_COLOR_FG_BROWN         = 0x06
+CGA_COLOR_FG_LIGHT_GRAY    = 0x07
+CGA_COLOR_FG_DARK_GRAY     = 0x08
+CGA_COLOR_FG_LIGHT_BLUE    = 0x09
+CGA_COLOR_FG_LIGHT_GREEN   = 0x0A
+CGA_COLOR_FG_LIGHT_CYAN    = 0x0B
+CGA_COLOR_FG_LIGHT_RED     = 0x0C
+CGA_COLOR_FG_LIGHT_MAGENTA = 0x0D
+CGA_COLOR_FG_YELLOW        = 0x0E
+CGA_COLOR_FG_WHITE         = 0x0F
+
+CGA_COLOR_BG_BLACK         = 0x00
+CGA_COLOR_BG_BLUE          = 0x10
+CGA_COLOR_BG_GREEN         = 0x20
+CGA_COLOR_BG_CYAN          = 0x30
+CGA_COLOR_BG_RED           = 0x40
+CGA_COLOR_BG_MAGENTA       = 0x50
+CGA_COLOR_BG_BROWN         = 0x60
+CGA_COLOR_BG_LIGHT_GRAY    = 0x70
+CGA_COLOR_BG_DARK_GRAY     = 0x80
+CGA_COLOR_BG_LIGHT_BLUE    = 0x90
+CGA_COLOR_BG_LIGHT_GREEN   = 0xA0
+CGA_COLOR_BG_LIGHT_CYAN    = 0xB0
+CGA_COLOR_BG_LIGHT_RED     = 0xC0
+CGA_COLOR_BG_LIGHT_MAGENTA = 0xD0
+CGA_COLOR_BG_YELLOW        = 0xE0
+CGA_COLOR_BG_WHITE         = 0xF0
+
 	;; Function: cga_getpos
 	;; 
 	;; Out:
@@ -94,7 +128,7 @@ cga_putc:
 	mov cx, [ebp-0x2]
 	shl cx, 1
 	add edx, ecx
-	mov ah, 0x07
+	mov ah, byte [cga_color]
 	mov word [edx], ax
 	mov cx, [ebp-0x2]
 	inc cx
@@ -134,3 +168,5 @@ cga_putc:
 
 cga_device:
 	db 'video', 0, 0, 0
+
+cga_color db CGA_COLOR_FG_LIGHT_GRAY
diff --git a/kernel/kernel.asm b/kernel/kernel.asm
index 824fb53..d654395 100644
--- a/kernel/kernel.asm
+++ b/kernel/kernel.asm
@@ -46,20 +46,15 @@ kmain:
 
 	call mm_bootstrap
 
-	xchg bx, bx
-
-	; init pmm (kend, 0x400000)
-	mov eax, kend
-	mov ebx, 0xC0400000
 	call pmm_init
 
 	; init vmm
-	call mm_init
+	;call mm_init
 
-	mov eax, 0xC0400000
-	mov ebx, [stBootInfo.high_mem]
-	add ebx, KERNEL_VIRT_BASE
-	call pmm_free_range
+	;mov eax, 0xC0400000
+	;mov ebx, [stBootInfo.high_mem]
+	;add ebx, KERNEL_VIRT_BASE
+	;call pmm_free_range
 
 	;mov eax, [stBootInfo.low_mem]
 	;call heap_init
@@ -121,8 +116,7 @@ kmain:
 	include 'klog.inc'
 	include 'dev/console.inc'
 	include 'dev/dev.inc'
-	include 'mm/bootstrap.inc'
-	include 'mm/mm.old.inc'
+	include 'mm/mm.inc'
 	include 'lock.inc'
 	include 'gdt.inc'
 	include 'syscall.inc'
diff --git a/kernel/klog.inc b/kernel/klog.inc
index f6067dc..c56ce5f 100644
--- a/kernel/klog.inc
+++ b/kernel/klog.inc
@@ -4,6 +4,12 @@
 
 COM1 = 0x3F8
 
+macro TRACE {
+	mov byte [cga_color], CGA_COLOR_FG_CYAN
+	call klog
+	mov byte [cga_color], CGA_COLOR_FG_LIGHT_GRAY
+}
+
 	;; Function: _klog_print_str
 	;;
 	;; In: EAX - Null-terminated string to print
@@ -213,7 +219,7 @@ klog:
 	; display log time
 	call _klog_print_time
 
-	mov ecx, 4
+	mov ecx, 8
 .begin:
 	mov al, [esi]
 	or al, al
@@ -299,6 +305,8 @@ klog:
 	mov eax, szCRLF
 	call _klog_print_str
 
+	pop esi
+
 	leave
 	ret
 
diff --git a/kernel/mm/bootstrap.inc b/kernel/mm/bootstrap.inc
index 5966a65..fa7a8d3 100644
--- a/kernel/mm/bootstrap.inc
+++ b/kernel/mm/bootstrap.inc
@@ -38,7 +38,7 @@ mm_bootstrap:
 
 	mov eax, 0x400000 + (1023 * PAGE_SIZE)
 	mov cr3, eax
- 
+	
 	ret
 
 szMsgMmBootstrap db "MM: boostrap", 0
diff --git a/kernel/mm/mm.inc b/kernel/mm/mm.inc
new file mode 100644
index 0000000..eb860e2
--- /dev/null
+++ b/kernel/mm/mm.inc
@@ -0,0 +1,9 @@
+MM_KERNEL_PTE_BASE = 0xFFC00000
+
+	include '../sys/mmu.inc'
+	include 'bootstrap.inc'
+	include 'pmm.inc'
+	include 'vmm.inc'
+
+mm_init:
+	ret
diff --git a/kernel/mm/mm.new.inc b/kernel/mm/mm.new.inc
deleted file mode 100644
index 4e85f31..0000000
--- a/kernel/mm/mm.new.inc
+++ /dev/null
@@ -1,34 +0,0 @@
-MM_PTE_BASE = 0xFFC00000
-MM_VIRT_TEMP = 0xD0000000
-
-	;; EAX - Physical address to map
-mm_map_temp:
-	mov ecx, MM_PTE_BASE + (MM_VIRT_TEMP shr 12)
-	or eax, 0x3
-	mov [ecx], eax
-
-if COMPAT_I386
-	mov eax, 0x40000 + (1023 * PAGE_SIZE)
-	mov cr3, eax
-else
-	mov eax, MM_VIRT_TEMP
-	invlpg [eax]
-end if
-
-	ret
-
-mm_unmap_temp:
-	mov ecx, MM_PTE_BASE + (MM_VIRT_TEMP shr 12)
-	mov dword [ecx], 0
-
-if COMPAT_I386
-	mov eax, 0x40000 + (1023 * PAGE_SIZE)
-	mov cr3, eax
-else
-	mov eax, MM_VIRT_TEMP
-	invlpg [eax]
-end if
-	ret
-
-mm_init:
-	ret
diff --git a/kernel/mm/pmm.inc b/kernel/mm/pmm.inc
index 0d61cf9..8e157de 100644
--- a/kernel/mm/pmm.inc
+++ b/kernel/mm/pmm.inc
@@ -8,6 +8,13 @@
 	;; > └─────┘      └─────┘       
 	;;
 
+;;; MARK: macros and structs
+
+	;; Constant: PMM_VIRT_TEMP
+PMM_VIRT_TEMP = 0xD0000000
+PMM_BITMAP_USED = 0x0
+PMM_BITMAP_FREE = 0x1
+
 	;; Macro: PAGE_ALIGN_UP reg
 macro PAGE_ALIGN_UP reg {
 	add reg, PAGE_SIZE - 1
@@ -26,37 +33,128 @@ struc PMMFreeRange {
 }
 DEFN PMMFreeRange
 
+;;; MARK: private functions
+
 	;; Function: _pmm_map_temp_page
 	;;
+	;; In:
+	;;   EAX - physical address to map at <PMM_VIRT_TEMP>
 _pmm_map_temp_page:
+	mov ecx, MM_KERNEL_PTE_BASE + (PMM_VIRT_TEMP shr 12) * 4
+	or eax, 0x3
+	mov [ecx], eax
+
+if CONFIG_COMPAT_I386
+	mov eax, 0x40000 + (1023 * PAGE_SIZE)
+	mov cr3, eax
+else
+	mov eax, PMM_VIRT_TEMP
+	invlpg [eax]
+end if
 	ret
 
 _pmm_unmap_temp_page:
+	mov ecx, MM_KERNEL_PTE_BASE + (PMM_VIRT_TEMP shr 12) * 4
+	mov dword [ecx], 0
+
+if CONFIG_COMPAT_I386
+	mov eax, 0x40000 + (1023 * PAGE_SIZE)
+	mov cr3, eax
+else
+	mov eax, PMM_VIRT_TEMP
+	invlpg [eax]
+end if
 	ret
 
+	;; Function: _pmm_init_region
+	;;
+	;; Add new memory region to the linked list.
+	;;
+	;; In:
+	;;    EAX - Start
+	;;    EDX - End
+	;;
 _pmm_init_region:
 	push ebp
 	mov ebp, esp
 
+	push edi
+	push esi
+
+	mov edi, eax
+	mov esi, edx
+
+	push edx
 	push eax
-	call _pmm_map_temp_page
+	mov eax, szMsgPmmFreeRange
+	call klog
 	pop eax
+	pop edx
+
+	call _pmm_map_temp_page
 
 	xor ecx, ecx
-	mov [MM_VIRT_TEMP], edx
-	mov [MM_VIRT_TEMP + PMMFreeRange.next], ecx
-	mov ecx, [pPMMFreeListHead]
+	mov [PMM_VIRT_TEMP], esi
+	mov [PMM_VIRT_TEMP + PMMFreeRange.next], ecx
+	mov ecx, [pPmmFreeListHead]
 	or ecx, ecx
 	jz @f
-	mov [MM_VIRT_TEMP + PMMFreeRange.next], ecx
+	mov [PMM_VIRT_TEMP + PMMFreeRange.next], ecx
 @@:
-	mov [pPMMFreeListHead], eax
+	mov [pPmmFreeListHead], edi
 
 	call _pmm_unmap_temp_page
 
+	pop edi
+	pop esi
+
 	leave
 	ret
 
+_pmm_init_low_memory:
+	push ebp
+	mov ebp, esp
+
+	mov eax, [stBootInfo.low_mem]
+	push eax
+	xor eax, eax
+	push eax
+	mov eax, szMsgPmmFreeRange
+	call klog
+	add esp, 8
+
+	; clear bitmap
+	push edi
+	xor eax, eax
+	mov ecx, 8
+	mov edi, au32PmmLowMemBitmap
+	rep stosd
+	
+	mov edi, au32PmmLowMemBitmap
+	xor eax, eax
+	xor ecx, ecx
+@@:
+	add eax, PAGE_SIZE
+	cmp eax, [stBootInfo.low_mem]
+	jg @f
+	mov ebx, 1
+	shl ebx, cl
+	or [edi], ebx
+	inc ecx
+	cmp ecx, 32
+	jb @b
+	xor ecx, ecx
+	add edi, 4
+	jmp @b
+
+@@:
+	pop edi
+
+	leave
+	ret
+
+;;; MARK: public functions
+
 	;; Function: pmm_alloc
 	;; 
 	;; In:
@@ -64,7 +162,18 @@ _pmm_init_region:
 	;;
 	;; Out:
 	;;    EAX - first page physical address, 0 on error
+	;;
 pmm_alloc:
+	mov eax, [pPmmFreeListHead]
+	or eax, eax
+	jnz @f
+	mov edx, ENOMEM
+	ret	; no memory left :'(
+@@:
+	call _pmm_map_temp_page
+
+	call _pmm_unmap_temp_page
+
 	ret
 
 	;; Function: pmm_alloc_page
@@ -84,33 +193,47 @@ pmm_alloc_page:
 pmm_free:
 	ret
 
-	;; Function: _pmm_init_region
-	;;
-	;; Add new memory region to the linked list.
-	;;
-	;; In:
-	;;    EAX - Start
-	;;    EDX - End
-	;;
-
 	;; Function: pmm_init
 	;; 
 	;; Out:
 	;;    EAX - return -1 on error
 pmm_init:
-	mov eax, szMsgMmInit
+	mov eax, szMsgPmmInit
 	call klog
 
-	mov eax, kend
+	call _pmm_init_low_memory
+
+if CONFIG_TRACE_PMM
+	mov byte [cga_color], CGA_COLOR_FG_BLUE
+	push dword [au32PmmLowMemBitmap + 28]
+	push dword [au32PmmLowMemBitmap + 24]
+	push dword [au32PmmLowMemBitmap + 20]
+	push dword [au32PmmLowMemBitmap + 16]
+	push dword [au32PmmLowMemBitmap + 12]
+	push dword [au32PmmLowMemBitmap + 8]
+	push dword [au32PmmLowMemBitmap + 4]
+	push dword [au32PmmLowMemBitmap]
+
+	mov eax, szTracePmmBitmap
+
+	TRACE
+
+	add esp, 32
+
+end if
+
+	mov eax, kend - KERNEL_VIRT_BASE
 	PAGE_ALIGN_UP eax
 
 	mov edx, 0x400000
 	sub edx, eax
+
 	jle @f
 	cmp edx, PAGE_SIZE
 	jle @f
 
 	mov edx, 0x400000
+
 	call _pmm_init_region
 
 @@:
@@ -122,10 +245,19 @@ pmm_init:
 	xor eax, eax ; TODO: check if enough memory and so on
 	ret
 
+;;; MARK: variables
+
 	;; Variable: pPMMFreeListHead
 	;; Hold first free list entry physical address
-pPMMFreeListHead dd 0
+pPmmFreeListHead dd 0
+
+au32PmmLowMemBitmap rd 8
 
 szMsgPmmInit      db "PMM: initialize", 0
 szMsgPmmFreeRange db "PMM: add free memory region %x - %x", 0
 szErrorNoMemLeft  db "Error(PMM): no free memory left", 0
+if CONFIG_TRACE_PMM
+szTracePmmBitmap db "Trace(PMM): low memory bitmap", CR, LF, \
+	"    %x", CR, LF, "    %x", CR, LF, "    %x", CR, LF, "    %x", CR, LF, \
+	"    %x", CR, LF, "    %x", CR, LF, "    %x", CR, LF, "    %x", 0
+end if
diff --git a/kernel/mm/vm.inc b/kernel/mm/vmm.inc
similarity index 100%
rename from kernel/mm/vm.inc
rename to kernel/mm/vmm.inc
diff --git a/kernel/sys/errno.inc b/kernel/sys/errno.inc
index 14de0c2..0bd3d8d 100644
--- a/kernel/sys/errno.inc
+++ b/kernel/sys/errno.inc
@@ -1,2 +1,13 @@
-ENXIO  = 6 
+	;; File: errno.inc
+
+	;; Constant: ENODEV
+	;; No such device.
 ENODEV = 19
+
+	;; Constant: ENOMEM
+	;; Not enough space.
+ENOMEM = 20
+
+	;; Constant: ENXIO
+	;; No such device or address.
+ENXIO  = 6