diff --git a/usr/src/uts/armv6/os/memnode.c b/usr/src/uts/armv6/os/memnode.c
index 70043b6..0e51413 100644
--- a/usr/src/uts/armv6/os/memnode.c
+++ b/usr/src/uts/armv6/os/memnode.c
@@ -11,6 +11,7 @@
 
 /*
  * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  */
 
 /*
@@ -19,14 +20,20 @@
  * XXX Fill this in when we know much more about what it looks like.
  */
 
+#include <sys/systm.h>
+#include <sys/memlist.h>
 #include <sys/memnode.h>
 /* This is only used for panic and can be removed when we implement the file */
 #include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
 
 int max_mem_nodes = 1;
 
 struct mem_node_conf mem_node_config[MAX_MEM_NODES];
 
+uint16_t num_memnodes;
+mnodeset_t memnodes_mask; /* assumes 8*(sizeof(mnodeset_t)) >= MAX_MEM_NODES */
+
 int
 plat_pfn_to_mem_node(pfn_t pfn)
 {
@@ -45,10 +52,30 @@ plat_mem_node_to_lgrphand(int mnode)
 	panic("plat_mem_node_to_lgrphand");
 }
 
-void
-plat_slice_add(pfn_t start, pfn_t end)
+static void
+mem_node_add_slice(pfn_t start, pfn_t end)
 {
-	panic("plat_slice_add");
+	int mnode;
+
+	mnode = PFN_2_MEM_NODE(start);
+	ASSERT(mnode >= 0 && mnode < max_mem_nodes);
+
+	if (atomic_cas_32((uint32_t *)&mem_node_config[mnode].exists, 0, 1)) {
+		/*
+		 * Add slice to existing node.
+		 */
+		if (start < mem_node_config[mnode].physbase)
+			mem_node_config[mnode].physbase = start;
+		if (end > mem_node_config[mnode].physmax)
+			mem_node_config[mnode].physmax = end;
+	} else {
+		mem_node_config[mnode].physbase = start;
+		mem_node_config[mnode].physmax = end;
+		atomic_inc_16(&num_memnodes);
+		atomic_or_64(&memnodes_mask, 1ull << mnode);
+	}
+
+	lgrp_config(LGRP_CONFIG_MEM_ADD, mnode, MEM_NODE_2_LGRPHAND(mnode));
 }
 
 void
@@ -56,3 +83,20 @@ plat_slice_del(pfn_t start, pfn_t end)
 {
 	panic("plat_slice_del");
 }
+
+void
+startup_build_mem_nodes(struct memlist *list)
+{
+	pfn_t start, end;
+
+	/* LINTED: ASSERT will always true or false */
+	ASSERT(NBBY * sizeof (mnodeset_t) >= max_mem_nodes);
+
+	while (list) {
+		start = list->ml_address >> PAGESHIFT;
+		end = (list->ml_address + list->ml_size - 1) >> PAGESHIFT;
+		end = MIN(end, physmax);
+		mem_node_add_slice(start, end);
+		list = list->ml_next;
+	}
+}
diff --git a/usr/src/uts/armv6/os/startup.c b/usr/src/uts/armv6/os/startup.c
index e9944b6..bf6c4b9 100644
--- a/usr/src/uts/armv6/os/startup.c
+++ b/usr/src/uts/armv6/os/startup.c
@@ -11,12 +11,16 @@
 
 /*
  * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  */
 
 #include <sys/types.h>
 #include <sys/bootconf.h>
 #include <sys/obpdefs.h>
 #include <sys/promif.h>
+#include <sys/systm.h>
+#include <sys/memnode.h>
+#include <vm/page.h>
 
 /*
  *	32-bit Kernel's Virtual memory layout.
@@ -56,6 +60,8 @@
  * + Item does not exist at this time.
  */
 
+extern void pcf_init(void);
+
 struct bootops		*bootops = 0;	/* passed in from boot */
 struct bootops		**bootopsp;
 struct boot_syscalls	*sysp;		/* passed in from boot */
@@ -63,6 +69,12 @@ struct boot_syscalls	*sysp;		/* passed in from boot */
 char kern_bootargs[OBP_MAXPATHLEN];
 char kern_bootfile[OBP_MAXPATHLEN];
 
+/* XXX: 1GB for now */
+pgcnt_t physmem = mmu_btop(1ul << 30);
+
+pgcnt_t npages;
+pgcnt_t orig_npages;
+
 caddr_t s_text;		/* start of kernel text segment */
 caddr_t e_text;		/* end of kernel text segment */
 caddr_t s_data;		/* start of kernel data segment */
@@ -101,6 +113,17 @@ int armv6_cache_assoc;		/* L1 cache associativity */
 int armv6_l2cache_linesz;	/* Size of a line in the l2 cache */
 int armv6_l2cache_size;		/* Total size of the l2 cache */
 
+static void
+print_memlist(char *title, struct memlist *mp)
+{
+	prom_printf("MEMLIST: %s:\n", title);
+	while (mp != NULL)  {
+		prom_printf("\tAddress 0x%" PRIx64 ", size 0x%" PRIx64 "\n",
+		    mp->ml_address, mp->ml_size);
+		mp = mp->ml_next;
+	}
+}
+
 /*
  * Do basic set up.
  */
@@ -116,6 +139,65 @@ startup_init()
 static void
 startup_memlist()
 {
+	struct memlist *ml;
+	int memblocks;
+
+	ml = &bootops->boot_mem.physinstalled;
+	if (prom_debug)
+		print_memlist("boot physinstalled", ml);
+
+	/* XXX: assuming we have only one element in our memlist */
+	physmax = (ml->ml_address + ml->ml_size - 1) >> PAGESHIFT;
+	physinstalled = btop(ml->ml_size);
+	memblocks = 1;
+
+	if (prom_debug)
+		prom_printf("physmax = %lu, physinstalled = %lu, "
+		    "memblocks = %d\n", physmax, physinstalled, memblocks);
+
+	// XXX: mmu_init();
+	startup_build_mem_nodes(ml);
+
+	/*
+	 * We will need page_t's for every page in the system.
+	 *
+	 * XXX: Don't count pages we'll never get to use - e.g., pages
+	 * mapped at or above the start of kernel .text.
+	 */
+	npages = physinstalled - 1;
+
+	/*
+	 * If physmem is patched to be non-zero, use it instead of the
+	 * computed value unless it is larger than the actual amount of
+	 * memory on hand.
+	 */
+	if (physmem == 0 || physmem > npages) {
+		physmem = npages;
+	} else if (physmem < npages) {
+		orig_npages = npages;
+		npages = physmem;
+	}
+
+	if (prom_debug)
+		prom_printf("npages = %lu, orig_npages = %lu\n", npages,
+		    orig_npages);
+
+	// XXX: allocate pse_mutex
+	// XXX: set valloc_base
+	// XXX: set up page coloring
+	//	page_coloring_setup(pagecolor_mem);
+
+	page_lock_init();
+
+	// XXX: page_ctrs_alloc(page_ctrs_mem);
+
+	pcf_init();
+
+	/*
+	 * Initialize the page structures from the memory lists.
+	 */
+	availrmem_initial = availrmem = freemem = 0;
+
 	bop_panic("startup_memlist");
 }
 
diff --git a/usr/src/uts/armv6/sys/memnode.h b/usr/src/uts/armv6/sys/memnode.h
index ac007c5..4c2f8fb 100644
--- a/usr/src/uts/armv6/sys/memnode.h
+++ b/usr/src/uts/armv6/sys/memnode.h
@@ -11,6 +11,7 @@
 
 /*
  * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  */
 
 #ifndef _SYS_MEMNODE_H
@@ -59,7 +60,6 @@ extern int max_mem_nodes;
 extern int plat_pfn_to_mem_node(pfn_t);
 extern void plat_assign_lgrphand_to_mem_node(lgrp_handle_t, int);
 extern lgrp_handle_t plat_mem_node_to_lgrphand(int);
-extern void plat_slice_add(pfn_t, pfn_t);
 extern void plat_slice_del(pfn_t, pfn_t);
 
 struct mem_node_conf {
@@ -68,6 +68,10 @@ struct mem_node_conf {
 	pfn_t	physmax;	/* highest PFN in this memnode */
 };
 
+struct memlist;
+
+extern void startup_build_mem_nodes(struct memlist *);
+
 extern struct mem_node_conf	mem_node_config[];
 
 #endif	/* _KERNEL */
