slab: Add an arena pointer to the interface
[akaros.git] / kern / src / ktest / pb_ktests.c
index a0f72c6..3be4a78 100644 (file)
@@ -34,6 +34,7 @@
 #include <kmalloc.h>
 #include <hashtable.h>
 #include <radix.h>
+#include <circular_buffer.h>
 #include <monitor.h>
 #include <kthread.h>
 #include <schedule.h>
 
 KTEST_SUITE("POSTBOOT")
 
-#define l1 (available_caches.l1)
-#define l2 (available_caches.l2)
-#define l3 (available_caches.l3)
-
 #ifdef CONFIG_X86
 
 // TODO: Do test if possible inside this function, and add assertions.
@@ -109,8 +106,9 @@ bool test_pic_reception(void)
        pic_unmask_irq(0, 0);
        cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
        cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
-       unmask_lapic_lvt(LAPIC_LVT_LINT0);
-       cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
+       unmask_lapic_lvt(MSR_LAPIC_LVT_LINT0);
+       printk("Core %d's LINT0: 0x%08x\n", core_id(),
+              apicrget(MSR_LAPIC_LVT_TIMER));
        enable_irq();
        while(1);
 
@@ -119,136 +117,6 @@ bool test_pic_reception(void)
 
 #endif // CONFIG_X86
 
-// TODO: Add assertions. Possibly the way to go is to extract relevant info 
-//       from cache properties and make assertions on the colored pages lists 
-//       based on those.
-// TODO: The test was commented out. Figure out why was it like that and fix it.
-bool test_page_coloring(void) 
-{
-       /*
-       //Print the different cache properties of our machine
-       print_cache_properties("L1", l1);
-       cprintf("\n");
-       print_cache_properties("L2", l2);
-       cprintf("\n");
-       print_cache_properties("L3", l3);
-       cprintf("\n");
-
-       //Print some stats about our memory
-       cprintf("Max Address: %llu\n", MAX_VADDR);
-       cprintf("Num Pages: %u\n", npages);
-
-       //Declare a local variable for allocating pages 
-       page_t* page;
-
-       cprintf("Contents of the page free list:\n");
-       for(int i=0; i<llc_cache->num_colors; i++) {
-               cprintf("  COLOR %d:\n", i);
-               LIST_FOREACH(page, &colored_page_free_list[i], pg_link) {
-                       cprintf("    Page: %d\n", page2ppn(page));
-               }
-       }
-
-       //Run through and allocate all pages through l1_page_alloc
-       cprintf("Allocating from L1 page colors:\n");
-       for(int i=0; i<get_cache_num_page_colors(l1); i++) {
-               cprintf("  COLOR %d:\n", i);
-               while(colored_page_alloc(l1, &page, i) != -ENOMEM)
-                       cprintf("    Page: %d\n", page2ppn(page));
-       }
-
-       //Put all the pages back by reinitializing
-       page_init();
-       
-       //Run through and allocate all pages through l2_page_alloc
-       cprintf("Allocating from L2 page colors:\n");
-       for(int i=0; i<get_cache_num_page_colors(l2); i++) {
-               cprintf("  COLOR %d:\n", i);
-               while(colored_page_alloc(l2, &page, i) != -ENOMEM)
-                       cprintf("    Page: %d\n", page2ppn(page));
-       }
-
-       //Put all the pages back by reinitializing
-       page_init();
-       
-       //Run through and allocate all pages through l3_page_alloc
-       cprintf("Allocating from L3 page colors:\n");
-       for(int i=0; i<get_cache_num_page_colors(l3); i++) {
-               cprintf("  COLOR %d:\n", i);
-               while(colored_page_alloc(l3, &page, i) != -ENOMEM)
-                       cprintf("    Page: %d\n", page2ppn(page));
-       }
-       
-       //Put all the pages back by reinitializing
-       page_init();
-       
-       //Run through and allocate all pages through page_alloc
-       cprintf("Allocating from global allocator:\n");
-       while(upage_alloc(&page) != -ENOMEM)
-               cprintf("    Page: %d\n", page2ppn(page));
-       
-       if(colored_page_alloc(l2, &page, 0) != -ENOMEM)
-               cprintf("Should not get here, all pages should already be gone!\n");
-       cprintf("All pages gone for sure...\n");
-       
-       //Now lets put a few pages back using page_free..
-       cprintf("Reinserting pages via page_free and reallocating them...\n");
-       page_free(&pages[0]);
-       page_free(&pages[15]);
-       page_free(&pages[7]);
-       page_free(&pages[6]);
-       page_free(&pages[4]);
-
-       while(upage_alloc(&page) != -ENOMEM)
-               cprintf("Page: %d\n", page2ppn(page));  
-       
-       page_init();
-       */
-       return true;
-}
-
-// TODO: Add assertions.
-bool test_color_alloc(void) {
-       size_t checkpoint = 0;
-       uint8_t* colors_map = kmalloc(BYTES_FOR_BITMASK(llc_cache->num_colors), 0);
-       cache_color_alloc(l2, colors_map);
-       cache_color_alloc(l3, colors_map);
-       cache_color_alloc(l3, colors_map);
-       cache_color_alloc(l2, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(l2, colors_map);
-       cache_color_free(llc_cache, colors_map);
-       cache_color_free(llc_cache, colors_map);
-
-print_cache_colors:
-       printk("L1 free colors, tot colors: %d\n", l1->num_colors);
-       PRINT_BITMASK(l1->free_colors_map, l1->num_colors);
-       printk("L2 free colors, tot colors: %d\n", l2->num_colors);
-       PRINT_BITMASK(l2->free_colors_map, l2->num_colors);
-       printk("L3 free colors, tot colors: %d\n", l3->num_colors);
-       PRINT_BITMASK(l3->free_colors_map, l3->num_colors);
-       printk("Process allocated colors\n");
-       PRINT_BITMASK(colors_map, llc_cache->num_colors);
-       printk("test_color_alloc() complete!\n");
-
-       return true;
-}
-
 barrier_t test_cpu_array;
 
 // TODO: Add assertions, try to do everything from within this same function.
@@ -262,7 +130,7 @@ bool test_barrier(void)
        return true;
 }
 
-// TODO: Maybe remove all the printing statements and instead use the 
+// TODO: Maybe remove all the printing statements and instead use the
 //       KT_ASSERT_M macro to include a message on assertions.
 bool test_interrupts_irqsave(void)
 {
@@ -383,11 +251,11 @@ bool test_bitmasks(void)
        KT_ASSERT_M("Bit 11 should be 0", 0 == GET_BITMASK_BIT(mask, 11));
        FILL_BITMASK(mask, masksize);
 //     PRINT_BITMASK(mask, masksize);
-       KT_ASSERT_M("Bitmask should not be clear after calling FILL_BITMASK", 
+       KT_ASSERT_M("Bitmask should not be clear after calling FILL_BITMASK",
                    0 == BITMASK_IS_CLEAR(mask,masksize));
        CLR_BITMASK(mask, masksize);
 //     PRINT_BITMASK(mask, masksize);
-       KT_ASSERT_M("Bitmask should be clear after calling CLR_BITMASK", 
+       KT_ASSERT_M("Bitmask should be clear after calling CLR_BITMASK",
                    1 == BITMASK_IS_CLEAR(mask,masksize));
        return true;
 }
@@ -570,7 +438,6 @@ bool test_lapic_status_bit(void)
        // KT_ASSERT_M("IPIs received should be 0", (0 == a));
        for(int i = 0; i < NUM_IPI; i++) {
                send_ipi(7, I_TESTING);
-               lapic_wait_to_send();
        }
        // need to wait a bit to let those IPIs get there
        udelay(5000000);
@@ -654,7 +521,7 @@ bool test_circ_buffer(void)
                FOR_CIRC_BUFFER(i, 5, j)
                        printk("Starting with current = %d, each value = %d\n", i, j);
        }
-       
+
        return true;
 }
 
@@ -697,7 +564,7 @@ bool test_kernel_messages(void)
                                    KMSG_ROUTINE);
        }
        udelay(5000000);
-       
+
        return true;
 }
 #endif // CONFIG_X86
@@ -707,7 +574,8 @@ static void test_single_cache(int iters, size_t size, int align, int flags,
 {
        struct kmem_cache *test_cache;
        void *objects[iters];
-       test_cache = kmem_cache_create("test_cache", size, align, flags, ctor, dtor);
+       test_cache = kmem_cache_create("test_cache", size, align, flags,
+                                      NULL, ctor, dtor);
        printk("Testing Kmem Cache:\n");
        print_kmem_cache(test_cache);
        for (int i = 0; i < iters; i++) {
@@ -744,7 +612,7 @@ bool test_slab(void)
 bool test_kmalloc(void)
 {
        printk("Testing Kmalloc\n");
-       void *bufs[NUM_KMALLOC_CACHES + 1];     
+       void *bufs[NUM_KMALLOC_CACHES + 1];
        size_t size;
        for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
                size = (KMALLOC_SMALLEST << i) - sizeof(struct kmalloc_tag);
@@ -779,58 +647,58 @@ bool test_hashtable(void)
        struct test *v = &tstruct[0];
 
        h = create_hashtable(32, __generic_hash, __generic_eq);
-       
+
        // test inserting one item, then finding it again
-       KT_ASSERT_M("It should be possible to insert items to a hashtable", 
+       KT_ASSERT_M("It should be possible to insert items to a hashtable",
                    hashtable_insert(h, (void*)k, v));
        v = NULL;
-       KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
+       KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable",
                    (v = hashtable_search(h, (void*)k)));
 
-       KT_ASSERT_M("The extracted element should be the same we inserted", 
+       KT_ASSERT_M("The extracted element should be the same we inserted",
                    (v == &tstruct[0]));
 
        v = NULL;
 
-       KT_ASSERT_M("It should be possible to remove an existing element", 
+       KT_ASSERT_M("It should be possible to remove an existing element",
                    (v = hashtable_remove(h, (void*)k)));
 
-       KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
+       KT_ASSERT_M("An element should not remain in a hashtable after deletion",
                    !(v = hashtable_search(h, (void*)k)));
 
        /* Testing a bunch of items, insert, search, and removal */
        for (int i = 0; i < 10; i++) {
                k = i; // vary the key, we don't do KEY collisions
-               KT_ASSERT_M("It should be possible to insert elements to a hashtable", 
+               KT_ASSERT_M("It should be possible to insert elements to a hashtable",
                            (hashtable_insert(h, (void*)k, &tstruct[i])));
        }
        // read out the 10 items
        for (int i = 0; i < 10; i++) {
                k = i;
-               KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
+               KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable",
                            (v = hashtable_search(h, (void*)k)));
-               KT_ASSERT_M("The extracted element should be the same we inserted", 
+               KT_ASSERT_M("The extracted element should be the same we inserted",
                            (v == &tstruct[i]));
        }
 
-       KT_ASSERT_M("The total count of number of elements should be 10", 
+       KT_ASSERT_M("The total count of number of elements should be 10",
                    (10 == hashtable_count(h)));
 
        // remove the 10 items
        for (int i = 0; i < 10; i++) {
                k = i;
-               KT_ASSERT_M("It should be possible to remove an existing element", 
+               KT_ASSERT_M("It should be possible to remove an existing element",
                            (v = hashtable_remove(h, (void*)k)));
 
        }
        // make sure they are all gone
        for (int i = 0; i < 10; i++) {
                k = i;
-               KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
+               KT_ASSERT_M("An element should not remain in a hashtable after deletion",
                            !(v = hashtable_search(h, (void*)k)));
        }
 
-       KT_ASSERT_M("The hashtable should be empty", 
+       KT_ASSERT_M("The hashtable should be empty",
                    (0 == hashtable_count(h)));
 
        hashtable_destroy(h);
@@ -842,36 +710,36 @@ bool test_hashtable(void)
        for (int i = 0; i < 10; i++) {
                k = i; // vary the key, we don't do KEY collisions
 
-               KT_ASSERT_M("It should be possible to insert elements to a hashtable", 
+               KT_ASSERT_M("It should be possible to insert elements to a hashtable",
                            (hashtable_insert(h, (void*)k, &tstruct[i])));
        }
        // read out the 10 items
        for (int i = 0; i < 10; i++) {
                k = i;
-               KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
+               KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable",
                            (v = hashtable_search(h, (void*)k)));
-               KT_ASSERT_M("The extracted element should be the same we inserted", 
+               KT_ASSERT_M("The extracted element should be the same we inserted",
                            (v == &tstruct[i]));
        }
 
-       KT_ASSERT_M("The total count of number of elements should be 10", 
+       KT_ASSERT_M("The total count of number of elements should be 10",
                    (10 == hashtable_count(h)));
 
        // remove the 10 items
        for (int i = 0; i < 10; i++) {
                k = i;
-               KT_ASSERT_M("It should be possible to remove an existing element", 
+               KT_ASSERT_M("It should be possible to remove an existing element",
                            (v = hashtable_remove(h, (void*)k)));
        }
        // make sure they are all gone
        for (int i = 0; i < 10; i++) {
                k = i;
 
-               KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
+               KT_ASSERT_M("An element should not remain in a hashtable after deletion",
                            !(v = hashtable_search(h, (void*)k)));
        }
 
-       KT_ASSERT_M("The hashtable should be empty", 
+       KT_ASSERT_M("The hashtable should be empty",
                    (0 == hashtable_count(h)));
 
        hashtable_destroy(h);
@@ -879,6 +747,83 @@ bool test_hashtable(void)
        return true;
 }
 
+bool test_circular_buffer(void)
+{
+       static const size_t cbsize = 4096;
+       struct circular_buffer cb;
+       char *bigbuf;
+       size_t csize, off, cnum, mxsize;
+       char buf[256];
+
+       KT_ASSERT_M("Failed to build the circular buffer",
+                               circular_buffer_init(&cb, cbsize, NULL));
+
+       for (size_t i = 0; i < 8 * cbsize; i++) {
+               size_t len = snprintf(buf, sizeof(buf), "%lu\n", i);
+
+               KT_ASSERT_M("Circular buffer write failed",
+                                       circular_buffer_write(&cb, buf, len) == len);
+       }
+       cnum = off = 0;
+       while ((csize = circular_buffer_read(&cb, buf, sizeof(buf), off)) != 0) {
+               char *top = buf + csize;
+               char *ptr = buf;
+               char *pnl;
+
+               while ((pnl = memchr(ptr, '\n', top - ptr)) != NULL) {
+                       size_t num;
+
+                       *pnl = 0;
+                       num = strtoul(ptr, NULL, 10);
+                       KT_ASSERT_M("Numbers should be ascending", num >= cnum);
+                       cnum = num;
+                       ptr = pnl + 1;
+               }
+
+               off += ptr - buf;
+       }
+
+       for (size_t i = 0; i < (cbsize / sizeof(buf) + 1); i++) {
+               memset(buf, (int) i, sizeof(buf));
+
+               KT_ASSERT_M("Circular buffer write failed",
+                                       circular_buffer_write(&cb, buf,
+                                                                                 sizeof(buf)) == sizeof(buf));
+       }
+       cnum = off = 0;
+       while ((csize = circular_buffer_read(&cb, buf, sizeof(buf), off)) != 0) {
+               size_t num = buf[0];
+
+               KT_ASSERT_M("Invalid record read size", csize == sizeof(buf));
+
+               if (off != 0)
+                       KT_ASSERT_M("Invalid record sequence number",
+                                               num == ((cnum + 1) % 256));
+               cnum = num;
+               off += csize;
+       }
+
+       bigbuf = kzmalloc(cbsize, MEM_WAIT);
+       KT_ASSERT(bigbuf != NULL);
+
+       mxsize = circular_buffer_max_write_size(&cb);
+       KT_ASSERT_M("Circular buffer max write failed",
+                               circular_buffer_write(&cb, bigbuf, mxsize) == mxsize);
+
+       memset(bigbuf, 17, cbsize);
+       csize = circular_buffer_read(&cb, bigbuf, mxsize, 0);
+       KT_ASSERT_M("Invalid max record read size", csize == mxsize);
+
+       for (size_t i = 0; i < csize; i++)
+               KT_ASSERT_M("Invalid max record value", bigbuf[i] == 0);
+
+       kfree(bigbuf);
+
+       circular_buffer_destroy(&cb);
+
+       return TRUE;
+}
+
 /* Ghetto test, only tests one prod or consumer at a time */
 // TODO: Un-guetto test, add assertions.
 bool test_bcq(void)
@@ -889,26 +834,26 @@ bool test_bcq(void)
                int y;
        };
        struct my_struct in_struct, out_struct;
-       
+
        DEFINE_BCQ_TYPES(test, struct my_struct, 16);
        struct test_bcq t_bcq;
        bcq_init(&t_bcq, struct my_struct, 16);
-       
+
        in_struct.x = 4;
        in_struct.y = 5;
        out_struct.x = 1;
        out_struct.y = 2;
-       
+
        bcq_enqueue(&t_bcq, &in_struct, 16, 5);
        bcq_dequeue(&t_bcq, &out_struct, 16);
        printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
-       
+
        /* Tests the BCQ a bit more, esp with overflow */
        #define NR_ELEM_A_BCQ 8 /* NOTE: this must be a power of 2! */
        DEFINE_BCQ_TYPES(my, int, NR_ELEM_A_BCQ);
        struct my_bcq a_bcq;
        bcq_init(&a_bcq, int, NR_ELEM_A_BCQ);
-       
+
        int y = 2;
        int output[100];
        int retval[100];
@@ -933,27 +878,27 @@ bool test_bcq(void)
                printk("enqueued: %d, had retval %d \n", y, retval[i]);
        }
        //print_a_bcq(&a_bcq);
-       
+
        /* Try to dequeue more than we put in */
        for (int i = 0; i < 15; i++) {
                retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
                printk("dequeued: %d with retval %d\n", output[i], retval[i]);
        }
        //print_a_bcq(&a_bcq);
-       
+
        /* Put in some it should be able to take */
        for (int i = 0; i < 3; i++) {
                y = i;
                retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
                printk("enqueued: %d, had retval %d \n", y, retval[i]);
        }
-       
+
        /* Take those, and then a couple extra */
        for (int i = 0; i < 5; i++) {
                retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
                printk("dequeued: %d with retval %d\n", output[i], retval[i]);
        }
-       
+
        /* Try some one-for-one */
        for (int i = 0; i < 5; i++) {
                y = i;
@@ -980,7 +925,8 @@ bool test_ucq(void)
        void send_msgs(struct alarm_waiter *waiter)
        {
                struct timer_chain *tchain;
-               struct proc *old_proc, *p = waiter->data;
+               struct proc *p = waiter->data;
+               uintptr_t old_proc;
                struct ucq *ucq = (struct ucq*)USTACKTOP;
                struct event_msg msg;
 
@@ -1043,8 +989,8 @@ bool test_ucq(void)
        /* Just spawn the program */
        struct file *program;
        program = do_file_open("/bin/ucq", O_READ, 0);
-       
-       KT_ASSERT_M("We should be able to find /bin/ucq", 
+
+       KT_ASSERT_M("We should be able to find /bin/ucq",
                    program);
 
        struct proc *p = proc_create(program, NULL, NULL);
@@ -1058,7 +1004,7 @@ bool test_ucq(void)
         * around that are runnable */
        run_scheduler();
        smp_idle();
-       
+
        KT_ASSERT_M("We should never return from schedule",
                    false);
 
@@ -1078,8 +1024,8 @@ bool test_vm_regions(void)
        TAILQ_INIT(&p->vm_regions);
 
        struct vmr_summary {
-               uintptr_t base; 
-               uintptr_t end; 
+               uintptr_t base;
+               uintptr_t end;
        };
        int check_vmrs(struct proc *p, struct vmr_summary *results, int len, int n)
        {
@@ -1115,7 +1061,7 @@ bool test_vm_regions(void)
        results[0].end = 0x4000;
        check_vmrs(p, results, 1, n++);
        /* Grow it poorly */
-       KT_ASSERT_M("It should pass bad grow test", 
+       KT_ASSERT_M("It should pass bad grow test",
                    (-1 == grow_vmr(vmrs[0], 0x3000)));
        check_vmrs(p, results, 1, n++);
        /* Make another right next to it */
@@ -1124,7 +1070,7 @@ bool test_vm_regions(void)
        results[1].end = 0x5000;
        check_vmrs(p, results, 2, n++);
        /* try to grow through it */
-       KT_ASSERT_M("It should pass bad grow test", 
+       KT_ASSERT_M("It should pass bad grow test",
                    (-1 == grow_vmr(vmrs[0], 0x5000)));
        check_vmrs(p, results, 2, n++);
        /* Merge them */
@@ -1138,7 +1084,7 @@ bool test_vm_regions(void)
        results[1].end = 0xa000;
        check_vmrs(p, results, 2, n++);
        /* try to merge unmergables (just testing ranges) */
-       KT_ASSERT_M("It should pass bad merge test", 
+       KT_ASSERT_M("It should pass bad merge test",
                    (-1 == merge_vmr(vmrs[0], vmrs[1])));
        check_vmrs(p, results, 2, n++);
        vmrs[2] = split_vmr(vmrs[1], 0x8000);
@@ -1156,13 +1102,13 @@ bool test_vm_regions(void)
        results[1].base = 0x8000;
        results[1].end = 0x9000;
        check_vmrs(p, results, 2, n++); /* 10 */
-       KT_ASSERT_M("We should be able to find the right vmr", 
+       KT_ASSERT_M("We should be able to find the right vmr",
                    (vmrs[2] == find_vmr(p, 0x8500)));
-       KT_ASSERT_M("We should be able to find the right vmr", 
+       KT_ASSERT_M("We should be able to find the right vmr",
                    (vmrs[2] == find_first_vmr(p, 0x8500)));
-       KT_ASSERT_M("We should be able to find the right vmr", 
+       KT_ASSERT_M("We should be able to find the right vmr",
                    (vmrs[2] == find_first_vmr(p, 0x7500)));
-       KT_ASSERT_M("We shouldn't be able to find a vmr", 
+       KT_ASSERT_M("We shouldn't be able to find a vmr",
                    !(find_first_vmr(p, 0x9500)));
        /* grow up to another */
        grow_vmr(vmrs[0], 0x8000);
@@ -1171,7 +1117,7 @@ bool test_vm_regions(void)
        vmrs[0]->vm_prot = 88;
        vmrs[2]->vm_prot = 77;
        /* should be unmergeable due to perms */
-       KT_ASSERT_M("It should pass bad merge test", 
+       KT_ASSERT_M("It should pass bad merge test",
                    -1 == merge_vmr(vmrs[0], vmrs[2]));
        check_vmrs(p, results, 2, n++);
        /* should merge now */
@@ -1217,13 +1163,13 @@ bool test_radix_tree(void)
        struct radix_tree *tree = &real_tree;
        void *retval;
 
-       KT_ASSERT_M("It should be possible to insert at 0", 
+       KT_ASSERT_M("It should be possible to insert at 0",
                    !radix_insert(tree, 0, (void*)0xdeadbeef, 0));
        radix_delete(tree, 0);
-       KT_ASSERT_M("It should be possible to re-insert at 0", 
+       KT_ASSERT_M("It should be possible to re-insert at 0",
                    !radix_insert(tree, 0, (void*)0xdeadbeef, 0));
 
-       KT_ASSERT_M("It should be possible to insert first", 
+       KT_ASSERT_M("It should be possible to insert first",
                    !radix_insert(tree, 3, (void*)0xdeadbeef, 0));
        radix_insert(tree, 4, (void*)0x04040404, 0);
        KT_ASSERT((void*)0xdeadbeef == radix_lookup(tree, 3));
@@ -1234,13 +1180,13 @@ bool test_radix_tree(void)
                        print_radix_tree(tree);
                        monitor(0);
                }
-       KT_ASSERT_M("It should be possible to insert a two-tier", 
+       KT_ASSERT_M("It should be possible to insert a two-tier",
                    !radix_insert(tree, 65, (void*)0xcafebabe, 0));
-       KT_ASSERT_M("It should not be possible to reinsert", 
+       KT_ASSERT_M("It should not be possible to reinsert",
                    radix_insert(tree, 4, (void*)0x03030303, 0));
-       KT_ASSERT_M("It should be possible to insert a two-tier boundary", 
+       KT_ASSERT_M("It should be possible to insert a two-tier boundary",
                    !radix_insert(tree, 4095, (void*)0x4095, 0));
-       KT_ASSERT_M("It should be possible to insert a three-tier", 
+       KT_ASSERT_M("It should be possible to insert a three-tier",
                    !radix_insert(tree, 4096, (void*)0x4096, 0));
        //print_radix_tree(tree);
        radix_delete(tree, 65);
@@ -1258,26 +1204,26 @@ bool test_radix_tree(void)
 bool test_random_fs(void)
 {
        int retval = do_symlink("/dir1/sym", "/bin/hello", S_IRWXU);
-       KT_ASSERT_M("symlink1 should be created successfully", 
+       KT_ASSERT_M("symlink1 should be created successfully",
                    (!retval));
        retval = do_symlink("/symdir", "/dir1/dir1-1", S_IRWXU);
-       KT_ASSERT_M("symlink1 should be created successfully", 
+       KT_ASSERT_M("symlink1 should be created successfully",
                    (!retval));
        retval = do_symlink("/dir1/test.txt", "/dir2/test2.txt", S_IRWXU);
-       KT_ASSERT_M("symlink2 should be created successfully", 
+       KT_ASSERT_M("symlink2 should be created successfully",
                    (!retval));
        retval = do_symlink("/dir1/dir1-1/up", "../../", S_IRWXU);
-       KT_ASSERT_M("symlink3 should be created successfully", 
+       KT_ASSERT_M("symlink3 should be created successfully",
                    (!retval));
        retval = do_symlink("/bin/hello-sym", "hello", S_IRWXU);
-       KT_ASSERT_M("symlink4 should be created successfully", 
+       KT_ASSERT_M("symlink4 should be created successfully",
                    (!retval));
 
        struct dentry *dentry;
        struct nameidata nd_r = {0}, *nd = &nd_r;
        retval = path_lookup("/dir1/sym", 0, nd);
-       KT_ASSERT_M("symlink lookup should work for an existing symlink", 
-                   (!retval)); 
+       KT_ASSERT_M("symlink lookup should work for an existing symlink",
+                   (!retval));
        char *symname = nd->dentry->d_inode->i_op->readlink(nd->dentry);
        printk("Pathlookup got %s (sym)\n", nd->dentry->d_name.name);
        if (!symname)
@@ -1288,33 +1234,33 @@ bool test_random_fs(void)
        /* try with follow */
        memset(nd, 0, sizeof(struct nameidata));
        retval = path_lookup("/dir1/sym", LOOKUP_FOLLOW, nd);
-       
-       KT_ASSERT_M("symlink lookup should work for an existing symlink", 
+
+       KT_ASSERT_M("symlink lookup should work for an existing symlink",
                    (!retval));
        printk("Pathlookup got %s (hello)\n", nd->dentry->d_name.name);
        path_release(nd);
-       
+
        /* try with a directory */
        memset(nd, 0, sizeof(struct nameidata));
        retval = path_lookup("/symdir/f1-1.txt", 0, nd);
-       KT_ASSERT_M("symlink lookup should work for an existing symlink", 
+       KT_ASSERT_M("symlink lookup should work for an existing symlink",
                    (!retval));
        printk("Pathlookup got %s (f1-1.txt)\n", nd->dentry->d_name.name);
        path_release(nd);
-       
+
        /* try with a rel path */
        printk("Try with a rel path\n");
        memset(nd, 0, sizeof(struct nameidata));
        retval = path_lookup("/symdir/up/hello.txt", 0, nd);
-       KT_ASSERT_M("symlink lookup should work for an existing symlink", 
+       KT_ASSERT_M("symlink lookup should work for an existing symlink",
                    (!retval));
        printk("Pathlookup got %s (hello.txt)\n", nd->dentry->d_name.name);
        path_release(nd);
-       
+
        printk("Try for an ELOOP\n");
        memset(nd, 0, sizeof(struct nameidata));
        retval = path_lookup("/symdir/up/symdir/up/symdir/up/symdir/up/hello.txt", 0, nd);
-       KT_ASSERT_M("symlink lookup should fail for a non existing symlink", 
+       KT_ASSERT_M("symlink lookup should fail for a non existing symlink",
                    (retval));
        path_release(nd);
 
@@ -1381,7 +1327,7 @@ bool test_kref(void)
 {
        struct kref local_kref;
        bool done = FALSE;
-       
+
        kref_init(&local_kref, fake_release, 1);
        send_kernel_message(2, __test_kref_2, (long)&local_kref, (long)&done, 0,
                            KMSG_ROUTINE);
@@ -1436,9 +1382,9 @@ bool test_atomics(void)
                do {
                        old_num = atomic_read(&actual_num);
                        /* First time, try to fail */
-                       if (attempt == 0) 
+                       if (attempt == 0)
                                old_num++;
-                       attempt++;      
+                       attempt++;
                } while (!atomic_cas(&actual_num, old_num, old_num + 10));
                if (atomic_read(&actual_num) != init_val + 10) {
                        return false;
@@ -1605,19 +1551,19 @@ bool test_cv(void)
 bool test_memset(void)
 {
        #define ARR_SZ 256
-       
+
        void print_array(char *c, size_t len)
        {
                for (int i = 0; i < len; i++)
                        printk("%04d: %02x\n", i, *c++);
        }
-       
+
        bool check_array(char *c, char x, size_t len)
        {
                for (int i = 0; i < len; i++) {
                        #define ASSRT_SIZE 64
                        char *assrt_msg = (char*) kmalloc(ASSRT_SIZE, 0);
-                       snprintf(assrt_msg, ASSRT_SIZE, 
+                       snprintf(assrt_msg, ASSRT_SIZE,
                                     "Char %d is %c (%02x), should be %c (%02x)", i, *c, *c,
                                     x, x);
                        KT_ASSERT_M(assrt_msg, (*c == x));
@@ -1625,7 +1571,7 @@ bool test_memset(void)
                }
                return true;
        }
-       
+
        bool run_check(char *arr, int ch, size_t len)
        {
                char *c = arr;
@@ -1655,7 +1601,7 @@ void __attribute__((noinline)) __longjmp_wrapper(struct jmpbuf* jb)
        printk("Starting: %s\n", __FUNCTION__);
        longjmp(jb, 1);
        // Should never get here
-       printk("Exiting: %s\n", __FUNCTION__); 
+       printk("Exiting: %s\n", __FUNCTION__);
 }
 
 // TODO: Add assertions.
@@ -1813,7 +1759,7 @@ bool test_rwlock(void)
                /* signal to allow core 0 to finish */
                atomic_dec(&rwlock_counter);
        }
-               
+
        /* send 4 messages to each non core 0 */
        atomic_init(&rwlock_counter, (num_cores - 1) * 4);
        for (int i = 1; i < num_cores; i++)
@@ -2012,7 +1958,7 @@ bool test_u16pool(void)
        int numalloc;
        KT_ASSERT(id);
 
-       t = kzmalloc(sizeof(int) * (AMT + 1), KMALLOC_WAIT);
+       t = kzmalloc(sizeof(int) * (AMT + 1), MEM_WAIT);
        for (x = 0; x < 1024; x++) {
                KT_ASSERT_M("Should be empty", id->tos == 0);
                for (i = 0; i < id->size; i++) {
@@ -2089,87 +2035,121 @@ bool test_u16pool(void)
        return FALSE;
 }
 
-bool test_uaccess(void)
-{
-       char buf[128] = { 0 };
-       char buf2[128] = { 0 };
-       struct proc *tmp = switch_to(NULL);
-
-       KT_ASSERT_M("Copy to user (u8) to not mapped UDATA address should fail",
-                               copy_to_user((void *) UDATA, buf, 1) == -EFAULT);
-       KT_ASSERT_M("Copy to user (u16) to not mapped UDATA address should fail",
-                               copy_to_user((void *) UDATA, buf, 2) == -EFAULT);
-       KT_ASSERT_M("Copy to user (u32) to not mapped UDATA address should fail",
-                               copy_to_user((void *) UDATA, buf, 4) == -EFAULT);
-       KT_ASSERT_M("Copy to user (u64) to not mapped UDATA address should fail",
-                               copy_to_user((void *) UDATA, buf, 8) == -EFAULT);
-       KT_ASSERT_M("Copy to user (mem) to not mapped UDATA address should fail",
-                               copy_to_user((void *) UDATA, buf, sizeof(buf)) == -EFAULT);
-
-       KT_ASSERT_M("Copy from user (u8) to not mapped UDATA address should fail",
-                               copy_from_user(buf, (const void *) UDATA, 1) == -EFAULT);
-       KT_ASSERT_M("Copy from user (u16) to not mapped UDATA address should fail",
-                               copy_from_user(buf, (const void *) UDATA, 2) == -EFAULT);
-       KT_ASSERT_M("Copy from user (u32) to not mapped UDATA address should fail",
-                               copy_from_user(buf, (const void *) UDATA, 4) == -EFAULT);
-       KT_ASSERT_M("Copy from user (u64) to not mapped UDATA address should fail",
-                               copy_from_user(buf, (const void *) UDATA, 8) == -EFAULT);
-       KT_ASSERT_M("Copy from user (mem) to not mapped UDATA address should fail",
-                               copy_from_user(buf, (const void *) UDATA, sizeof(buf)) ==
-                               -EFAULT);
+static bool uaccess_mapped(void *addr, char *buf, char *buf2)
+{
+       KT_ASSERT_M(
+               "Copy to user (u8) to mapped address should not fail",
+               copy_to_user(addr, buf, 1) == 0);
+       KT_ASSERT_M(
+               "Copy to user (u16) to mapped address should not fail",
+               copy_to_user(addr, buf, 2) == 0);
+       KT_ASSERT_M(
+               "Copy to user (u32) to mapped address should not fail",
+               copy_to_user(addr, buf, 4) == 0);
+       KT_ASSERT_M(
+               "Copy to user (u64) to mapped address should not fail",
+               copy_to_user(addr, buf, 8) == 0);
+       KT_ASSERT_M(
+               "Copy to user (mem) to mapped address should not fail",
+               copy_to_user(addr, buf, sizeof(buf)) == 0);
+
+       KT_ASSERT_M(
+               "Copy from user (u8) to mapped address should not fail",
+               copy_from_user(buf, addr, 1) == 0);
+       KT_ASSERT_M(
+               "Copy from user (u16) to mapped address should not fail",
+               copy_from_user(buf, addr, 2) == 0);
+       KT_ASSERT_M(
+               "Copy from user (u32) to mapped address should not fail",
+               copy_from_user(buf, addr, 4) == 0);
+       KT_ASSERT_M(
+               "Copy from user (u64) to mapped address should not fail",
+               copy_from_user(buf, addr, 8) == 0);
+       KT_ASSERT_M(
+               "Copy from user (mem) to mapped address should not fail",
+               copy_from_user(buf, addr, sizeof(buf)) == 0);
+
+       KT_ASSERT_M(
+               "String copy to user to mapped address should not fail",
+               strcpy_to_user(current, addr, "Akaros") == 0);
+       KT_ASSERT_M(
+               "String copy from user to mapped address should not fail",
+               strcpy_from_user(current, buf, addr) == 0);
+       KT_ASSERT_M("The copied string content should be matching",
+                               memcmp(buf, "Akaros", 7) == 0);
+
+       return TRUE;
+}
+
+static bool uaccess_unmapped(void *addr, char *buf, char *buf2)
+{
+       KT_ASSERT_M("Copy to user (u8) to not mapped address should fail",
+                               copy_to_user(addr, buf, 1) == -EFAULT);
+       KT_ASSERT_M("Copy to user (u16) to not mapped address should fail",
+                               copy_to_user(addr, buf, 2) == -EFAULT);
+       KT_ASSERT_M("Copy to user (u32) to not mapped address should fail",
+                               copy_to_user(addr, buf, 4) == -EFAULT);
+       KT_ASSERT_M("Copy to user (u64) to not mapped address should fail",
+                               copy_to_user(addr, buf, 8) == -EFAULT);
+       KT_ASSERT_M("Copy to user (mem) to not mapped address should fail",
+                               copy_to_user(addr, buf, sizeof(buf)) == -EFAULT);
+
+       KT_ASSERT_M("Copy from user (u8) to not mapped address should fail",
+                               copy_from_user(buf, addr, 1) == -EFAULT);
+       KT_ASSERT_M("Copy from user (u16) to not mapped address should fail",
+                               copy_from_user(buf, addr, 2) == -EFAULT);
+       KT_ASSERT_M("Copy from user (u32) to not mapped address should fail",
+                               copy_from_user(buf, addr, 4) == -EFAULT);
+       KT_ASSERT_M("Copy from user (u64) to not mapped address should fail",
+                               copy_from_user(buf, addr, 8) == -EFAULT);
+       KT_ASSERT_M("Copy from user (mem) to not mapped address should fail",
+                               copy_from_user(buf, addr, sizeof(buf)) == -EFAULT);
+
+       KT_ASSERT_M(
+               "String copy to user to not mapped address should fail",
+               strcpy_to_user(NULL, addr, "Akaros") == -EFAULT);
+       KT_ASSERT_M(
+               "String copy from user to not mapped address should fail",
+               strcpy_from_user(NULL, buf, addr) == -EFAULT);
 
        KT_ASSERT_M("Copy from user with kernel side source pointer should fail",
                                copy_from_user(buf, buf2, sizeof(buf)) == -EFAULT);
        KT_ASSERT_M("Copy to user with kernel side source pointer should fail",
                                copy_to_user(buf, buf2, sizeof(buf)) == -EFAULT);
 
-       switch_back(NULL, tmp);
-
-       if (tmp != NULL) {
-               static const size_t mmap_size = 4096;
-               void *addr = mmap(tmp, 0, mmap_size, PROT_READ | PROT_WRITE,
-                                 MAP_PRIVATE, -1, 0);
-
-               KT_ASSERT_M("Mmap failed", addr != MAP_FAILED);
-
-               KT_ASSERT_M(
-                       "Copy to user (u8) to mapped address should not fail",
-                       copy_to_user(addr, buf, 1) == 0);
-               KT_ASSERT_M(
-                       "Copy to user (u16) to mapped address should not fail",
-                       copy_to_user(addr, buf, 2) == 0);
-               KT_ASSERT_M(
-                       "Copy to user (u32) to mapped address should not fail",
-                       copy_to_user(addr, buf, 4) == 0);
-               KT_ASSERT_M(
-                       "Copy to user (u64) to mapped address should not fail",
-                       copy_to_user(addr, buf, 8) == 0);
-               KT_ASSERT_M(
-                       "Copy to user (mem) to mapped address should not fail",
-                       copy_to_user(addr, buf, sizeof(buf)) == 0);
-
-               KT_ASSERT_M(
-                       "Copy from user (u8) to mapped address should not fail",
-                       copy_from_user(buf, addr, 1) == 0);
-               KT_ASSERT_M(
-                       "Copy from user (u16) to mapped address should not fail",
-                       copy_from_user(buf, addr, 2) == 0);
-               KT_ASSERT_M(
-                       "Copy from user (u32) to mapped address should not fail",
-                       copy_from_user(buf, addr, 4) == 0);
-               KT_ASSERT_M(
-                       "Copy from user (u64) to mapped address should not fail",
-                       copy_from_user(buf, addr, 8) == 0);
-               KT_ASSERT_M(
-                       "Copy from user (mem) to mapped address should not fail",
-                       copy_from_user(buf, addr, sizeof(buf)) == 0);
-
-               munmap(tmp, (uintptr_t) addr, mmap_size);
-       }
-
        return TRUE;
 }
 
+bool test_uaccess(void)
+{
+       char buf[128] = { 0 };
+       char buf2[128] = { 0 };
+       struct proc *tmp;
+       uintptr_t switch_tmp;
+       int err;
+       static const size_t mmap_size = 4096;
+       void *addr;
+       bool passed = FALSE;
+
+       err = proc_alloc(&tmp, 0, 0);
+       KT_ASSERT_M("Failed to alloc a temp proc", err == 0);
+       /* Tell everyone we're ready in case some ops don't work on PROC_CREATED */
+       __proc_set_state(tmp, PROC_RUNNABLE_S);
+       switch_tmp = switch_to(tmp);
+       addr = mmap(tmp, 0, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, -1, 0);
+       if (addr == MAP_FAILED)
+               goto out;
+       passed = uaccess_mapped(addr, buf, buf2);
+       munmap(tmp, (uintptr_t) addr, mmap_size);
+       if (!passed)
+               goto out;
+       passed = uaccess_unmapped(addr, buf, buf2);
+out:
+       switch_back(tmp, switch_tmp);
+       proc_decref(tmp);
+       return passed;
+}
+
 bool test_sort(void)
 {
        int cmp_longs_asc(const void *p1, const void *p2)
@@ -2285,10 +2265,6 @@ static struct ktest ktests[] = {
        KTEST_REG(circ_buffer,        CONFIG_TEST_circ_buffer),
        KTEST_REG(kernel_messages,    CONFIG_TEST_kernel_messages),
 #endif // CONFIG_X86
-#ifdef CONFIG_PAGE_COLORING
-       KTEST_REG(page_coloring,      CONFIG_TEST_page_coloring),
-       KTEST_REG(color_alloc,        CONFIG_TEST_color_alloc),
-#endif // CONFIG_PAGE_COLORING
        KTEST_REG(barrier,            CONFIG_TEST_barrier),
        KTEST_REG(interrupts_irqsave, CONFIG_TEST_interrupts_irqsave),
        KTEST_REG(bitmasks,           CONFIG_TEST_bitmasks),
@@ -2297,6 +2273,7 @@ static struct ktest ktests[] = {
        KTEST_REG(slab,               CONFIG_TEST_slab),
        KTEST_REG(kmalloc,            CONFIG_TEST_kmalloc),
        KTEST_REG(hashtable,          CONFIG_TEST_hashtable),
+       KTEST_REG(circular_buffer,    CONFIG_TEST_circular_buffer),
        KTEST_REG(bcq,                CONFIG_TEST_bcq),
        KTEST_REG(ucq,                CONFIG_TEST_ucq),
        KTEST_REG(vm_regions,         CONFIG_TEST_vm_regions),