aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/Makefile9
-rw-r--r--src/kernel/core/kmain.c209
-rw-r--r--src/kernel/core/sys.c3
-rw-r--r--src/rules.make7
-rw-r--r--src/tests/Makefile2
l---------src/tests/ktests/breakpoint/Makefile1
-rw-r--r--src/tests/ktests/breakpoint/test.c13
l---------src/tests/ktests/cmdline/Makefile1
-rw-r--r--src/tests/ktests/cmdline/test.c24
l---------src/tests/ktests/hashtbl1/Makefile1
-rw-r--r--src/tests/ktests/hashtbl1/test.c41
l---------src/tests/ktests/hashtbl2/Makefile1
-rw-r--r--src/tests/ktests/hashtbl2/test.c42
l---------src/tests/ktests/kmalloc/Makefile1
-rw-r--r--src/tests/ktests/kmalloc/test.c32
l---------src/tests/ktests/region1/Makefile1
-rw-r--r--src/tests/ktests/region1/test.c36
l---------src/tests/ktests/region2/Makefile1
-rw-r--r--src/tests/ktests/region2/test.c34
-rw-r--r--src/tests/ktests/rules.make17
-rwxr-xr-xsrc/tests/ktests/run_qemu_test.sh12
-rwxr-xr-xsrc/tests/run_tests.sh13
-rw-r--r--src/tests/slab_test/Makefile5
-rw-r--r--src/tests/slab_test/slab_test.c (renamed from src/tests/slab_test.c)0
24 files changed, 307 insertions, 199 deletions
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index a8e1c65..cbd6a96 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -1,5 +1,5 @@
-OBJ = core/loader.o core/kmain.o core/dbglog.o core/sys.o \
+OBJ = core/loader.o core/dbglog.o core/sys.o \
core/gdt.o core/idt.o core/interrupt.o core/context_switch.o core/thread.o \
core/frame.o core/paging.o core/region.o core/kmalloc.o \
user/vfs.o user/nullfs.o user/process.o user/elf.o user/syscall.o
@@ -10,6 +10,11 @@ CFLAGS = -I ./include -I ../common/include
LDFLAGS = -T linker.ld -Xlinker -Map=kernel.map
-OUT = kernel.bin
+OUT = kernel.lib
include ../rules.make
+
+kernel.bin: kernel.lib core/kmain.o
+ $(LD) $(LDFLAGS) -o $@ $^
+
+all: $(OUT) kernel.bin
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index ce3f536..2e8991e 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -20,9 +20,21 @@
#include <syscall.h>
#include <slab_alloc.h>
-#include <hashtbl.h>
#include <string.h>
+// ===== FOR TESTS =====
+#define TEST_PLACEHOLDER_AFTER_IDT
+#define TEST_PLACEHOLDER_AFTER_REGION
+#define TEST_PLACEHOLDER_AFTER_KMALLOC
+#define TEST_PLACEHOLDER_AFTER_TASKING
+#define TEST_PLACEHOLDER_AFTER_DEVFS
+#ifdef IS_A_TEST
+#define BEGIN_TEST(n) dbg_printf("(BEGIN-TEST %s)\n", n);
+#define TEST_OK { dbg_printf("(TEST-OK)\n"); asm volatile("cli; hlt"); }
+#include <test.c>
+#endif
+// ===== / FOR TESTS ====
+
extern const void k_end_addr; // defined in linker script : 0xC0000000 plus kernel stuff
void breakpoint_handler(registers_t *regs) {
@@ -31,186 +43,6 @@ void breakpoint_handler(registers_t *regs) {
BOCHS_BREAKPOINT;
}
-void test_breakpoint() {
- dbg_printf("(BEGIN-TEST 'breakpoint-test)\n");
- asm volatile("int $0x3"); // test breakpoint
- dbg_printf("(TEST-OK)\n");
-}
-
-void test_region_1() {
- dbg_printf("(BEGIN-TEST 'region-test-1)\n");
- void* p = region_alloc(0x1000, "Test region", 0);
- dbg_printf("Allocated one-page region: 0x%p\n", p);
- dbg_print_region_info();
- void* q = region_alloc(0x1000, "Test region", 0);
- dbg_printf("Allocated one-page region: 0x%p\n", q);
- dbg_print_region_info();
- void* r = region_alloc(0x2000, "Test region", 0);
- dbg_printf("Allocated two-page region: 0x%p\n", r);
- dbg_print_region_info();
- void* s = region_alloc(0x10000, "Test region", 0);
- dbg_printf("Allocated 16-page region: 0x%p\n", s);
- dbg_print_region_info();
- region_free(p);
- dbg_printf("Freed region 0x%p\n", p);
- dbg_print_region_info();
- region_free(q);
- dbg_printf("Freed region 0x%p\n", q);
- dbg_print_region_info();
- region_free(r);
- dbg_printf("Freed region 0x%p\n", r);
- dbg_print_region_info();
- region_free(s);
- dbg_printf("Freed region 0x%p\n", s);
- dbg_print_region_info();
-
- dbg_printf("(TEST-OK)\n");
-}
-
-void test_region_2() {
- // allocate a big region and try to write into it
- dbg_printf("(BEGIN-TEST 'region-test-2)\n");
- const size_t n = 200;
- void* p0 = region_alloc(n * PAGE_SIZE, "Test big region", default_allocator_pf_handler);
- for (size_t i = 0; i < n; i++) {
- uint32_t *x = (uint32_t*)(p0 + i * PAGE_SIZE);
- x[0] = 12;
- x[1] = (i * 20422) % 122;
- }
- // unmap memory
- for (size_t i = 0; i < n; i++) {
- void* p = p0 + i * PAGE_SIZE;
- uint32_t *x = (uint32_t*)p;
- ASSERT(x[1] == (i * 20422) % 122);
-
- uint32_t f = pd_get_frame(p);
- ASSERT(f != 0);
- pd_unmap_page(p);
- ASSERT(pd_get_frame(p) == 0);
-
- frame_free(f, 1);
- }
- region_free(p0);
-
- dbg_printf("(TEST-OK)\n");
-}
-
-void kmalloc_test(void* kernel_data_end) {
- dbg_printf("(BEGIN-TEST 'kmalloc-test)\n");
- // Test kmalloc !
- dbg_print_region_info();
- const int m = 200;
- uint16_t** ptr = malloc(m * sizeof(uint32_t));
- for (int i = 0; i < m; i++) {
- size_t s = 1 << ((i * 7) % 11 + 2);
- ptr[i] = (uint16_t*)malloc(s);
- ASSERT((void*)ptr[i] >= kernel_data_end && (size_t)ptr[i] < 0xFFC00000);
- *ptr[i] = ((i * 211) % 1024);
- }
- dbg_printf("Fully allocated.\n");
- dbg_print_region_info();
- for (int i = 0; i < m; i++) {
- for (int j = i; j < m; j++) {
- ASSERT(*ptr[j] == (j * 211) % 1024);
- }
- free(ptr[i]);
- }
- free(ptr);
- dbg_printf("Kmalloc test OK.\n");
- dbg_print_region_info();
-
- dbg_printf("(TEST-OK)\n");
-}
-
-void test_hashtbl_1() {
- dbg_printf("(BEGIN-TEST 'test-hashtbl-1)\n");
- // hashtable test
- hashtbl_t *ht = create_hashtbl(str_key_eq_fun, str_hash_fun, 0);
- ASSERT(ht != 0);
-
- ASSERT(hashtbl_add(ht, "test1", "STRTEST1"));
- ASSERT(hashtbl_add(ht, "test2", "STRTEST2"));
- ASSERT(hashtbl_find(ht, "test1") != 0 &&
- strcmp(hashtbl_find(ht, "test1"), "STRTEST1") == 0);
- ASSERT(hashtbl_find(ht, "test2") != 0 &&
- strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
- ASSERT(hashtbl_find(ht, "test") == 0);
-
- ASSERT(hashtbl_add(ht, "test", "Forever alone"));
- ASSERT(hashtbl_find(ht, "test1") != 0 &&
- strcmp(hashtbl_find(ht, "test1"), "STRTEST1") == 0);
- ASSERT(hashtbl_find(ht, "test2") != 0 &&
- strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
- ASSERT(hashtbl_find(ht, "test") != 0 &&
- strcmp(hashtbl_find(ht, "test"), "Forever alone") == 0);
-
- hashtbl_remove(ht, "test1");
- ASSERT(hashtbl_find(ht, "test1") == 0);
- ASSERT(hashtbl_find(ht, "test2") != 0 &&
- strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
- ASSERT(hashtbl_find(ht, "test") != 0 &&
- strcmp(hashtbl_find(ht, "test"), "Forever alone") == 0);
-
- delete_hashtbl(ht);
-
- dbg_printf("(TEST-OK)\n");
-}
-
-void test_hashtbl_2() {
- dbg_printf("(BEGIN-TEST 'test-hashtbl-2)\n");
-
- hashtbl_t *ht = create_hashtbl(id_key_eq_fun, id_hash_fun, 0);
- ASSERT(ht != 0);
-
- ASSERT(hashtbl_add(ht, (void*)12, "TESTSTR12"));
- ASSERT(hashtbl_add(ht, (void*)777, "TESTSTR777"));
-
- ASSERT(hashtbl_find(ht, (void*)12) != 0 &&
- strcmp(hashtbl_find(ht, (void*)12), "TESTSTR12") == 0);
- ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
- strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
- ASSERT(hashtbl_find(ht, (void*)144) == 0);
-
- ASSERT(hashtbl_add(ht, (void*)144, "Forever alone"));
-
- ASSERT(hashtbl_find(ht, (void*)12) != 0 &&
- strcmp(hashtbl_find(ht, (void*)12), "TESTSTR12") == 0);
- ASSERT(hashtbl_find(ht, (void*)144) != 0 &&
- strcmp(hashtbl_find(ht, (void*)144), "Forever alone") == 0);
- ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
- strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
-
- hashtbl_remove(ht, (void*)12);
- ASSERT(hashtbl_find(ht, (void*)12) == 0);
- ASSERT(hashtbl_find(ht, (void*)144) != 0 &&
- strcmp(hashtbl_find(ht, (void*)144), "Forever alone") == 0);
- ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
- strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
-
- delete_hashtbl(ht);
-
- dbg_printf("(TEST-OK)\n");
-}
-
-void test_cmdline(multiboot_info_t *mbd, fs_t *devfs) {
- dbg_printf("(BEGIN-TEST 'test-cmdline)\n");
-
- fs_handle_t *f = fs_open(devfs, "/cmdline", FM_READ);
- ASSERT(f != 0);
-
- char buf[256];
- size_t l = file_read(f, 0, 255, buf);
- ASSERT(l > 0);
- buf[l] = 0;
-
- unref_file(f);
- dbg_printf("Command line as in /cmdline file: '%s'.\n", buf);
-
- ASSERT(strcmp(buf, (char*)mbd->cmdline) == 0);
-
- dbg_printf("(TEST-OK)\n");
-}
-
void kernel_init_stage2(void* data);
void kmain(multiboot_info_t *mbd, int32_t mb_magic) {
// used for allocation of data structures before malloc is set up
@@ -249,7 +81,7 @@ void kmain(multiboot_info_t *mbd, int32_t mb_magic) {
idt_init(); dbg_printf("IDT set up.\n");
idt_set_ex_handler(EX_BREAKPOINT, breakpoint_handler);
- test_breakpoint();
+ TEST_PLACEHOLDER_AFTER_IDT;
size_t total_ram = ((mbd->mem_upper + mbd->mem_lower) * 1024);
dbg_printf("Total ram: %d Kb\n", total_ram / 1024);
@@ -262,14 +94,12 @@ void kmain(multiboot_info_t *mbd, int32_t mb_magic) {
paging_setup(kernel_data_end);
dbg_printf("Paging seems to be working!\n");
- BOCHS_BREAKPOINT;
-
region_allocator_init(kernel_data_end);
- test_region_1();
- test_region_2();
+
+ TEST_PLACEHOLDER_AFTER_REGION;
kmalloc_setup();
- kmalloc_test(kernel_data_end);
+ TEST_PLACEHOLDER_AFTER_KMALLOC;
setup_syscalls();
@@ -286,8 +116,7 @@ void kernel_init_stage2(void* data) {
dbg_print_region_info();
dbg_print_frame_stats();
- test_hashtbl_1();
- test_hashtbl_2();
+ TEST_PLACEHOLDER_AFTER_TASKING;
// Create devfs
register_nullfs_driver();
@@ -336,7 +165,7 @@ void kernel_init_stage2(void* data) {
len, false, FM_READ | FM_MMAP));
}
- test_cmdline(mbd, devfs);
+ TEST_PLACEHOLDER_AFTER_DEVFS;
fs_handle_t *init_bin = fs_open(devfs, "/mod/init.bin", FM_READ | FM_MMAP);
if (init_bin == 0) PANIC("No init.bin module provided!");
diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c
index 2b77463..b1e69ad 100644
--- a/src/kernel/core/sys.c
+++ b/src/kernel/core/sys.c
@@ -11,6 +11,9 @@ static void panic_do(const char* type, const char *msg, const char* file, int li
dbg_printf("| System halted -_-'\n");
dbg_printf("\\---------------------------------------------------------/");
BOCHS_BREAKPOINT;
+#ifdef IS_A_TEST
+ dbg_printf("(TEST-FAIL)\n");
+#endif
asm volatile("hlt");
}
diff --git a/src/rules.make b/src/rules.make
index 6c02313..9f4e8ce 100644
--- a/src/rules.make
+++ b/src/rules.make
@@ -12,11 +12,8 @@ LDFLAGS += -ffreestanding -O2 -nostdlib -lgcc
all: $(OUT)
-%.bin: $(OBJ)
- $(LD) $(LDFLAGS) -o $@ $^ $(LIB)
-
-%.lib: $(OBJ)
- $(LD) $(LDFLAGS) -r -o $@ $^ $(LIB)
+$(OUT): $(OBJ) $(LIB)
+ OUT=$(OUT); $(LD) $(LDFLAGS) `if [ $${OUT##*.} = lib ]; then echo -r; fi` -o $@ $^
%.o: %.s
$(AS) $(ASFLAGS) -o $@ $<
diff --git a/src/tests/Makefile b/src/tests/Makefile
deleted file mode 100644
index 4a21edf..0000000
--- a/src/tests/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-slab_test.bin: slab_test.c ../include/slab_alloc.h ../lib/slab_alloc.c
- gcc -m32 -o $@ -std=c99 -I ../include slab_test.c ../lib/slab_alloc.c
diff --git a/src/tests/ktests/breakpoint/Makefile b/src/tests/ktests/breakpoint/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/breakpoint/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/breakpoint/test.c b/src/tests/ktests/breakpoint/test.c
new file mode 100644
index 0000000..cd577e0
--- /dev/null
+++ b/src/tests/ktests/breakpoint/test.c
@@ -0,0 +1,13 @@
+
+void test_breakpoint() {
+ BEGIN_TEST("breakpoint-test");
+
+ asm volatile("int $0x3"); // test breakpoint
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_IDT
+#define TEST_PLACEHOLDER_AFTER_IDT { test_breakpoint(); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/cmdline/Makefile b/src/tests/ktests/cmdline/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/cmdline/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/cmdline/test.c b/src/tests/ktests/cmdline/test.c
new file mode 100644
index 0000000..a6d0a4c
--- /dev/null
+++ b/src/tests/ktests/cmdline/test.c
@@ -0,0 +1,24 @@
+
+void test_cmdline(multiboot_info_t *mbd, fs_t *devfs) {
+ BEGIN_TEST("test-cmdline");
+
+ fs_handle_t *f = fs_open(devfs, "/cmdline", FM_READ);
+ ASSERT(f != 0);
+
+ char buf[256];
+ size_t l = file_read(f, 0, 255, buf);
+ ASSERT(l > 0);
+ buf[l] = 0;
+
+ unref_file(f);
+ dbg_printf("Command line as in /cmdline file: '%s'.\n", buf);
+
+ ASSERT(strcmp(buf, (char*)mbd->cmdline) == 0);
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_DEVFS
+#define TEST_PLACEHOLDER_AFTER_DEVFS { test_cmdline(mbd, devfs); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/hashtbl1/Makefile b/src/tests/ktests/hashtbl1/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/hashtbl1/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/hashtbl1/test.c b/src/tests/ktests/hashtbl1/test.c
new file mode 100644
index 0000000..993718c
--- /dev/null
+++ b/src/tests/ktests/hashtbl1/test.c
@@ -0,0 +1,41 @@
+#include <hashtbl.h>
+
+void test_hashtbl_1() {
+ BEGIN_TEST("test-hashtbl-1");
+
+ // hashtable test
+ hashtbl_t *ht = create_hashtbl(str_key_eq_fun, str_hash_fun, 0);
+ ASSERT(ht != 0);
+
+ ASSERT(hashtbl_add(ht, "test1", "STRTEST1"));
+ ASSERT(hashtbl_add(ht, "test2", "STRTEST2"));
+ ASSERT(hashtbl_find(ht, "test1") != 0 &&
+ strcmp(hashtbl_find(ht, "test1"), "STRTEST1") == 0);
+ ASSERT(hashtbl_find(ht, "test2") != 0 &&
+ strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
+ ASSERT(hashtbl_find(ht, "test") == 0);
+
+ ASSERT(hashtbl_add(ht, "test", "Forever alone"));
+ ASSERT(hashtbl_find(ht, "test1") != 0 &&
+ strcmp(hashtbl_find(ht, "test1"), "STRTEST1") == 0);
+ ASSERT(hashtbl_find(ht, "test2") != 0 &&
+ strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
+ ASSERT(hashtbl_find(ht, "test") != 0 &&
+ strcmp(hashtbl_find(ht, "test"), "Forever alone") == 0);
+
+ hashtbl_remove(ht, "test1");
+ ASSERT(hashtbl_find(ht, "test1") == 0);
+ ASSERT(hashtbl_find(ht, "test2") != 0 &&
+ strcmp(hashtbl_find(ht, "test2"), "STRTEST2") == 0);
+ ASSERT(hashtbl_find(ht, "test") != 0 &&
+ strcmp(hashtbl_find(ht, "test"), "Forever alone") == 0);
+
+ delete_hashtbl(ht);
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_TASKING
+#define TEST_PLACEHOLDER_AFTER_TASKING { test_hashtbl_1(); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/hashtbl2/Makefile b/src/tests/ktests/hashtbl2/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/hashtbl2/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/hashtbl2/test.c b/src/tests/ktests/hashtbl2/test.c
new file mode 100644
index 0000000..2441e79
--- /dev/null
+++ b/src/tests/ktests/hashtbl2/test.c
@@ -0,0 +1,42 @@
+#include <hashtbl.h>
+
+void test_hashtbl_2() {
+ BEGIN_TEST("test-hashtbl-2");
+
+ hashtbl_t *ht = create_hashtbl(id_key_eq_fun, id_hash_fun, 0);
+ ASSERT(ht != 0);
+
+ ASSERT(hashtbl_add(ht, (void*)12, "TESTSTR12"));
+ ASSERT(hashtbl_add(ht, (void*)777, "TESTSTR777"));
+
+ ASSERT(hashtbl_find(ht, (void*)12) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)12), "TESTSTR12") == 0);
+ ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
+ ASSERT(hashtbl_find(ht, (void*)144) == 0);
+
+ ASSERT(hashtbl_add(ht, (void*)144, "Forever alone"));
+
+ ASSERT(hashtbl_find(ht, (void*)12) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)12), "TESTSTR12") == 0);
+ ASSERT(hashtbl_find(ht, (void*)144) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)144), "Forever alone") == 0);
+ ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
+
+ hashtbl_remove(ht, (void*)12);
+ ASSERT(hashtbl_find(ht, (void*)12) == 0);
+ ASSERT(hashtbl_find(ht, (void*)144) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)144), "Forever alone") == 0);
+ ASSERT(hashtbl_find(ht, (void*)777) != 0 &&
+ strcmp(hashtbl_find(ht, (void*)777), "TESTSTR777") == 0);
+
+ delete_hashtbl(ht);
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_TASKING
+#define TEST_PLACEHOLDER_AFTER_TASKING { test_hashtbl_2(); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/kmalloc/Makefile b/src/tests/ktests/kmalloc/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/kmalloc/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/kmalloc/test.c b/src/tests/ktests/kmalloc/test.c
new file mode 100644
index 0000000..2b5dc6d
--- /dev/null
+++ b/src/tests/ktests/kmalloc/test.c
@@ -0,0 +1,32 @@
+
+void kmalloc_test(void* kernel_data_end) {
+ BEGIN_TEST("kmalloc-test");
+
+ dbg_print_region_info();
+ const int m = 200;
+ uint16_t** ptr = malloc(m * sizeof(uint32_t));
+ for (int i = 0; i < m; i++) {
+ size_t s = 1 << ((i * 7) % 11 + 2);
+ ptr[i] = (uint16_t*)malloc(s);
+ ASSERT((void*)ptr[i] >= kernel_data_end && (size_t)ptr[i] < 0xFFC00000);
+ *ptr[i] = ((i * 211) % 1024);
+ }
+ dbg_printf("Fully allocated.\n");
+ dbg_print_region_info();
+ for (int i = 0; i < m; i++) {
+ for (int j = i; j < m; j++) {
+ ASSERT(*ptr[j] == (j * 211) % 1024);
+ }
+ free(ptr[i]);
+ }
+ free(ptr);
+ dbg_printf("Kmalloc test OK.\n");
+ dbg_print_region_info();
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_KMALLOC
+#define TEST_PLACEHOLDER_AFTER_KMALLOC { kmalloc_test(kernel_data_end); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/region1/Makefile b/src/tests/ktests/region1/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/region1/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/region1/test.c b/src/tests/ktests/region1/test.c
new file mode 100644
index 0000000..1a42638
--- /dev/null
+++ b/src/tests/ktests/region1/test.c
@@ -0,0 +1,36 @@
+
+void test_region_1() {
+ BEGIN_TEST("region-test-1");
+
+ void* p = region_alloc(0x1000, "Test region", 0);
+ dbg_printf("Allocated one-page region: 0x%p\n", p);
+ dbg_print_region_info();
+ void* q = region_alloc(0x1000, "Test region", 0);
+ dbg_printf("Allocated one-page region: 0x%p\n", q);
+ dbg_print_region_info();
+ void* r = region_alloc(0x2000, "Test region", 0);
+ dbg_printf("Allocated two-page region: 0x%p\n", r);
+ dbg_print_region_info();
+ void* s = region_alloc(0x10000, "Test region", 0);
+ dbg_printf("Allocated 16-page region: 0x%p\n", s);
+ dbg_print_region_info();
+ region_free(p);
+ dbg_printf("Freed region 0x%p\n", p);
+ dbg_print_region_info();
+ region_free(q);
+ dbg_printf("Freed region 0x%p\n", q);
+ dbg_print_region_info();
+ region_free(r);
+ dbg_printf("Freed region 0x%p\n", r);
+ dbg_print_region_info();
+ region_free(s);
+ dbg_printf("Freed region 0x%p\n", s);
+ dbg_print_region_info();
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_REGION
+#define TEST_PLACEHOLDER_AFTER_REGION { test_region_1(); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/region2/Makefile b/src/tests/ktests/region2/Makefile
new file mode 120000
index 0000000..4630a7c
--- /dev/null
+++ b/src/tests/ktests/region2/Makefile
@@ -0,0 +1 @@
+../rules.make \ No newline at end of file
diff --git a/src/tests/ktests/region2/test.c b/src/tests/ktests/region2/test.c
new file mode 100644
index 0000000..24908b0
--- /dev/null
+++ b/src/tests/ktests/region2/test.c
@@ -0,0 +1,34 @@
+
+void test_region_2() {
+ BEGIN_TEST("region-test-2");
+
+ // allocate a big region and try to write into it
+ const size_t n = 200;
+ void* p0 = region_alloc(n * PAGE_SIZE, "Test big region", default_allocator_pf_handler);
+ for (size_t i = 0; i < n; i++) {
+ uint32_t *x = (uint32_t*)(p0 + i * PAGE_SIZE);
+ x[0] = 12;
+ x[1] = (i * 20422) % 122;
+ }
+ // unmap memory
+ for (size_t i = 0; i < n; i++) {
+ void* p = p0 + i * PAGE_SIZE;
+ uint32_t *x = (uint32_t*)p;
+ ASSERT(x[1] == (i * 20422) % 122);
+
+ uint32_t f = pd_get_frame(p);
+ ASSERT(f != 0);
+ pd_unmap_page(p);
+ ASSERT(pd_get_frame(p) == 0);
+
+ frame_free(f, 1);
+ }
+ region_free(p0);
+
+ TEST_OK;
+}
+
+#undef TEST_PLACEHOLDER_AFTER_REGION
+#define TEST_PLACEHOLDER_AFTER_REGION { test_region_2(); }
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/tests/ktests/rules.make b/src/tests/ktests/rules.make
new file mode 100644
index 0000000..f31ab89
--- /dev/null
+++ b/src/tests/ktests/rules.make
@@ -0,0 +1,17 @@
+LIB = ../../../kernel/kernel.lib
+
+OBJ = kmain.o
+
+CFLAGS = -I . -I ../../../common/include -I ../../../kernel/include -DIS_A_TEST
+LDFLAGS = -T ../../../kernel/linker.ld -Xlinker -Map=test_kernel.map
+
+OUT = test_kernel.bin
+
+include ../../../rules.make
+
+kmain.o: ../../../kernel/core/kmain.c test.c
+ $(CC) -c $< -o $@ $(CFLAGS)
+
+run_test: all
+ ../run_qemu_test.sh
+
diff --git a/src/tests/ktests/run_qemu_test.sh b/src/tests/ktests/run_qemu_test.sh
new file mode 100755
index 0000000..93c7320
--- /dev/null
+++ b/src/tests/ktests/run_qemu_test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+(qemu-system-i386 -kernel test_kernel.bin -serial stdio -m 16 -display none & echo $! >&3) 3>pid \
+ | tee >(grep -m 1 "TEST-" >result; kill -INT `cat pid`) \
+
+RESULT=`cat result`
+
+rm result
+rm pid
+
+if [ $RESULT != '(TEST-OK)' ]; then exit 1; fi
+
diff --git a/src/tests/run_tests.sh b/src/tests/run_tests.sh
new file mode 100755
index 0000000..bd23801
--- /dev/null
+++ b/src/tests/run_tests.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+cd `dirname $0`
+
+for FILE in */Makefile */*/Makefile; do
+ TEST=`dirname $FILE`
+ echo -n "Running test $TEST ... "
+ if make -C $TEST run_test > $TEST/test.log 2>&1; then
+ echo OK
+ else
+ echo FAIL
+ fi
+done
diff --git a/src/tests/slab_test/Makefile b/src/tests/slab_test/Makefile
new file mode 100644
index 0000000..4cda341
--- /dev/null
+++ b/src/tests/slab_test/Makefile
@@ -0,0 +1,5 @@
+slab_test.bin: slab_test.c ../../common/include/slab_alloc.h ../../common/libkogata/slab_alloc.c
+ gcc -m32 -o $@ -std=c99 -I ../../common/include slab_test.c ../../common/libkogata/slab_alloc.c
+
+run_test: slab_test.bin
+ ./slab_test.bin
diff --git a/src/tests/slab_test.c b/src/tests/slab_test/slab_test.c
index 747c785..747c785 100644
--- a/src/tests/slab_test.c
+++ b/src/tests/slab_test/slab_test.c