+void *
+page_alloc(u64 len)
+{
+ if (len > SIZE_MAX)
+ die("page_alloc: Size %llu is too large for the current architecture", (long long) len);
+ ASSERT(!(len & (CPU_PAGE_SIZE-1)));
+ byte *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (p == (byte*) MAP_FAILED)
+ die("Cannot mmap %llu bytes of memory: %m", (long long)len);
+ return p;
+}
+
+void *
+page_alloc_zero(u64 len)
+{
+ void *p = page_alloc(len);
+ bzero(p, len);
+ return p;
+}
+
+void
+page_free(void *start, u64 len)
+{
+ ASSERT(!(len & (CPU_PAGE_SIZE-1)));
+ ASSERT(!((uintptr_t) start & (CPU_PAGE_SIZE-1)));
+ munmap(start, len);
+}
+
+void *
+page_realloc(void *start, u64 old_len, u64 new_len)
+{
+ void *p = page_alloc(new_len);
+ memcpy(p, start, MIN(old_len, new_len));
+ page_free(start, old_len);
+ return p;
+}
+
+static u64
+big_round(u64 len)