ROUNDDOWN can handle uint64_t on 32 bit (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Aug 2013 23:44:34 +0000 (16:44 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Aug 2013 23:44:34 +0000 (16:44 -0700)
ROUNDDOWN was casting to a uintptr_t, which would truncate a uint64_t on
32 bit builds.  (Came up in mboot parsing, when pages above
0x0000000100000000 would get treated as if offset from 0).

Since the compiler complains about the int->pointer->int casting, even
in code that should never be called (based on the sizeof() in
ROUNDDOWN), we had to make ROUNDDOWN (and ROUNDUP) only work on
uintptr_t.  Ideally, we'll fix that in the future (C11 features,
perhaps).

You should reinstall your kernel headers to get the new changes for
userspace, though it's not a huge deal.

kern/arch/x86/pmap32.c
kern/arch/x86/trap.c
kern/include/ros/common.h
kern/src/slab.c
kern/src/umem.c
user/parlib/slab.c

index 58d432a..4a42fc2 100644 (file)
@@ -647,7 +647,7 @@ int env_user_mem_walk(env_t* e, void* start, size_t len,
        physaddr_t pa;
 
        assert((uintptr_t)start % PGSIZE == 0 && len % PGSIZE == 0);
-       void* end = (char*)start+len;
+       uintptr_t end = (uintptr_t)start+len;
        uint32_t pdeno_start = PDX(start);
        uint32_t pdeno_end = PDX(ROUNDUP(end,PTSIZE));
        /* concerned about overflow.  this should catch it for now, given the above
index 6013f19..6a9ddc0 100644 (file)
@@ -137,7 +137,8 @@ void idt_init(void)
 
 #ifdef CONFIG_KTHREAD_POISON
        /* TODO: KTHR-STACK */
-       uintptr_t *poison = (uintptr_t*)ROUNDDOWN(bootstacktop - 1, PGSIZE);
+       uintptr_t *poison = (uintptr_t*)ROUNDDOWN((uintptr_t)bootstacktop - 1,
+                                                 PGSIZE);
        *poison = 0xdeadbeef;
 #endif /* CONFIG_KTHREAD_POISON */
 
index b600819..46d2fa9 100644 (file)
@@ -48,31 +48,35 @@ typedef unsigned long uintreg_t;
 })
 #endif
 
-// Rounding operations (efficient when n is a power of 2)
-// Round down to the nearest multiple of n
-#define ROUNDDOWN(a, n)                                                \
-({                                                             \
-       uintptr_t __a = (uintptr_t) (a);                                \
-       (typeof(a)) (__a - __a % (n));                          \
-})
-// Round up to the nearest multiple of n
-#define ROUNDUP(a, n)                                          \
-({                                                             \
-       uintptr_t __n = (uintptr_t) (n);                                \
-       (typeof(a)) (ROUNDDOWN((uintptr_t) (a) + __n - 1, __n));        \
+/* Rounding operations (efficient when n is a power of 2)
+ * Round down to the nearest multiple of n.
+ * The compiler should compile out the branch.  This is needed for 32 bit, so
+ * that we can round down uint64_t, without chopping off the top 32 bits. */
+#define ROUNDDOWN(a, n)                                                        \
+({                                                                             \
+       typeof(a) __b;                                                             \
+       if (sizeof(a) == 8) {                                                      \
+               uint64_t __a = (uint64_t) (a);                                         \
+               __b = (typeof(a)) (__a - __a % (n));                                   \
+       } else {                                                                   \
+               uintptr_t __a = (uintptr_t) (a);                                       \
+               __b = (typeof(a)) (__a - __a % (n));                                   \
+       }                                                                          \
+       __b;                                                                       \
 })
 
-// Round down to the nearest multiple of n
-#define PTRROUNDDOWN(a, n)                                             \
-({                                                             \
-       char * __a = (char *) (a);                              \
-       (typeof(a)) (__a - (uintptr_t)__a % (n));                               \
-})
-// Round pointer up to the nearest multiple of n
-#define PTRROUNDUP(a, n)                                               \
-({                                                             \
-       uintptr_t __n = (uintptr_t) (n);                                \
-       (typeof(a)) (PTRROUNDDOWN((char *) (a) + __n - 1, __n));        \
+/* Round up to the nearest multiple of n */
+#define ROUNDUP(a, n)                                                          \
+({                                                                             \
+       typeof(a) __b;                                                             \
+       if (sizeof(a) == 8) {                                                      \
+               uint64_t __n = (uint64_t) (n);                                         \
+               __b = (typeof(a)) (ROUNDDOWN((uint64_t) (a) + __n - 1, __n));          \
+       } else {                                                                   \
+               uintptr_t __n = (uintptr_t) (n);                                       \
+               __b = (typeof(a)) (ROUNDDOWN((uintptr_t) (a) + __n - 1, __n));         \
+       }                                                                          \
+       __b;                                                                       \
 })
 
 // Return the integer logarithm of the value provided rounded down
index 6d2b313..d394d70 100644 (file)
@@ -107,7 +107,7 @@ static void kmem_slab_destroy(struct kmem_cache *cp, struct kmem_slab *a_slab)
                                buf += a_slab->obj_size;
                        }
                }
-               page_decref(kva2page(ROUNDDOWN(a_slab, PGSIZE)));
+               page_decref(kva2page((void*)ROUNDDOWN((uintptr_t)a_slab, PGSIZE)));
        } else {
                struct kmem_bufctl *i;
                void *page_start = (void*)-1;
@@ -212,8 +212,8 @@ void kmem_cache_free(struct kmem_cache *cp, void *buf)
        spin_lock_irqsave(&cp->cache_lock);
        if (cp->obj_size <= SLAB_LARGE_CUTOFF) {
                // find its slab
-               a_slab = (struct kmem_slab*)(ROUNDDOWN(buf, PGSIZE) + PGSIZE -
-                                            sizeof(struct kmem_slab));
+               a_slab = (struct kmem_slab*)(ROUNDDOWN((uintptr_t)buf, PGSIZE) +
+                                            PGSIZE - sizeof(struct kmem_slab));
                /* write location of next free small obj to the space at the end of the
                 * buffer, then list buf as the next free small obj */
                *(uintptr_t**)(buf + cp->obj_size) = a_slab->free_small_obj;
index ed6bde3..e8d83c5 100644 (file)
@@ -66,8 +66,8 @@ void *user_mem_check(struct proc *p, const void *DANGEROUS va, size_t len,
        int page_perms = 0;
 
        perm |= PTE_P;
-       start = ROUNDDOWN((void*DANGEROUS)va, PGSIZE);
-       end = ROUNDUP((void*DANGEROUS)va + len, PGSIZE);
+       start = (void*)ROUNDDOWN((uintptr_t)va, PGSIZE);
+       end = (void*)ROUNDUP((uintptr_t)va + len, PGSIZE);
        if (start >= end) {
                warn("Blimey!  Wrap around in VM range calculation!");  
                return NULL;
@@ -151,8 +151,8 @@ int memcpy_from_user(struct proc *p, void *dest, const void *DANGEROUS va,
 
        static_assert(ULIM % PGSIZE == 0 && ULIM != 0); // prevent wrap-around
 
-       start = ROUNDDOWN(va, PGSIZE);
-       end = ROUNDUP(va + len, PGSIZE);
+       start = (void*)ROUNDDOWN((uintptr_t)va, PGSIZE);
+       end = (void*)ROUNDUP((uintptr_t)va + len, PGSIZE);
 
        if (start >= (void*SNT)ULIM || end > (void*SNT)ULIM)
                return -EFAULT;
@@ -217,8 +217,8 @@ int memcpy_to_user(struct proc *p, void *va, const void *src, size_t len)
 
        static_assert(ULIM % PGSIZE == 0 && ULIM != 0); // prevent wrap-around
 
-       start = ROUNDDOWN(va, PGSIZE);
-       end = ROUNDUP(va + len, PGSIZE);
+       start = (void*)ROUNDDOWN((uintptr_t)va, PGSIZE);
+       end = (void*)ROUNDUP((uintptr_t)va + len, PGSIZE);
 
        if (start >= (void*SNT)ULIM || end > (void*SNT)ULIM)
                return -EFAULT;
index 1bd76d1..1e2ad04 100644 (file)
@@ -107,7 +107,7 @@ static void kmem_slab_destroy(struct kmem_cache *cp, struct kmem_slab *a_slab)
                                buf += a_slab->obj_size;
                        }
                }
-               munmap(ROUNDDOWN(a_slab, PGSIZE), PGSIZE);
+               munmap((void*)ROUNDDOWN((uintptr_t)a_slab, PGSIZE), PGSIZE);
        } else {
                struct kmem_bufctl *i;
                void *page_start = (void*)-1;
@@ -209,8 +209,8 @@ void kmem_cache_free(struct kmem_cache *cp, void *buf)
        spin_pdr_lock(&cp->cache_lock);
        if (cp->obj_size <= SLAB_LARGE_CUTOFF) {
                // find its slab
-               a_slab = (struct kmem_slab*)(ROUNDDOWN(buf, PGSIZE) + PGSIZE -
-                                            sizeof(struct kmem_slab));
+               a_slab = (struct kmem_slab*)(ROUNDDOWN((uintptr_t)buf, PGSIZE) +
+                                            PGSIZE - sizeof(struct kmem_slab));
                /* write location of next free small obj to the space at the end of the
                 * buffer, then list buf as the next free small obj */
                *(uintptr_t**)(buf + cp->obj_size) = a_slab->free_small_obj;