Use a temp process for test_uaccess
[akaros.git] / kern / src / ktest / pb_ktests.c
index ed053b3..a5de1ee 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <arch/mmu.h>
 #include <arch/arch.h>
+#include <arch/uaccess.h>
 #include <bitmask.h>
 #include <smp.h>
 
@@ -24,6 +25,7 @@
 #include <syscall.h>
 #include <time.h>
 #include <kfs.h>
+#include <mm.h>
 #include <multiboot.h>
 #include <pmap.h>
 #include <page_alloc.h>
 #include <kmalloc.h>
 #include <hashtable.h>
 #include <radix.h>
+#include <circular_buffer.h>
 #include <monitor.h>
 #include <kthread.h>
 #include <schedule.h>
 #include <umem.h>
+#include <init.h>
 #include <ucq.h>
 #include <setjmp.h>
+#include <sort.h>
 
 #include <apipe.h>
 #include <rwlock.h>
 #include <rendez.h>
 #include <ktest.h>
+#include <smallidpool.h>
 #include <linker_func.h>
 
 KTEST_SUITE("POSTBOOT")
@@ -112,43 +118,8 @@ bool test_pic_reception(void)
        return true;
 }
 
-// TODO: Add assertions.
-bool test_ioapic_pit_reroute(void) 
-{
-       register_irq(IdtPIC + IrqCLOCK, test_hello_world_handler, NULL,
-                    MKBUS(BusISA, 0, 0, 0));
-#ifdef CONFIG_ENABLE_MPTABLES
-#warning "not routing the irq"
-       //ioapic_route_irq(0, 3);       
-#endif
-
-       cprintf("Starting pit on core 3....\n");
-       udelay(3000000);
-       pit_set_timer(0xFFFE,TIMER_RATEGEN); // totally arbitrary time
-       
-       udelay(3000000);
-#ifdef CONFIG_ENABLE_MPTABLES
-#warning "NOT unrouting the irq"
-       //ioapic_unroute_irq(0);
-#endif
-       udelay(300000);
-       cprintf("Masked pit. Waiting before return...\n");
-       udelay(3000000);
-
-       return true;
-}
-
 #endif // CONFIG_X86
 
-// TODO: Assert printed info follows the standard (or whatever we want to test).
-bool test_print_info(void)
-{
-       cprintf("\nCORE 0 asking all cores to print info:\n");
-       smp_call_function_all(test_print_info_handler, NULL, 0);
-       cprintf("\nDone!\n");
-       return true;
-}
-
 // 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.
@@ -285,7 +256,7 @@ barrier_t test_cpu_array;
 bool test_barrier(void)
 {
        cprintf("Core 0 initializing barrier\n");
-       init_barrier(&test_cpu_array, num_cpus);
+       init_barrier(&test_cpu_array, num_cores);
        cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
        smp_call_function_all(test_barrier_handler, NULL, 0);
 
@@ -422,7 +393,7 @@ bool test_bitmasks(void)
        return true;
 }
 
-checklist_t *RO the_global_list;
+checklist_t *the_global_list;
 
 static void test_checklist_handler(struct hw_trapframe *hw_tf, void *data)
 {
@@ -434,7 +405,7 @@ static void test_checklist_handler(struct hw_trapframe *hw_tf, void *data)
 // TODO: Add assertions
 bool test_checklists(void)
 {
-       INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
+       INIT_CHECKLIST(a_list, MAX_NUM_CORES);
        the_global_list = &a_list;
        printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
        printk("mask\n");
@@ -444,12 +415,12 @@ bool test_checklists(void)
        PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
 
        CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
-       INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CPUS);
-       FILL_BITMASK(a_mask.bits, num_cpus);
+       INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CORES);
+       FILL_BITMASK(a_mask.bits, num_cores);
        //CLR_BITMASK_BIT(a_mask.bits, core_id());
        //SET_BITMASK_BIT(a_mask.bits, 1);
        //printk("New mask (1, 17, 25):\n");
-       printk("Created new mask, filled up to num_cpus\n");
+       printk("Created new mask, filled up to num_cores\n");
        PRINT_BITMASK(a_mask.bits, a_mask.size);
        printk("committing new mask\n");
        commit_checklist_wait(&a_list, &a_mask);
@@ -505,7 +476,7 @@ bool test_smp_call_functions(void)
        smp_call_wait(waiter0);
        printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
        printk("---------------------\n");
-       for(i = 1; i < num_cpus; i++)
+       for(i = 1; i < num_cores; i++)
                smp_call_function_single(i, test_hello_world_handler, NULL, 0);
        printk("\nCore %d: SMP Call Self (wait):\n", me);
        printk("---------------------\n");
@@ -513,7 +484,7 @@ bool test_smp_call_functions(void)
        smp_call_wait(waiter0);
        printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
        printk("---------------------\n");
-       for(i = 1; i < num_cpus; i++)
+       for(i = 1; i < num_cores; i++)
        {
                smp_call_function_single(i, test_hello_world_handler, NULL, &waiter0);
                smp_call_wait(waiter0);
@@ -524,18 +495,18 @@ bool test_smp_call_functions(void)
        smp_call_function_all(test_incrementer_handler, &b, 0);
        smp_call_function_all(test_incrementer_handler, &c, 0);
        // if i can clobber a previous IPI, the interleaving might do it
-       smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
-       smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
-       smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
-       smp_call_function_single(4 % num_cpus, test_incrementer_handler, &a, 0);
-       smp_call_function_single(5 % num_cpus, test_incrementer_handler, &b, 0);
-       smp_call_function_single(6 % num_cpus, test_incrementer_handler, &c, 0);
+       smp_call_function_single(1 % num_cores, test_incrementer_handler, &a, 0);
+       smp_call_function_single(2 % num_cores, test_incrementer_handler, &b, 0);
+       smp_call_function_single(3 % num_cores, test_incrementer_handler, &c, 0);
+       smp_call_function_single(4 % num_cores, test_incrementer_handler, &a, 0);
+       smp_call_function_single(5 % num_cores, test_incrementer_handler, &b, 0);
+       smp_call_function_single(6 % num_cores, test_incrementer_handler, &c, 0);
        smp_call_function_all(test_incrementer_handler, &a, 0);
-       smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
+       smp_call_function_single(3 % num_cores, test_incrementer_handler, &c, 0);
        smp_call_function_all(test_incrementer_handler, &b, 0);
-       smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
+       smp_call_function_single(1 % num_cores, test_incrementer_handler, &a, 0);
        smp_call_function_all(test_incrementer_handler, &c, 0);
-       smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
+       smp_call_function_single(2 % num_cores, test_incrementer_handler, &b, 0);
        // wait, so we're sure the others finish before printing.
        // without this, we could (and did) get 19,18,19, since the B_inc
        // handler didn't finish yet
@@ -628,40 +599,6 @@ void test_hello_world_handler(struct hw_trapframe *hw_tf, void *data)
                trapno, core_id(), hw_tf);
 }
 
-spinlock_t print_info_lock = SPINLOCK_INITIALIZER_IRQSAVE;
-
-void test_print_info_handler(struct hw_trapframe *hw_tf, void *data)
-{
-       uint64_t tsc = read_tsc();
-
-       spin_lock_irqsave(&print_info_lock);
-       cprintf("----------------------------\n");
-       cprintf("This is Core %d\n", core_id());
-       cprintf("Timestamp = %lld\n", tsc);
-#ifdef CONFIG_X86
-       cprintf("Hardware core %d\n", hw_core_id());
-       cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
-       cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x200), read_msr(0x201));
-       cprintf("MTRR Phys1 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x202), read_msr(0x203));
-       cprintf("MTRR Phys2 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x204), read_msr(0x205));
-       cprintf("MTRR Phys3 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x206), read_msr(0x207));
-       cprintf("MTRR Phys4 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x208), read_msr(0x209));
-       cprintf("MTRR Phys5 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x20a), read_msr(0x20b));
-       cprintf("MTRR Phys6 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x20c), read_msr(0x20d));
-       cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
-               read_msr(0x20e), read_msr(0x20f));
-#endif // CONFIG_X86
-       cprintf("----------------------------\n");
-       spin_unlock_irqsave(&print_info_lock);
-}
-
 void test_barrier_handler(struct hw_trapframe *hw_tf, void *data)
 {
        cprintf("Round 1: Core %d\n", core_id());
@@ -943,6 +880,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, KMALLOC_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)
@@ -1106,13 +1120,12 @@ bool test_ucq(void)
        set_alarm(tchain, waiter);
        /* Just spawn the program */
        struct file *program;
-       program = do_file_open("/bin/ucq", 0, 0);
+       program = do_file_open("/bin/ucq", O_READ, 0);
        
        KT_ASSERT_M("We should be able to find /bin/ucq", 
                    program);
 
-       char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
-       struct proc *p = proc_create(program, 0, p_envp);
+       struct proc *p = proc_create(program, NULL, NULL);
        proc_wakeup(p);
        /* instead of getting rid of the reference created in proc_create, we'll put
         * it in the awaiter */
@@ -1406,8 +1419,7 @@ static void __test_up_sem(uint32_t srcid, long a0, long a1, long a2)
 // TODO: Add assertions.
 bool test_kthreads(void)
 {
-       struct semaphore sem;
-       sem_init(&sem, 1);              /* set to 1 to test the unwind */
+       struct semaphore sem = SEMAPHORE_INITIALIZER(sem, 1);
        printk("We're a kthread!  Stacktop is %p.  Testing suspend, etc...\n",
               get_stack_top());
        /* So we have something that will wake us up.  Routine messages won't get
@@ -1599,9 +1611,9 @@ bool test_cv(void)
        printk("test_cv: signal without waiting complete\n");
 
        /* Test 1: single / minimal shit */
-       nr_msgs = num_cpus - 1; /* not using cpu 0 */
+       nr_msgs = num_cores - 1; /* not using cpu 0 */
        atomic_init(&counter, nr_msgs);
-       for (int i = 1; i < num_cpus; i++)
+       for (int i = 1; i < num_cores; i++)
                send_kernel_message(i, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
        udelay(1000000);
        cv_signal(cv);
@@ -1621,7 +1633,7 @@ bool test_cv(void)
        nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
        atomic_init(&counter, nr_msgs);
        for (int i = 0; i < nr_msgs; i++) {
-               int cpu = (i % (num_cpus - 1)) + 1;
+               int cpu = (i % (num_cores - 1)) + 1;
                if (atomic_read(&counter) % 5)
                        send_kernel_message(cpu, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
                else
@@ -1881,8 +1893,8 @@ bool test_rwlock(void)
        }
                
        /* send 4 messages to each non core 0 */
-       atomic_init(&rwlock_counter, (num_cpus - 1) * 4);
-       for (int i = 1; i < num_cpus; i++)
+       atomic_init(&rwlock_counter, (num_cores - 1) * 4);
+       for (int i = 1; i < num_cores; i++)
                for (int j = 0; j < 4; j++)
                        send_kernel_message(i, __test_rwlock, 0, 0, 0, KMSG_ROUTINE);
        while (atomic_read(&rwlock_counter))
@@ -1936,10 +1948,10 @@ bool test_rv(void)
        printk("test_rv: wakeup without sleeping complete\n");
 
        /* Test 1: a few sleepers */
-       nr_msgs = num_cpus - 1; /* not using cpu 0 */
+       nr_msgs = num_cores - 1; /* not using cpu 0 */
        atomic_init(&counter, nr_msgs);
        state = FALSE;
-       for (int i = 1; i < num_cpus; i++)
+       for (int i = 1; i < num_cores; i++)
                send_kernel_message(i, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
        udelay(1000000);
        cmb();
@@ -1957,10 +1969,10 @@ bool test_rv(void)
        nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
        atomic_init(&counter, nr_msgs);
        for (int i = 0; i < nr_msgs; i++) {
-               int cpu = (i % (num_cpus - 1)) + 1;
+               int cpu = (i % (num_cores - 1)) + 1;
                /* timeouts from 0ms ..5000ms (enough that they should wake via cond */
                if (atomic_read(&counter) % 5)
-                       send_kernel_message(cpu, __test_rv_sleeper_timeout, i * 4, 0, 0,
+                       send_kernel_message(cpu, __test_rv_sleeper_timeout, i * 4000, 0, 0,
                                            KMSG_ROUTINE);
                else
                        send_kernel_message(cpu, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
@@ -2016,11 +2028,355 @@ bool test_alarm(void)
        return true;
 }
 
+bool test_kmalloc_incref(void)
+{
+       /* this test is a bit invasive of the kmalloc internals */
+       void *__get_unaligned_orig_buf(void *buf)
+       {
+               int *tag_flags = (int*)(buf - sizeof(int));
+               if ((*tag_flags & KMALLOC_FLAG_MASK) == KMALLOC_TAG_UNALIGN)
+                       return (buf - (*tag_flags >> KMALLOC_ALIGN_SHIFT));
+               else
+                       return 0;
+       }
+
+       bool test_buftag(void *b, struct kmalloc_tag *btag, char *str)
+       {
+               KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 1);
+               kmalloc_incref(b);
+               KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 2);
+               kfree(b);
+               KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 1);
+               kfree(b);
+               /* dangerous read, it's been freed */
+               KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 0);
+               return TRUE;
+       }
+
+       void *b1, *b2, *b2o;
+       struct kmalloc_tag *b1tag, *b2tag;
+
+       /* no realigned case */
+       b1 = kmalloc(55, 0);
+       KT_ASSERT(!__get_unaligned_orig_buf(b1));
+       b1tag = (struct kmalloc_tag*)(b1 - sizeof(struct kmalloc_tag));
+
+       /* realigned case.  alloc'd before b1's test, so we know we get different
+        * buffers. */
+       b2 = kmalloc_align(55, 0, 64);
+       b2o = __get_unaligned_orig_buf(b2);
+       KT_ASSERT(b2o);
+       b2tag = (struct kmalloc_tag*)(b2o - sizeof(struct kmalloc_tag));
+
+       test_buftag(b1, b1tag, "b1, no realign");
+       test_buftag(b2, b2tag, "b2, realigned");
+
+       return TRUE;
+}
+
+/* Some ghetto things:
+ * - ASSERT_M only lets you have a string, not a format string.
+ * - put doesn't return, so we have a "loud" test for that.  alternatively, we
+ *   could have put panic, but then we couldn't test it at all.  and i don't
+ *   particularly want it to have a return value.
+ * - ASSERT_M just blindly returns.  we're leaking memory.
+ */
+bool test_u16pool(void)
+{
+       #define AMT 4096
+       int *t;
+       struct u16_pool *id = create_u16_pool(AMT);
+       int i, x, y;
+       int numalloc;
+       KT_ASSERT(id);
+
+       t = kzmalloc(sizeof(int) * (AMT + 1), KMALLOC_WAIT);
+       for (x = 0; x < 1024; x++) {
+               KT_ASSERT_M("Should be empty", id->tos == 0);
+               for (i = 0; i < id->size; i++) {
+                       int p = get_u16(id);
+                       if (p < 0)
+                               KT_ASSERT_M("Couldn't get enough", 0);
+                       t[i] = p;
+               }
+               numalloc = i;
+               // free them at random. With luck, we don't get too many duplicate
+               // hits.
+               for (y = i = 0; i < numalloc; y++) {
+                       /* could read genrand, but that could be offline */
+                       int f = (uint16_t)read_tsc() % numalloc;
+                       if (!t[f])
+                               continue;
+                       put_u16(id, t[f]);
+                       t[f] = 0;
+                       i++;
+                       /* that's long enough... */
+                       if (y > 2 * id->size)
+                               break;
+               }
+               /* grab the leftovers */
+               for (i = 0; i < id->size; i++) {
+                       if (!t[i])
+                               continue;
+                       put_u16(id, t[i]);
+                       t[i] = 0;
+               }
+               /* all of our previous checks failed to give back 0 */
+               put_u16(id, 0);
+       }
+
+       // pop too many.
+       bool we_broke = FALSE;
+       for (i = 0; i < id->size * 2; i++) {
+               x = get_u16(id);
+               if (x == -1) {
+                       we_broke = TRUE;
+                       break;
+               }
+               t[i] = x;
+       }
+       KT_ASSERT_M("Should have failed to get too many", we_broke);
+
+       numalloc = i;
+
+       printd("Allocated %d items\n", numalloc);
+       for (i = 0; i < numalloc; i++) {
+               put_u16(id, t[i]);
+               t[i] = 0;
+       }
+       KT_ASSERT_M("Should be empty", id->tos == 0);
+
+       printk("Ignore next BAD, testing bad alloc\n");
+       put_u16(id, 25);        // should get an error.
+       for (i = 0; i < id->size; i++) {
+               int v = get_u16(id);
+               if (t[v])
+                       printd("BAD: %d pops twice!\n", v);
+               KT_ASSERT_M("Popped twice!", t[v] == 0);
+               t[v] = 1;
+               //printk("%d,", v);
+       }
+
+       for (i = 1; i < id->size; i++) {
+               if (!t[i])
+                       printd("BAD: %d was not set\n", i);
+               KT_ASSERT_M("Wasn't set!", t[i]);
+       }
+
+       kfree(t);
+       return FALSE;
+}
+
+bool test_uaccess(void)
+{
+       char buf[128] = { 0 };
+       char buf2[128] = { 0 };
+       struct proc *tmp;
+       int err;
+       static const size_t mmap_size = 4096;
+       void *addr;
+
+       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);
+
+       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);
+
+       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);
+
+       munmap(tmp, (uintptr_t) addr, mmap_size);
+
+
+       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);
+
+       proc_decref(tmp);
+       return TRUE;
+}
+
+bool test_sort(void)
+{
+       int cmp_longs_asc(const void *p1, const void *p2)
+       {
+               const long v1 = *(const long *) p1;
+               const long v2 = *(const long *) p2;
+
+               return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0);
+       }
+
+       int cmp_longs_desc(const void *p1, const void *p2)
+       {
+               const long v1 = *(const long *) p1;
+               const long v2 = *(const long *) p2;
+
+               return v1 < v2 ? 1 : (v1 > v2 ? -1 : 0);
+       }
+
+       size_t i;
+       long long_set_1[] = {
+               -9, 11, 0, 23, 123, -99, 3, 11, 23, -999, 872, 17, 21
+       };
+       long long_set_2[] = {
+               31, 77, -1, 2, 0, 64, 11, 19, 69, 111, -89, 17, 21, 44, 77
+       };
+
+       sort(long_set_1, ARRAY_SIZE(long_set_1), sizeof(long), cmp_longs_asc);
+       for (i = 1; i < ARRAY_SIZE(long_set_1); i++)
+               KT_ASSERT(long_set_1[i - 1] <= long_set_1[i]);
+
+       sort(long_set_2, ARRAY_SIZE(long_set_2), sizeof(long), cmp_longs_desc);
+       for (i = 1; i < ARRAY_SIZE(long_set_2); i++)
+               KT_ASSERT(long_set_2[i - 1] >= long_set_2[i]);
+
+       return TRUE;
+}
+
+bool test_cmdline_parse(void)
+{
+       static const char *fake_cmdline =
+               "kernel -root=/foo -simple -num=123 -quoted='abc \\'' -dup=311 "
+               "-dup='akaros' -empty='' -inner=-outer -outer=-inner=xyz";
+       const char *opt;
+       char param[128];
+
+       /* Note that the get_boot_option() API should be passed NULL the first time
+        * it is called, in normal cases, and should be passed the value returned by
+        * previous call to get_boot_option(), in case multiple options with same
+        * name have to be fetched.
+        */
+       opt = get_boot_option(fake_cmdline, "-root", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -root option", opt);
+       KT_ASSERT_M("Invalid -root option value", strcmp(param, "/foo") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-root", NULL, 0);
+       KT_ASSERT_M("Unable to parse -root option when param not provided", opt);
+
+       opt = get_boot_option(fake_cmdline, "-simple", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -simple option", opt);
+       KT_ASSERT_M("Invalid -simple option value", strcmp(param, "") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-num", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -num option", opt);
+       KT_ASSERT_M("Invalid -num option value", strcmp(param, "123") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-quoted", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -quoted option", opt);
+       KT_ASSERT_M("Invalid -quoted option value", strcmp(param, "abc '") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-dup", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -dup option", opt);
+       KT_ASSERT_M("Invalid -dup option first value", strcmp(param, "311") == 0);
+
+       opt = get_boot_option(opt, "-dup", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -dup option", opt);
+       KT_ASSERT_M("Invalid -dup option second value",
+                               strcmp(param, "akaros") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-inner", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -inner option", opt);
+       KT_ASSERT_M("Invalid -inner option value", strcmp(param, "-outer") == 0);
+
+       opt = get_boot_option(opt, "-inner", param, sizeof(param));
+       KT_ASSERT_M("Should not be parsing -inner as value", !opt);
+
+       opt = get_boot_option(fake_cmdline, "-outer", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -outer option", opt);
+       KT_ASSERT_M("Invalid -outer option value",
+                               strcmp(param, "-inner=xyz") == 0);
+
+       opt = get_boot_option(fake_cmdline, "-missing", param, sizeof(param));
+       KT_ASSERT_M("Should not be parsing -missing option", !opt);
+
+       opt = get_boot_option(fake_cmdline, "-inne", NULL, 0);
+       KT_ASSERT_M("Should not be parsing -inne option", !opt);
+
+       opt = get_boot_option(fake_cmdline, "-outera", NULL, 0);
+       KT_ASSERT_M("Should not be parsing -outera option", !opt);
+
+       opt = get_boot_option(fake_cmdline, "-empty", param, sizeof(param));
+       KT_ASSERT_M("Unable to parse -empty option", opt);
+       KT_ASSERT_M("Invalid -empty option value", strcmp(param, "") == 0);
+
+       return TRUE;
+}
+
 static struct ktest ktests[] = {
 #ifdef CONFIG_X86
        KTEST_REG(ipi_sending,        CONFIG_TEST_ipi_sending),
        KTEST_REG(pic_reception,      CONFIG_TEST_pic_reception),
-       KTEST_REG(ioapic_pit_reroute, CONFIG_TEST_ioapic_status_bit),
        KTEST_REG(lapic_status_bit,   CONFIG_TEST_lapic_status_bit),
        KTEST_REG(pit,                CONFIG_TEST_pit),
        KTEST_REG(circ_buffer,        CONFIG_TEST_circ_buffer),
@@ -2030,7 +2386,6 @@ static struct ktest ktests[] = {
        KTEST_REG(page_coloring,      CONFIG_TEST_page_coloring),
        KTEST_REG(color_alloc,        CONFIG_TEST_color_alloc),
 #endif // CONFIG_PAGE_COLORING
-       KTEST_REG(print_info,         CONFIG_TEST_print_info),
        KTEST_REG(barrier,            CONFIG_TEST_barrier),
        KTEST_REG(interrupts_irqsave, CONFIG_TEST_interrupts_irqsave),
        KTEST_REG(bitmasks,           CONFIG_TEST_bitmasks),
@@ -2039,6 +2394,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),
@@ -2054,7 +2410,12 @@ static struct ktest ktests[] = {
        KTEST_REG(apipe,              CONFIG_TEST_apipe),
        KTEST_REG(rwlock,             CONFIG_TEST_rwlock),
        KTEST_REG(rv,                 CONFIG_TEST_rv),
-       KTEST_REG(alarm,              CONFIG_TEST_alarm)
+       KTEST_REG(alarm,              CONFIG_TEST_alarm),
+       KTEST_REG(kmalloc_incref,     CONFIG_TEST_kmalloc_incref),
+       KTEST_REG(u16pool,            CONFIG_TEST_u16pool),
+       KTEST_REG(uaccess,            CONFIG_TEST_uaccess),
+       KTEST_REG(sort,               CONFIG_TEST_sort),
+       KTEST_REG(cmdline_parse,      CONFIG_TEST_cmdline_parse),
 };
 static int num_ktests = sizeof(ktests) / sizeof(struct ktest);
 linker_func_1(register_pb_ktests)