All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] mini-os: initial ARM support
@ 2014-06-02 17:49 Thomas Leonard
  2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
                   ` (4 more replies)
  0 siblings, 5 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-02 17:49 UTC (permalink / raw)
  To: xen-devel; +Cc: samuel.thibault, Thomas Leonard, stefano.stabellini

This series is Karim's initial ARM support, broken up into smaller patches.
I removed some debug code from the patch, fixed it to work on x86 again,
and replaced memmove with a BSD-licensed version.

I also added a fix so that Mini-OS doesn't shut down immediately. This is
for x86 too, but I needed it because otherwise it's hard to test it.

It's probably not worth worrying too much about the ARM support itself (there
will be more patches coming shortly!) - the main thing is refactoring Mini-OS
to support the new architecture.

Karim Raslan (3):
  mini-os: Tidied up code
  mini-os: Initial commit to port minios to ARM
  mini-os: Added FDT support on ARM

Thomas Leonard (1):
  mini-os: Fixed shutdown thread

 extras/mini-os/ARM-TODO.txt                        |   19 +
 extras/mini-os/COPYING                             |   27 +
 extras/mini-os/Config.mk                           |    2 +
 extras/mini-os/Makefile                            |   23 +
 extras/mini-os/README                              |    7 +-
 extras/mini-os/arch/arm/Makefile                   |   33 +
 extras/mini-os/arch/arm/arch.mk                    |    6 +
 extras/mini-os/arch/arm/arm32.S                    |  211 +++
 extras/mini-os/arch/arm/divsi3.S                   |  404 ++++++
 extras/mini-os/arch/arm/events.c                   |   24 +
 extras/mini-os/arch/arm/hypercalls32.S             |   88 ++
 extras/mini-os/arch/arm/ldivmod.S                  |   67 +
 extras/mini-os/arch/arm/ldivmod_helper.c           |   66 +
 extras/mini-os/arch/arm/minios-arm32.lds           |   73 +
 extras/mini-os/arch/arm/mm.c                       |   44 +
 extras/mini-os/arch/arm/qdivrem.c                  |  270 ++++
 extras/mini-os/arch/arm/sched.c                    |   32 +
 extras/mini-os/arch/arm/setup.c                    |   55 +
 extras/mini-os/arch/arm/time.c                     |  232 +++
 extras/mini-os/arch/arm/xenbus.c                   |   36 +
 extras/mini-os/arch/x86/events.c                   |   28 +
 extras/mini-os/arch/x86/setup.c                    |   44 +-
 extras/mini-os/arch/x86/time.c                     |    6 +-
 extras/mini-os/arch/x86/x86_32.S                   |    2 +-
 extras/mini-os/arch/x86/x86_64.S                   |    2 +-
 extras/mini-os/arch/x86/xenbus.c                   |   10 +
 extras/mini-os/console/console.c                   |    4 +-
 extras/mini-os/drivers/gic.c                       |  179 +++
 extras/mini-os/events.c                            |   35 +-
 extras/mini-os/gntmap.c                            |   34 +-
 extras/mini-os/gnttab.c                            |    1 +
 extras/mini-os/hypervisor.c                        |   20 +-
 extras/mini-os/include/arm/arch_limits.h           |    9 +
 extras/mini-os/include/arm/arch_mm.h               |   37 +
 extras/mini-os/include/arm/arch_sched.h            |   22 +
 extras/mini-os/include/arm/arch_spinlock.h         |   49 +
 extras/mini-os/include/arm/hypercall-arm32.h       |  173 +++
 extras/mini-os/include/arm/os.h                    |  314 +++++
 extras/mini-os/include/arm/traps.h                 |   20 +
 extras/mini-os/include/console.h                   |    1 +
 extras/mini-os/include/fdt.h                       |   60 +
 extras/mini-os/include/hypervisor.h                |   19 +-
 extras/mini-os/include/lib.h                       |    4 +-
 extras/mini-os/include/libfdt.h                    | 1478 ++++++++++++++++++++
 extras/mini-os/include/libfdt_env.h                |   37 +
 extras/mini-os/include/mm.h                        |    2 +
 extras/mini-os/include/types.h                     |   73 +-
 extras/mini-os/include/x86/arch_mm.h               |    2 +
 extras/mini-os/include/x86/arch_spinlock.h         |    2 +-
 extras/mini-os/include/x86/os.h                    |   19 +-
 .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |    1 +
 extras/mini-os/kernel.c                            |   94 +-
 extras/mini-os/lib/fdt/fdt.c                       |  222 +++
 extras/mini-os/lib/fdt/fdt_empty_tree.c            |   84 ++
 extras/mini-os/lib/fdt/fdt_ro.c                    |  574 ++++++++
 extras/mini-os/lib/fdt/fdt_rw.c                    |  492 +++++++
 extras/mini-os/lib/fdt/fdt_strerror.c              |   96 ++
 extras/mini-os/lib/fdt/fdt_sw.c                    |  256 ++++
 extras/mini-os/lib/fdt/fdt_wip.c                   |  118 ++
 extras/mini-os/lib/fdt/libfdt_internal.h           |   95 ++
 extras/mini-os/lib/memmove.c                       |   45 +
 extras/mini-os/lib/string.c                        |   12 +
 extras/mini-os/main.c                              |    2 +-
 extras/mini-os/mm.c                                |    9 +-
 extras/mini-os/sched.c                             |   12 +-
 extras/mini-os/time.c                              |   12 +
 extras/mini-os/xenbus/xenbus.c                     |   20 +-
 67 files changed, 6410 insertions(+), 139 deletions(-)
 create mode 100644 extras/mini-os/ARM-TODO.txt
 create mode 100755 extras/mini-os/arch/arm/Makefile
 create mode 100644 extras/mini-os/arch/arm/arch.mk
 create mode 100644 extras/mini-os/arch/arm/arm32.S
 create mode 100644 extras/mini-os/arch/arm/divsi3.S
 create mode 100644 extras/mini-os/arch/arm/events.c
 create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
 create mode 100644 extras/mini-os/arch/arm/ldivmod.S
 create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
 create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
 create mode 100644 extras/mini-os/arch/arm/mm.c
 create mode 100644 extras/mini-os/arch/arm/qdivrem.c
 create mode 100644 extras/mini-os/arch/arm/sched.c
 create mode 100644 extras/mini-os/arch/arm/setup.c
 create mode 100644 extras/mini-os/arch/arm/time.c
 create mode 100644 extras/mini-os/arch/arm/xenbus.c
 create mode 100644 extras/mini-os/arch/x86/events.c
 create mode 100644 extras/mini-os/arch/x86/xenbus.c
 create mode 100644 extras/mini-os/drivers/gic.c
 create mode 100644 extras/mini-os/include/arm/arch_limits.h
 create mode 100644 extras/mini-os/include/arm/arch_mm.h
 create mode 100644 extras/mini-os/include/arm/arch_sched.h
 create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
 create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
 create mode 100644 extras/mini-os/include/arm/os.h
 create mode 100644 extras/mini-os/include/arm/traps.h
 create mode 100644 extras/mini-os/include/fdt.h
 create mode 100644 extras/mini-os/include/libfdt.h
 create mode 100644 extras/mini-os/include/libfdt_env.h
 create mode 100644 extras/mini-os/lib/fdt/fdt.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_empty_tree.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_ro.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_rw.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_strerror.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_sw.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_wip.c
 create mode 100644 extras/mini-os/lib/fdt/libfdt_internal.h
 create mode 100644 extras/mini-os/lib/memmove.c
 create mode 100644 extras/mini-os/time.c

-- 
1.9.3

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 1/4] mini-os: Fixed shutdown thread
  2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
@ 2014-06-02 17:49 ` Thomas Leonard
  2014-06-03  0:51   ` Samuel Thibault
  2014-06-03  9:01   ` Andrew Cooper
  2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-02 17:49 UTC (permalink / raw)
  To: xen-devel; +Cc: samuel.thibault, Thomas Leonard, stefano.stabellini

Before, it read "" and started a shutdown immediately. Now, it waits for
a non-empty value and then actually shuts down.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/kernel.c | 16 ++++++++++++----
 extras/mini-os/main.c   |  2 +-
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index ea409f4..386be8f 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -69,6 +69,8 @@ void setup_xen_features(void)
 __attribute__((weak)) void app_shutdown(unsigned reason)
 {
     printk("Shutdown requested: %d\n", reason);
+    struct sched_shutdown sched_shutdown = { .reason = reason };
+    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
 }
 
 static void shutdown_thread(void *p)
@@ -76,12 +78,18 @@ static void shutdown_thread(void *p)
     const char *path = "control/shutdown";
     const char *token = path;
     xenbus_event_queue events = NULL;
-    char *shutdown, *err;
+    char *shutdown = NULL, *err;
     unsigned int shutdown_reason;
     xenbus_watch_path_token(XBT_NIL, path, token, &events);
-    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL)
+    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
     {
-        free(err);
+        if (err)
+            free(err);
+        if (shutdown)
+        {
+            free(shutdown);
+            shutdown = NULL;
+        }
         xenbus_wait_for_watch(&events);
     }
     err = xenbus_unwatch_path_token(XBT_NIL, path, token);
@@ -106,7 +114,7 @@ static void shutdown_thread(void *p)
 /* This should be overridden by the application we are linked against. */
 __attribute__((weak)) int app_main(start_info_t *si)
 {
-    printk("Dummy main: start_info=%p\n", si);
+    printk("kernel.c: dummy main: start_info=%p\n", si);
     return 0;
 }
 
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index 73eb6fb..aec0586 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -185,7 +185,7 @@ void _exit(int ret)
 
 int app_main(start_info_t *si)
 {
-    printk("Dummy main: start_info=%p\n", si);
+    printk("main.c: dummy main: start_info=%p\n", si);
     main_thread = create_thread("main", call_main, si);
     return 0;
 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 2/4] mini-os: Tidied up code
  2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
  2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
@ 2014-06-02 17:49 ` Thomas Leonard
  2014-06-03  0:57   ` Samuel Thibault
  2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-02 17:49 UTC (permalink / raw)
  To: xen-devel; +Cc: samuel.thibault, Thomas Leonard, stefano.stabellini

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/README                      |  7 +++++--
 extras/mini-os/arch/x86/time.c             |  2 +-
 extras/mini-os/console/console.c           |  2 +-
 extras/mini-os/events.c                    |  3 ++-
 extras/mini-os/gntmap.c                    | 33 ++++++++++++++----------------
 extras/mini-os/include/x86/arch_spinlock.h |  2 +-
 extras/mini-os/sched.c                     |  3 +++
 extras/mini-os/xenbus/xenbus.c             |  2 +-
 8 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/extras/mini-os/README b/extras/mini-os/README
index 710a303..bf49700 100644
--- a/extras/mini-os/README
+++ b/extras/mini-os/README
@@ -25,8 +25,11 @@ This includes:
 
 - to build it with much better libc support, see the stubdom/ directory
 
-- to start it do the following in domain0 (assuming xend is running)
-  # xm create domain_config
+- to start it do the following in domain0
+  # xm create domain_config # old style xend ( assuming xend is running )
+or
+  # xl create domain_config # using toolstack
+
 
 This starts the kernel and prints out a bunch of stuff and then once every
 second the system time.
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index 89bc382..2c8d033 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -212,7 +212,7 @@ void block_domain(s_time_t until)
 
 
 /*
- * Just a dummy 
+ * Just a dummy
  */
 static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
 {
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 380f53c..5538bd4 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -124,7 +124,7 @@ void print(int direct, const char *fmt, va_list args)
     static char   buf[1024];
     
     (void)vsnprintf(buf, sizeof(buf), fmt, args);
- 
+
     if(direct)
     {
         (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 036b84b..2da9b01 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -138,7 +138,8 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
 	op.virq = virq;
 	op.vcpu = smp_processor_id();
 
-	if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op)) != 0 )
+	rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
+	if (rc != 0)
 	{
 		printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
 		return -1;
diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
index 22ed450..7eb69be 100644
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -38,6 +38,15 @@
 #include <inttypes.h>
 #include <mini-os/gntmap.h>
 
+//#define GNTMAP_DEBUG
+#ifdef GNTMAP_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=gntmap.c, line=%d) " _f "\n", __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
 #define DEFAULT_MAX_GRANTS 128
 
 struct gntmap_entry {
@@ -61,10 +70,8 @@ gntmap_find_free_entry(struct gntmap *map)
             return &map->entries[i];
     }
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
+    DEBUG("gntmap_find_free_entry(map=%p): all %d entries full\n",
            map, map->nentries);
-#endif
     return NULL;
 }
 
@@ -83,9 +90,7 @@ gntmap_find_entry(struct gntmap *map, unsigned long addr)
 int
 gntmap_set_max_grants(struct gntmap *map, int count)
 {
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
-#endif
+    DEBUG("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
 
     if (map->nentries != 0)
         return -EBUSY;
@@ -157,10 +162,8 @@ gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
     int i, rc;
     struct gntmap_entry *ent;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
+    DEBUG("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
            map, start_address, count);
-#endif
 
     for (i = 0; i < count; i++) {
         ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
@@ -189,14 +192,12 @@ gntmap_map_grant_refs(struct gntmap *map,
     struct gntmap_entry *ent;
     int i;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
+    DEBUG("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
            "domids=%p [%" PRIu32 "...], domids_stride=%d, "
            "refs=%p [%" PRIu32 "...], writable=%d)\n",
            map, count,
            domids, domids == NULL ? 0 : domids[0], domids_stride,
            refs, refs == NULL ? 0 : refs[0], writable);
-#endif
 
     (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
 
@@ -224,9 +225,7 @@ gntmap_map_grant_refs(struct gntmap *map,
 void
 gntmap_init(struct gntmap *map)
 {
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_init(map=%p)\n", map);
-#endif
+    DEBUG("gntmap_init(map=%p)\n", map);
     map->nentries = 0;
     map->entries = NULL;
 }
@@ -237,9 +236,7 @@ gntmap_fini(struct gntmap *map)
     struct gntmap_entry *ent;
     int i;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_fini(map=%p)\n", map);
-#endif
+    DEBUG("gntmap_fini(map=%p)\n", map);
 
     for (i = 0; i < map->nentries; i++) {
         ent = &map->entries[i];
diff --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h
index c08b6f1..59f7b63 100644
--- a/extras/mini-os/include/x86/arch_spinlock.h
+++ b/extras/mini-os/include/x86/arch_spinlock.h
@@ -61,7 +61,7 @@
 
 static inline void _raw_spin_unlock(spinlock_t *lock)
 {
-	char oldval = 1;
+	char oldval = ARCH_SPIN_LOCK_UNLOCKED;
 	__asm__ __volatile__(
 		spin_unlock_string
 	);
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 5ac5c1c..174945e 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -85,6 +85,7 @@ void schedule(void)
         printk("Must not call schedule() from a callback\n");
         BUG();
     }
+
     if (flags) {
         printk("Must not call schedule() with IRQs disabled\n");
         BUG();
@@ -188,6 +189,8 @@ struct _reent *__getreent(void)
 	}
     }
 #endif
+#else
+#error Not implemented yet
 #endif
     return _reent;
 }
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index c5d9b02..934f23b 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -276,7 +276,7 @@ static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
 }
 
 static int nr_live_reqs;
-static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(req_lock);
 static DECLARE_WAIT_QUEUE_HEAD(req_wq);
 
 /* Release a xenbus identifier */
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 3/4] mini-os: Initial commit to port minios to ARM
  2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
  2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
  2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
@ 2014-06-02 17:49 ` Thomas Leonard
  2014-06-03  9:12   ` Julien Grall
  2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
  2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
  4 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-02 17:49 UTC (permalink / raw)
  To: xen-devel; +Cc: samuel.thibault, Thomas Leonard, stefano.stabellini

From: Karim Raslan <karim.allah.ahmed@gmail.com>

On ARM, Mini-OS will boot and display some output on the Xen emergency
console (only visible if Xen is compiled in debug mode). Tested with:

make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
  CONFIG_TEST=n CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
  CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
  CONFIG_CONSFRONT=n CONFIG_XC=n

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: made x86_64 support work again]
[talex5@gmail.com: split into multiple patches]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/ARM-TODO.txt                        |  19 +
 extras/mini-os/Config.mk                           |   2 +
 extras/mini-os/Makefile                            |  12 +
 extras/mini-os/arch/arm/Makefile                   |  33 ++
 extras/mini-os/arch/arm/arch.mk                    |   6 +
 extras/mini-os/arch/arm/arm32.S                    | 211 +++++++++++
 extras/mini-os/arch/arm/divsi3.S                   | 404 +++++++++++++++++++++
 extras/mini-os/arch/arm/events.c                   |  24 ++
 extras/mini-os/arch/arm/hypercalls32.S             |  88 +++++
 extras/mini-os/arch/arm/ldivmod.S                  |  67 ++++
 extras/mini-os/arch/arm/ldivmod_helper.c           |  66 ++++
 extras/mini-os/arch/arm/minios-arm32.lds           |  73 ++++
 extras/mini-os/arch/arm/mm.c                       |  44 +++
 extras/mini-os/arch/arm/qdivrem.c                  | 270 ++++++++++++++
 extras/mini-os/arch/arm/sched.c                    |  32 ++
 extras/mini-os/arch/arm/setup.c                    |  55 +++
 extras/mini-os/arch/arm/time.c                     | 232 ++++++++++++
 extras/mini-os/arch/arm/xenbus.c                   |  36 ++
 extras/mini-os/arch/x86/events.c                   |  28 ++
 extras/mini-os/arch/x86/setup.c                    |  44 ++-
 extras/mini-os/arch/x86/time.c                     |   4 +-
 extras/mini-os/arch/x86/x86_32.S                   |   2 +-
 extras/mini-os/arch/x86/x86_64.S                   |   2 +-
 extras/mini-os/arch/x86/xenbus.c                   |  10 +
 extras/mini-os/console/console.c                   |   2 +
 extras/mini-os/drivers/gic.c                       | 179 +++++++++
 extras/mini-os/events.c                            |  32 +-
 extras/mini-os/gntmap.c                            |   1 +
 extras/mini-os/gnttab.c                            |   1 +
 extras/mini-os/hypervisor.c                        |  20 +-
 extras/mini-os/include/arm/arch_limits.h           |   9 +
 extras/mini-os/include/arm/arch_mm.h               |  37 ++
 extras/mini-os/include/arm/arch_sched.h            |  22 ++
 extras/mini-os/include/arm/arch_spinlock.h         |  49 +++
 extras/mini-os/include/arm/hypercall-arm32.h       | 173 +++++++++
 extras/mini-os/include/arm/os.h                    | 314 ++++++++++++++++
 extras/mini-os/include/arm/traps.h                 |  20 +
 extras/mini-os/include/console.h                   |   1 +
 extras/mini-os/include/hypervisor.h                |  19 +-
 extras/mini-os/include/mm.h                        |   2 +
 extras/mini-os/include/types.h                     |  73 +++-
 extras/mini-os/include/x86/arch_mm.h               |   2 +
 extras/mini-os/include/x86/os.h                    |  19 +-
 .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |   1 +
 extras/mini-os/kernel.c                            |  78 ++--
 extras/mini-os/mm.c                                |   9 +-
 extras/mini-os/sched.c                             |   9 +-
 extras/mini-os/time.c                              |  12 +
 extras/mini-os/xenbus/xenbus.c                     |  18 +-
 49 files changed, 2758 insertions(+), 108 deletions(-)
 create mode 100644 extras/mini-os/ARM-TODO.txt
 create mode 100755 extras/mini-os/arch/arm/Makefile
 create mode 100644 extras/mini-os/arch/arm/arch.mk
 create mode 100644 extras/mini-os/arch/arm/arm32.S
 create mode 100644 extras/mini-os/arch/arm/divsi3.S
 create mode 100644 extras/mini-os/arch/arm/events.c
 create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
 create mode 100644 extras/mini-os/arch/arm/ldivmod.S
 create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
 create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
 create mode 100644 extras/mini-os/arch/arm/mm.c
 create mode 100644 extras/mini-os/arch/arm/qdivrem.c
 create mode 100644 extras/mini-os/arch/arm/sched.c
 create mode 100644 extras/mini-os/arch/arm/setup.c
 create mode 100644 extras/mini-os/arch/arm/time.c
 create mode 100644 extras/mini-os/arch/arm/xenbus.c
 create mode 100644 extras/mini-os/arch/x86/events.c
 create mode 100644 extras/mini-os/arch/x86/xenbus.c
 create mode 100644 extras/mini-os/drivers/gic.c
 create mode 100644 extras/mini-os/include/arm/arch_limits.h
 create mode 100644 extras/mini-os/include/arm/arch_mm.h
 create mode 100644 extras/mini-os/include/arm/arch_sched.h
 create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
 create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
 create mode 100644 extras/mini-os/include/arm/os.h
 create mode 100644 extras/mini-os/include/arm/traps.h
 create mode 100644 extras/mini-os/time.c

diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
new file mode 100644
index 0000000..57d531a
--- /dev/null
+++ b/extras/mini-os/ARM-TODO.txt
@@ -0,0 +1,19 @@
+* os.h bit manipulation, write optimized assembly code
+* support abort exception handling ( and others )
+* scheduling!
+* use proper memory types and enable caches (L1 and L2)
+* Use LDREX and STREX in xchg implementation ( code already there but it causes an abort, I think because of using strong-ordered memory with disabled L1 caches - something to do with the implementation of the monitor on cortex-a7 )
+* gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler.
+* use device tree instead of the currently hardcoded values
+* Add virtual memory support and make vstart = 0 ( use 4k descriptors instead of 1M descriptors )
+* sched
+* fini_gnttab
+* fini_time
+* bind_*
+* add multiple cpu support (?)
+* map_frames
+* clean up the code and remove redundent code between arm and x86
+* remove start_info structure from the common code
+* make sure that wallclock is functioning properly
+* console support
+* evtchn_get_peercontext
diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
index d61877b..4ecde54 100644
--- a/extras/mini-os/Config.mk
+++ b/extras/mini-os/Config.mk
@@ -12,6 +12,8 @@ export XEN_INTERFACE_VERSION
 # If not x86 then use $(XEN_TARGET_ARCH)
 ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_)
 TARGET_ARCH_FAM = x86
+else ifeq ($(findstring arm,$(XEN_TARGET_ARCH)),arm)
+TARGET_ARCH_FAM = arm
 else
 TARGET_ARCH_FAM = $(XEN_TARGET_ARCH)
 endif
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 50d038b..0fd38a8 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -72,6 +72,11 @@ TARGET := mini-os
 # Subdirectories common to mini-os
 SUBDIRS := lib xenbus console
 
+ifeq ($(XEN_TARGET_ARCH),arm32)
+# ARM drivers
+src-y += drivers/gic.c
+endif
+
 src-$(CONFIG_BLKFRONT) += blkfront.c
 src-$(CONFIG_TPMFRONT) += tpmfront.c
 src-$(CONFIG_TPM_TIS) += tpm_tis.c
@@ -82,6 +87,7 @@ src-$(CONFIG_FBFRONT) += fbfront.c
 src-y += gntmap.c
 src-y += gnttab.c
 src-y += hypervisor.c
+src-y += time.c
 src-y += kernel.c
 src-y += lock.c
 src-y += main.c
@@ -92,7 +98,9 @@ src-y += sched.c
 src-$(CONFIG_TEST) += test.c
 
 src-y += lib/ctype.c
+ifneq ($(XEN_TARGET_ARCH),arm32)
 src-y += lib/math.c
+endif
 src-y += lib/printf.c
 src-y += lib/stack_chk_fail.c
 src-y += lib/string.c
@@ -178,7 +186,11 @@ $(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) $(APP_O) arch_lib
 	$(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
 	$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
 	$(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+	$(OBJCOPY) -O binary $@ $@.img
+else
 	gzip -f -9 -c $@ >$@.gz
+endif
 
 .PHONY: clean arch_clean
 
diff --git a/extras/mini-os/arch/arm/Makefile b/extras/mini-os/arch/arm/Makefile
new file mode 100755
index 0000000..d8ecc88
--- /dev/null
+++ b/extras/mini-os/arch/arm/Makefile
@@ -0,0 +1,33 @@
+#
+# x86 architecture specific makefiles.
+# It's is used for x86_32, x86_32y and x86_64
+#
+
+XEN_ROOT = $(CURDIR)/../../../..
+include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
+
+# include arch.mk has to be before mini-os.mk!
+
+include arch.mk
+include ../../minios.mk
+
+# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S
+# This is handled in $(HEAD_ARCH_OBJ)
+ARCH_SRCS := $(wildcard *.c)
+
+# The objects built from the sources.
+ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS))
+
+ARCH_OBJS += hypercalls32.o divsi3.o ldivmod.o
+
+all: $(OBJ_DIR)/$(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only build here, needed on linking
+# in ../../Makefile.
+$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+	$(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS)
+
+clean:
+	rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
+
diff --git a/extras/mini-os/arch/arm/arch.mk b/extras/mini-os/arch/arm/arch.mk
new file mode 100644
index 0000000..d2e0946
--- /dev/null
+++ b/extras/mini-os/arch/arm/arch.mk
@@ -0,0 +1,6 @@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__ #-DCPU_EXCLUSIVE_LDST
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
new file mode 100644
index 0000000..2dd0f6c
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,211 @@
+#define PHYS_START (0x80008000)
+
+.section .text
+
+.globl _start
+_start:
+	@ zImage header
+.rept   8
+        mov     r0, r0
+.endr
+        b       1f
+        .word   0x016f2818      @ Magic numbers to help the loader
+        .word   _start		@ absolute load/run zImage address
+        .word   _end - _start   @ zImage size
+	@ end of zImage header
+
+1:
+#if FIXME
+@ core processor specific initialization
+	@ Initialize ACTLR core register
+	mrc p15, 0, <Rt>, c1, c0, 1
+	mcr p15, 0, <Rt>, c1, c0, 1
+#endif
+
+@ Save dtb pointer passed by the hypervisor
+	mov	r4, r2		@ save dtb pointer
+
+@ Build pagetables
+	bl	build_pagetables
+
+	ldr	r2, =page_dir
+	MCR	p15, 0, r2, c2, c0, 0	@ set ttbr0
+
+	@ Set access permission for domains
+	mov	r0, #0x3
+	MCR	p15, 0, r0, c3, c0, 0
+	isb
+	
+	ldr	r0, =mmu_switched
+
+	@ enable mmu / sctlr
+	mrc	p15, 0, r1, c1, c0, 0	@ read sctlr
+	orr	r1, r1, #0x1		@ enable mmu
+	@orr	r1, r1, #0x4		@ enable cache
+	orr	r1, r1, #0x02		@ enable barrier enable
+	@mcr	p15, 0, r1, c1, c0, 0	@ write sctlr
+	isb
+
+	@ jump to the virtual address now
+	mov	pc, r0
+
+@ If we're here, then we're very lucky
+mmu_switched:
+
+@ set VBAR = exception_vector_table
+	@ SCTLR.V = 0
+	adr	r0, exception_vector_table
+	mcr	p15, 0, r0, c12, c0, 0
+
+@ load stack
+	ldr	sp, =stack
+	add	sp, sp, #(4*4*1024)
+
+
+	mov	r0, r4		@ set r0 = dtb pointer
+	b	arch_init
+
+
+@ Populate the whole pagedir with 1MB section descriptors for now (1-1 mapping)
+build_pagetables:
+	ldr	r0, =(0x2 + (1 << 16) + (1<<19)) @ First section entry (sharable + NS ).
+	ldr	r1, =page_dir
+	add	r2, r1, #(4*4*1024) @ Limit
+
+1:
+	str	r0, [r1] @ write the section entry
+
+	add	r0, r0, #(1 << 20) @ next physical page.
+	add	r1, r1, #4 @ next pagedir entry
+	cmp	r1, r2
+	bne	1b
+
+	mov	pc, lr
+
+.pushsection .data
+.align 13
+.globl stack
+stack:
+	.fill (4*1024), 4, 0x0
+.align 13
+irqstack:
+	.fill (1024), 4, 0x0
+.globl shared_info_page
+.align 13
+shared_info_page:
+	.fill (1024), 4, 0x0
+.align	14
+page_dir:
+	.fill (4*1024), 4, 0x0
+
+.popsection
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+exception_vector_table:
+	b	. @ reset
+	b	. @ undefined instruction
+	b	. @ supervisor call
+	b	. @ prefetch call
+	b	. @ prefetch abort
+	b	. @ data abort //FIXME CLREX
+	b	irq_handler @ irq
+	b	firq_handler @ firq
+
+irq_handler:
+firq_handler:
+	ldr	sp, =irqstack
+	add	sp, sp, #(4*1024)
+
+	@ Save registers
+	stmda	sp!, {r0 - r12}
+	stmda	sp!, {lr}
+
+	@ FIXME Find interrupt id and dispatch to the correct handler.
+	@ If event_irq
+	ldr	r0, IRQ_handler
+	cmp	r0, #0
+	beq	. @ If no IRQ handler was setup, just get stuck here!
+
+	adr	lr, 1f
+	mov	pc, r0
+1:
+	@bl	do_hypervisor_callback
+
+	@ Restore registers
+	ldmib	sp!, {lr}
+	ldmib	sp!, {r0 - r12}
+
+	@ Return from IRQ
+	subs	pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+	.long	0x0
+
+
+.globl __arch_switch_threads
+@ r0 = &prev->sp & r1 = &(next->sp)
+__arch_switch_threads:
+	@ store sp, ip for prev thread
+	str	sp, [r0] @ sp
+	str	lr, [r0, #4] @ ip
+	str	fp, [sp, #-4] @ store fp on the stack
+	@ Load sp, ip for next thread
+	ldr	sp, [r1] @ sp
+	ldr	lr, [r1, #4] @ ip
+	ldr	fp, [sp, #-4] @ restore fp from the stack
+	mov	pc, lr
+
+#if 0
+pagetables_code:
+	bl	build_pagetables
+
+	ldr	r2, =(page_dir+PHYS_START)
+	MCR	p15, 0, r2, c2, c0, 0	@ set ttbr0
+
+	@ Set access permission for domains
+	mov	r0, #0x3
+	MCR	p15, 0, r0, c3, c0, 0
+
+	ldr	r0, =mmu_switched
+
+	@ enable mmu / sctlr
+	isb
+	MRC	p15, 0, r1, c1, c0, 0	@ read sctlr
+	orr	r1, r1, #0x1
+	MCR	p15, 0, r1, c1, c0, 0	@ write sctlr
+	MRC     p15, 0, r1, c0, c0, 0	@ read id reg
+
+	@ jump to the virtual address now
+	mov	pc, r0
+
+mmu_switched:
+	b	.
+
+build_pagetables:
+	ldr	r2, =(page_dir + PHYS_START)
+	ldr	r0, =(pagetable + PHYS_START + 1)
+	str	r0, [r2]
+
+	ldr	r2, =(pagetable + PHYS_START)
+	add	r1, r2, #1000
+
+	@ setup entry
+	ldr	r0, =(PHYS_START + 0x3)
+2:
+	str	r0, [r2], #4
+	add	r0, r0, #1 << 12
+	cmp	r2, r1
+	bne	2b
+	mov	pc, lr
+
+.pushsection .data
+.align	14
+page_dir:
+	.fill (1024), 4, 0x0
+pagetable:
+	.fill (1024*50), 4, 0x0
+.popsection
+#endif
diff --git a/extras/mini-os/arch/arm/divsi3.S b/extras/mini-os/arch/arm/divsi3.S
new file mode 100644
index 0000000..fa92233
--- /dev/null
+++ b/extras/mini-os/arch/arm/divsi3.S
@@ -0,0 +1,404 @@
+/*	$NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $	*/
+
+/*-
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define ENTRY_NP(symbol) \
+	.globl symbol;	\
+	symbol:
+
+#define END(symbol)
+
+/* 
+ * stack is aligned as there's a possibility of branching to L_overflow
+ * which makes a C call
+ */
+
+ENTRY_NP(__umodsi3)
+	stmfd	sp!, {lr}
+	sub	sp, sp, #4	/* align stack */
+	bl	.L_udivide
+	add	sp, sp, #4	/* unalign stack */
+	mov	r0, r1
+	ldmfd	sp!, {pc}
+END(__umodsi3)
+
+ENTRY_NP(__modsi3)
+	stmfd	sp!, {lr}
+	sub	sp, sp, #4	/* align stack */
+	bl	.L_divide
+	add	sp, sp, #4	/* unalign stack */
+	mov	r0, r1
+	ldmfd	sp!, {pc}
+
+.L_overflow:
+	/* XXX should cause a fatal error */
+	mvn	r0, #0
+	mov	pc, lr
+
+END(__modsi3)
+
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_uidiv)
+ENTRY_NP(__aeabi_uidivmod)
+#endif
+ENTRY_NP(__udivsi3)
+.L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
+	eor     r0, r1, r0 
+	eor     r1, r0, r1 
+	eor     r0, r1, r0 
+					/* r0 = r1 / r0; r1 = r1 % r0 */
+	cmp	r0, #1
+	bcc	.L_overflow
+	beq	.L_divide_l0
+	mov	ip, #0
+	movs	r1, r1
+	bpl	.L_divide_l1
+	orr	ip, ip, #0x20000000	/* ip bit 0x20000000 = -ve r1 */
+	movs	r1, r1, lsr #1
+	orrcs	ip, ip, #0x10000000	/* ip bit 0x10000000 = bit 0 of r1 */
+	b	.L_divide_l1
+
+.L_divide_l0:				/* r0 == 1 */
+	mov	r0, r1
+	mov	r1, #0
+	mov	pc, lr
+#ifdef __ARM_EABI__
+END(__aeabi_uidiv)
+END(__aeabi_uidivmod)
+#endif
+END(__udivsi3)
+
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_idiv)
+ENTRY_NP(__aeabi_idivmod)
+#endif
+ENTRY_NP(__divsi3)
+.L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
+	eor     r0, r1, r0 
+	eor     r1, r0, r1 
+	eor     r0, r1, r0 
+					/* r0 = r1 / r0; r1 = r1 % r0 */
+	cmp	r0, #1
+	bcc	.L_overflow
+	beq	.L_divide_l0
+	ands	ip, r0, #0x80000000
+	rsbmi	r0, r0, #0
+	ands	r2, r1, #0x80000000
+	eor	ip, ip, r2
+	rsbmi	r1, r1, #0
+	orr	ip, r2, ip, lsr #1	/* ip bit 0x40000000 = -ve division */
+					/* ip bit 0x80000000 = -ve remainder */
+
+.L_divide_l1:
+	mov	r2, #1
+	mov	r3, #0
+
+	/*
+	 * If the highest bit of the dividend is set, we have to be
+	 * careful when shifting the divisor. Test this. 
+	 */
+	movs	r1,r1
+	bpl	.L_old_code
+
+	/*
+	 * At this point, the highest bit of r1 is known to be set.
+	 * We abuse this below in the tst instructions.
+	 */
+	tst	r1, r0 /*, lsl #0 */
+	bmi	.L_divide_b1
+	tst	r1, r0, lsl #1
+	bmi	.L_divide_b2
+	tst	r1, r0, lsl #2
+	bmi	.L_divide_b3
+	tst	r1, r0, lsl #3
+	bmi	.L_divide_b4
+	tst	r1, r0, lsl #4
+	bmi	.L_divide_b5
+	tst	r1, r0, lsl #5
+	bmi	.L_divide_b6
+	tst	r1, r0, lsl #6
+	bmi	.L_divide_b7
+	tst	r1, r0, lsl #7
+	bmi	.L_divide_b8
+	tst	r1, r0, lsl #8
+	bmi	.L_divide_b9
+	tst	r1, r0, lsl #9
+	bmi	.L_divide_b10
+	tst	r1, r0, lsl #10
+	bmi	.L_divide_b11
+	tst	r1, r0, lsl #11
+	bmi	.L_divide_b12
+	tst	r1, r0, lsl #12
+	bmi	.L_divide_b13
+	tst	r1, r0, lsl #13
+	bmi	.L_divide_b14
+	tst	r1, r0, lsl #14
+	bmi	.L_divide_b15
+	tst	r1, r0, lsl #15
+	bmi	.L_divide_b16
+	tst	r1, r0, lsl #16
+	bmi	.L_divide_b17
+	tst	r1, r0, lsl #17
+	bmi	.L_divide_b18
+	tst	r1, r0, lsl #18
+	bmi	.L_divide_b19
+	tst	r1, r0, lsl #19
+	bmi	.L_divide_b20
+	tst	r1, r0, lsl #20
+	bmi	.L_divide_b21
+	tst	r1, r0, lsl #21
+	bmi	.L_divide_b22
+	tst	r1, r0, lsl #22
+	bmi	.L_divide_b23
+	tst	r1, r0, lsl #23
+	bmi	.L_divide_b24
+	tst	r1, r0, lsl #24
+	bmi	.L_divide_b25
+	tst	r1, r0, lsl #25
+	bmi	.L_divide_b26
+	tst	r1, r0, lsl #26
+	bmi	.L_divide_b27
+	tst	r1, r0, lsl #27
+	bmi	.L_divide_b28
+	tst	r1, r0, lsl #28
+	bmi	.L_divide_b29
+	tst	r1, r0, lsl #29
+	bmi	.L_divide_b30
+	tst	r1, r0, lsl #30
+	bmi	.L_divide_b31
+/*
+ * instead of:
+ *	tst	r1, r0, lsl #31
+ *	bmi	.L_divide_b32
+ */
+	b	.L_divide_b32
+
+.L_old_code:
+	cmp	r1, r0
+	bcc	.L_divide_b0
+	cmp	r1, r0, lsl #1
+	bcc	.L_divide_b1
+	cmp	r1, r0, lsl #2
+	bcc	.L_divide_b2
+	cmp	r1, r0, lsl #3
+	bcc	.L_divide_b3
+	cmp	r1, r0, lsl #4
+	bcc	.L_divide_b4
+	cmp	r1, r0, lsl #5
+	bcc	.L_divide_b5
+	cmp	r1, r0, lsl #6
+	bcc	.L_divide_b6
+	cmp	r1, r0, lsl #7
+	bcc	.L_divide_b7
+	cmp	r1, r0, lsl #8
+	bcc	.L_divide_b8
+	cmp	r1, r0, lsl #9
+	bcc	.L_divide_b9
+	cmp	r1, r0, lsl #10
+	bcc	.L_divide_b10
+	cmp	r1, r0, lsl #11
+	bcc	.L_divide_b11
+	cmp	r1, r0, lsl #12
+	bcc	.L_divide_b12
+	cmp	r1, r0, lsl #13
+	bcc	.L_divide_b13
+	cmp	r1, r0, lsl #14
+	bcc	.L_divide_b14
+	cmp	r1, r0, lsl #15
+	bcc	.L_divide_b15
+	cmp	r1, r0, lsl #16
+	bcc	.L_divide_b16
+	cmp	r1, r0, lsl #17
+	bcc	.L_divide_b17
+	cmp	r1, r0, lsl #18
+	bcc	.L_divide_b18
+	cmp	r1, r0, lsl #19
+	bcc	.L_divide_b19
+	cmp	r1, r0, lsl #20
+	bcc	.L_divide_b20
+	cmp	r1, r0, lsl #21
+	bcc	.L_divide_b21
+	cmp	r1, r0, lsl #22
+	bcc	.L_divide_b22
+	cmp	r1, r0, lsl #23
+	bcc	.L_divide_b23
+	cmp	r1, r0, lsl #24
+	bcc	.L_divide_b24
+	cmp	r1, r0, lsl #25
+	bcc	.L_divide_b25
+	cmp	r1, r0, lsl #26
+	bcc	.L_divide_b26
+	cmp	r1, r0, lsl #27
+	bcc	.L_divide_b27
+	cmp	r1, r0, lsl #28
+	bcc	.L_divide_b28
+	cmp	r1, r0, lsl #29
+	bcc	.L_divide_b29
+	cmp	r1, r0, lsl #30
+	bcc	.L_divide_b30
+.L_divide_b32:
+	cmp	r1, r0, lsl #31
+	subhs	r1, r1,r0, lsl #31
+	addhs	r3, r3,r2, lsl #31
+.L_divide_b31:
+	cmp	r1, r0, lsl #30
+	subhs	r1, r1,r0, lsl #30
+	addhs	r3, r3,r2, lsl #30
+.L_divide_b30:
+	cmp	r1, r0, lsl #29
+	subhs	r1, r1,r0, lsl #29
+	addhs	r3, r3,r2, lsl #29
+.L_divide_b29:
+	cmp	r1, r0, lsl #28
+	subhs	r1, r1,r0, lsl #28
+	addhs	r3, r3,r2, lsl #28
+.L_divide_b28:
+	cmp	r1, r0, lsl #27
+	subhs	r1, r1,r0, lsl #27
+	addhs	r3, r3,r2, lsl #27
+.L_divide_b27:
+	cmp	r1, r0, lsl #26
+	subhs	r1, r1,r0, lsl #26
+	addhs	r3, r3,r2, lsl #26
+.L_divide_b26:
+	cmp	r1, r0, lsl #25
+	subhs	r1, r1,r0, lsl #25
+	addhs	r3, r3,r2, lsl #25
+.L_divide_b25:
+	cmp	r1, r0, lsl #24
+	subhs	r1, r1,r0, lsl #24
+	addhs	r3, r3,r2, lsl #24
+.L_divide_b24:
+	cmp	r1, r0, lsl #23
+	subhs	r1, r1,r0, lsl #23
+	addhs	r3, r3,r2, lsl #23
+.L_divide_b23:
+	cmp	r1, r0, lsl #22
+	subhs	r1, r1,r0, lsl #22
+	addhs	r3, r3,r2, lsl #22
+.L_divide_b22:
+	cmp	r1, r0, lsl #21
+	subhs	r1, r1,r0, lsl #21
+	addhs	r3, r3,r2, lsl #21
+.L_divide_b21:
+	cmp	r1, r0, lsl #20
+	subhs	r1, r1,r0, lsl #20
+	addhs	r3, r3,r2, lsl #20
+.L_divide_b20:
+	cmp	r1, r0, lsl #19
+	subhs	r1, r1,r0, lsl #19
+	addhs	r3, r3,r2, lsl #19
+.L_divide_b19:
+	cmp	r1, r0, lsl #18
+	subhs	r1, r1,r0, lsl #18
+	addhs	r3, r3,r2, lsl #18
+.L_divide_b18:
+	cmp	r1, r0, lsl #17
+	subhs	r1, r1,r0, lsl #17
+	addhs	r3, r3,r2, lsl #17
+.L_divide_b17:
+	cmp	r1, r0, lsl #16
+	subhs	r1, r1,r0, lsl #16
+	addhs	r3, r3,r2, lsl #16
+.L_divide_b16:
+	cmp	r1, r0, lsl #15
+	subhs	r1, r1,r0, lsl #15
+	addhs	r3, r3,r2, lsl #15
+.L_divide_b15:
+	cmp	r1, r0, lsl #14
+	subhs	r1, r1,r0, lsl #14
+	addhs	r3, r3,r2, lsl #14
+.L_divide_b14:
+	cmp	r1, r0, lsl #13
+	subhs	r1, r1,r0, lsl #13
+	addhs	r3, r3,r2, lsl #13
+.L_divide_b13:
+	cmp	r1, r0, lsl #12
+	subhs	r1, r1,r0, lsl #12
+	addhs	r3, r3,r2, lsl #12
+.L_divide_b12:
+	cmp	r1, r0, lsl #11
+	subhs	r1, r1,r0, lsl #11
+	addhs	r3, r3,r2, lsl #11
+.L_divide_b11:
+	cmp	r1, r0, lsl #10
+	subhs	r1, r1,r0, lsl #10
+	addhs	r3, r3,r2, lsl #10
+.L_divide_b10:
+	cmp	r1, r0, lsl #9
+	subhs	r1, r1,r0, lsl #9
+	addhs	r3, r3,r2, lsl #9
+.L_divide_b9:
+	cmp	r1, r0, lsl #8
+	subhs	r1, r1,r0, lsl #8
+	addhs	r3, r3,r2, lsl #8
+.L_divide_b8:
+	cmp	r1, r0, lsl #7
+	subhs	r1, r1,r0, lsl #7
+	addhs	r3, r3,r2, lsl #7
+.L_divide_b7:
+	cmp	r1, r0, lsl #6
+	subhs	r1, r1,r0, lsl #6
+	addhs	r3, r3,r2, lsl #6
+.L_divide_b6:
+	cmp	r1, r0, lsl #5
+	subhs	r1, r1,r0, lsl #5
+	addhs	r3, r3,r2, lsl #5
+.L_divide_b5:
+	cmp	r1, r0, lsl #4
+	subhs	r1, r1,r0, lsl #4
+	addhs	r3, r3,r2, lsl #4
+.L_divide_b4:
+	cmp	r1, r0, lsl #3
+	subhs	r1, r1,r0, lsl #3
+	addhs	r3, r3,r2, lsl #3
+.L_divide_b3:
+	cmp	r1, r0, lsl #2
+	subhs	r1, r1,r0, lsl #2
+	addhs	r3, r3,r2, lsl #2
+.L_divide_b2:
+	cmp	r1, r0, lsl #1
+	subhs	r1, r1,r0, lsl #1
+	addhs	r3, r3,r2, lsl #1
+.L_divide_b1:
+	cmp	r1, r0
+	subhs	r1, r1, r0
+	addhs	r3, r3, r2
+.L_divide_b0:
+
+	tst	ip, #0x20000000
+	bne	.L_udivide_l1
+	mov	r0, r3
+	cmp	ip, #0
+	rsbmi	r1, r1, #0
+	movs	ip, ip, lsl #1
+	bicmi	r0, r0, #0x80000000	/* Fix incase we divided 0x80000000 */
+	rsbmi	r0, r0, #0
+	mov	pc, lr
+
+.L_udivide_l1:
+	tst	ip, #0x10000000
+	mov	r1, r1, lsl #1
+	orrne	r1, r1, #1
+	mov	r3, r3, lsl #1
+	cmp	r1, r0
+	subhs	r1, r1, r0
+	addhs	r3, r3, r2
+	mov	r0, r3
+	mov	pc, lr
+END(__aeabi_idiv)
+END(__aeabi_idivmod)
+END(__divsi3)
+
diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..6e579e7
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,24 @@
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/hypervisor.h>
+
+static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
+{
+	printk("Received a virq_debug event\n");
+}
+
+evtchn_port_t debug_port = -1;
+void arch_init_events(void) {
+	debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
+	if(debug_port == -1)
+		BUG();
+	unmask_evtchn(debug_port);
+}
+
+void arch_fini_events(void) {
+	if(debug_port != -1)
+	{
+		mask_evtchn(debug_port);
+		unbind_evtchn(debug_port);
+	}
+}
diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
new file mode 100644
index 0000000..e2f21c4
--- /dev/null
+++ b/extras/mini-os/arch/arm/hypercalls32.S
@@ -0,0 +1,88 @@
+#define __HYPERVISOR_set_trap_table        0
+#define __HYPERVISOR_mmu_update            1
+#define __HYPERVISOR_set_gdt               2
+#define __HYPERVISOR_stack_switch          3
+#define __HYPERVISOR_set_callbacks         4
+#define __HYPERVISOR_fpu_taskswitch        5
+#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op           7
+#define __HYPERVISOR_set_debugreg          8
+#define __HYPERVISOR_get_debugreg          9
+#define __HYPERVISOR_update_descriptor    10
+#define __HYPERVISOR_memory_op            12
+#define __HYPERVISOR_multicall            13
+#define __HYPERVISOR_update_va_mapping    14
+#define __HYPERVISOR_set_timer_op         15
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+#define __HYPERVISOR_xen_version          17
+#define __HYPERVISOR_console_io           18
+#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
+#define __HYPERVISOR_grant_table_op       20
+#define __HYPERVISOR_vm_assist            21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret                 23 /* x86 only */
+#define __HYPERVISOR_vcpu_op              24
+#define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op            26
+#define __HYPERVISOR_xsm_op               27
+#define __HYPERVISOR_nmi_op               28
+#define __HYPERVISOR_sched_op             29
+#define __HYPERVISOR_callback_op          30
+#define __HYPERVISOR_xenoprof_op          31
+#define __HYPERVISOR_event_channel_op     32
+#define __HYPERVISOR_physdev_op           33
+#define __HYPERVISOR_hvm_op               34
+#define __HYPERVISOR_sysctl               35
+#define __HYPERVISOR_domctl               36
+#define __HYPERVISOR_kexec_op             37
+#define __HYPERVISOR_tmem_op              38
+#define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
+
+
+
+#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF)
+
+#define XEN_IMM 0xEA1
+
+#define HYPERCALL_SIMPLE(hypercall)		\
+.globl HYPERVISOR_##hypercall;			\
+.align 4,0x90;					\
+HYPERVISOR_##hypercall:				\
+        mov r12, #__HYPERVISOR_##hypercall;	\
+        __HVC(XEN_IMM);				\
+        mov pc, lr;
+
+#define _hypercall0 HYPERCALL_SIMPLE
+#define _hypercall1 HYPERCALL_SIMPLE
+#define _hypercall2 HYPERCALL_SIMPLE
+#define _hypercall3 HYPERCALL_SIMPLE
+#define _hypercall4 HYPERCALL_SIMPLE
+
+_hypercall1(set_trap_table);
+_hypercall4(mmu_update);
+_hypercall4(mmuext_op);
+_hypercall2(set_gdt);
+_hypercall2(stack_switch);
+_hypercall3(set_callbacks);
+_hypercall1(fpu_taskswitch);
+_hypercall2(sched_op);
+_hypercall1(set_timer_op);
+_hypercall2(set_debugreg);
+_hypercall1(get_debugreg);
+_hypercall2(update_descriptor);
+_hypercall2(memory_op);
+_hypercall2(multicall);
+_hypercall3(update_va_mapping);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall4(update_va_mapping_otherdomain);
+_hypercall2(vm_assist);
+_hypercall3(vcpu_op);
+_hypercall2(set_segment_base);
+_hypercall2(nmi_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
diff --git a/extras/mini-os/arch/arm/ldivmod.S b/extras/mini-os/arch/arm/ldivmod.S
new file mode 100644
index 0000000..7529826
--- /dev/null
+++ b/extras/mini-os/arch/arm/ldivmod.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define ENTRY_NP(symbol) \
+	.globl symbol;	\
+	symbol:
+
+#define END(symbol)
+
+/*
+ * These calculate:
+ * q = n / m 
+ * With a remainer r.
+ *
+ * They take n in {r0, r1} and m in {r2, r3} then pass them into the
+ * helper function. The hepler functions return q in {r0, r1} as
+ * required by the API spec however r is returned on the stack. The
+ * ABI required us to return r in {r2, r3}.
+ *
+ * We need to allocate 8 bytes on the stack to store r, the link
+ * register, and a pointer to the space where the helper function
+ * will write r to. After returning from the helper fuinction we load
+ * the old link register and r from the stack and return.
+ */
+ENTRY_NP(__aeabi_ldivmod)
+	sub	sp, sp, #8	/* Space for the remainder */
+	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
+	bl	__kern_ldivmod
+	ldr	lr, [sp, #4]	/* Restore lr */
+	add	sp, sp, #8	/* Move sp to the remainder value */
+	ldmfd	sp!, {r2, r3}	/* Load the remainder */
+	mov	pc, lr
+END(__aeabi_ldivmod)
+
+ENTRY_NP(__aeabi_uldivmod)
+	sub	sp, sp, #8	/* Space for the remainder */
+	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
+	bl	__qdivrem
+	ldr	lr, [sp, #4]	/* Restore lr */
+	add	sp, sp, #8	/* Move sp to the remainder value */
+	ldmfd	sp!, {r2, r3}	/* Load the remainder */
+	mov	pc, lr
+END(__aeabi_uldivmod)
diff --git a/extras/mini-os/arch/arm/ldivmod_helper.c b/extras/mini-os/arch/arm/ldivmod_helper.c
new file mode 100644
index 0000000..f4dde48
--- /dev/null
+++ b/extras/mini-os/arch/arm/ldivmod_helper.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <mini-os/types.h>
+
+u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+        u_quad_t ua, ub, uq;
+        int neg;
+
+        if (a < 0)
+                ua = -(u_quad_t)a, neg = 1;
+        else
+                ua = a, neg = 0;
+        if (b < 0)
+                ub = -(u_quad_t)b, neg ^= 1;
+        else
+                ub = b;
+        uq = __qdivrem(ua, ub, (u_quad_t *)0);
+        return (neg ? -uq : uq);
+}
+
+/*
+ * Helper for __aeabi_ldivmod.
+ * TODO: __divdi3 calls __qdivrem. We should do the same and use the
+ * remainder value rather than re-calculating it.
+ */
+long long __kern_ldivmod(long long, long long, long long *);
+
+long long
+__kern_ldivmod(long long n, long long m, long long *rem)
+{
+	long long q;
+
+	q = __divdi3(n, m);	/* q = n / m */
+	*rem = n - m * q;
+
+	return q;
+}
diff --git a/extras/mini-os/arch/arm/minios-arm32.lds b/extras/mini-os/arch/arm/minios-arm32.lds
new file mode 100755
index 0000000..793f0de
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,73 @@
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x80008000;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.gnu.warning)
+	} = 0x9090
+
+  _etext = .;			/* End of text section */
+
+  .rodata : { *(.rodata) *(.rodata.*) }
+  . = ALIGN(4096);
+  _erodata = .;
+
+  /* newlib initialization functions */
+  . = ALIGN(32 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
+
+  .ctors : {
+        __CTOR_LIST__ = .;
+        *(.ctors)
+	CONSTRUCTORS
+        LONG(0)
+        __CTOR_END__ = .;
+        }
+
+  .dtors : {
+        __DTOR_LIST__ = .;
+        *(.dtors)
+        LONG(0)
+        __DTOR_END__ = .;
+        }
+
+  .data : {			/* Data */
+	*(.data)
+	}
+
+  _edata = .;			/* End of data section */
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+        *(.app.bss)
+	}
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.text.exit)
+	*(.data.exit)
+	*(.exitcall.exit)
+	}
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
new file mode 100644
index 0000000..7e7ff06
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,44 @@
+#include <console.h>
+#include <arm/arch_mm.h>
+
+#define PHYS_START (0x80008000 + (1000 * 4 * 1024))
+#define PHYS_SIZE (40*1024*1024)
+
+static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
+{
+	// FIXME Create small pages descriptors here instead of the 1M superpages created earlier.
+	return;
+}
+
+unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
+{
+	// FIXME
+	BUG();
+}
+
+void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
+{
+	printk("    _text: %p(VA)\n", &_text);
+	printk("    _etext: %p(VA)\n", &_etext);
+	printk("    _erodata: %p(VA)\n", &_erodata);
+	printk("    _edata: %p(VA)\n", &_edata);
+	printk("    stack start: %p(VA)\n", stack);
+	printk("    _end: %p(VA)\n", &_end);
+
+	// FIXME Get from dt!
+	*start_pfn_p = (((unsigned long)&_end) >> PAGE_SHIFT) + 1000;
+	*max_pfn_p = ((unsigned long)&_end + PHYS_SIZE) >> PAGE_SHIFT;
+
+	printk("    start_pfn: %lx\n", *start_pfn_p);
+	printk("    max_pfn: %lx\n", *max_pfn_p);
+
+	build_pagetable(start_pfn_p, max_pfn_p);
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+}
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+}
diff --git a/extras/mini-os/arch/arm/qdivrem.c b/extras/mini-os/arch/arm/qdivrem.c
new file mode 100644
index 0000000..0ab5733
--- /dev/null
+++ b/extras/mini-os/arch/arm/qdivrem.c
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <mini-os/types.h>
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#define	B	(1 << HALF_BITS)	/* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define	COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+__shl(register digit *p, register int len, register int sh)
+{
+	register int i;
+
+	for (i = 0; i < len; i++)
+		p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+	p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+	union uu tmp;
+	digit *u, *v, *q;
+	register digit v1, v2;
+	u_long qhat, rhat, t;
+	int m, n, d, j, i;
+	digit uspace[5], vspace[5], qspace[5];
+
+	/*
+	 * Take care of special cases: divide by zero, and u < v.
+	 */
+	if (vq == 0) {
+		/* divide by zero. */
+		static volatile const unsigned int zero = 0;
+
+		tmp.ul[H] = tmp.ul[L] = 1 / zero;
+		if (arq)
+			*arq = uq;
+		return (tmp.q);
+	}
+	if (uq < vq) {
+		if (arq)
+			*arq = uq;
+		return (0);
+	}
+	u = &uspace[0];
+	v = &vspace[0];
+	q = &qspace[0];
+
+	/*
+	 * Break dividend and divisor into digits in base B, then
+	 * count leading zeros to determine m and n.  When done, we
+	 * will have:
+	 *	u = (u[1]u[2]...u[m+n]) sub B
+	 *	v = (v[1]v[2]...v[n]) sub B
+	 *	v[1] != 0
+	 *	1 < n <= 4 (if n = 1, we use a different division algorithm)
+	 *	m >= 0 (otherwise u < v, which we already checked)
+	 *	m + n = 4
+	 * and thus
+	 *	m = 4 - n <= 2
+	 */
+	tmp.uq = uq;
+	u[0] = 0;
+	u[1] = HHALF(tmp.ul[H]);
+	u[2] = LHALF(tmp.ul[H]);
+	u[3] = HHALF(tmp.ul[L]);
+	u[4] = LHALF(tmp.ul[L]);
+	tmp.uq = vq;
+	v[1] = HHALF(tmp.ul[H]);
+	v[2] = LHALF(tmp.ul[H]);
+	v[3] = HHALF(tmp.ul[L]);
+	v[4] = LHALF(tmp.ul[L]);
+	for (n = 4; v[1] == 0; v++) {
+		if (--n == 1) {
+			u_long rbj;	/* r*B+u[j] (not root boy jim) */
+			digit q1, q2, q3, q4;
+
+			/*
+			 * Change of plan, per exercise 16.
+			 *	r = 0;
+			 *	for j = 1..4:
+			 *		q[j] = floor((r*B + u[j]) / v),
+			 *		r = (r*B + u[j]) % v;
+			 * We unroll this completely here.
+			 */
+			t = v[2];	/* nonzero, by definition */
+			q1 = u[1] / t;
+			rbj = COMBINE(u[1] % t, u[2]);
+			q2 = rbj / t;
+			rbj = COMBINE(rbj % t, u[3]);
+			q3 = rbj / t;
+			rbj = COMBINE(rbj % t, u[4]);
+			q4 = rbj / t;
+			if (arq)
+				*arq = rbj % t;
+			tmp.ul[H] = COMBINE(q1, q2);
+			tmp.ul[L] = COMBINE(q3, q4);
+			return (tmp.q);
+		}
+	}
+
+	/*
+	 * By adjusting q once we determine m, we can guarantee that
+	 * there is a complete four-digit quotient at &qspace[1] when
+	 * we finally stop.
+	 */
+	for (m = 4 - n; u[1] == 0; u++)
+		m--;
+	for (i = 4 - m; --i >= 0;)
+		q[i] = 0;
+	q += 4 - m;
+
+	/*
+	 * Here we run Program D, translated from MIX to C and acquiring
+	 * a few minor changes.
+	 *
+	 * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+	 */
+	d = 0;
+	for (t = v[1]; t < B / 2; t <<= 1)
+		d++;
+	if (d > 0) {
+		__shl(&u[0], m + n, d);		/* u <<= d */
+		__shl(&v[1], n - 1, d);		/* v <<= d */
+	}
+	/*
+	 * D2: j = 0.
+	 */
+	j = 0;
+	v1 = v[1];	/* for D3 -- note that v[1..n] are constant */
+	v2 = v[2];	/* for D3 */
+	do {
+		register digit uj0, uj1, uj2;
+
+		/*
+		 * D3: Calculate qhat (\^q, in TeX notation).
+		 * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+		 * let rhat = (u[j]*B + u[j+1]) mod v[1].
+		 * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+		 * decrement qhat and increase rhat correspondingly.
+		 * Note that if rhat >= B, v[2]*qhat < rhat*B.
+		 */
+		uj0 = u[j + 0];	/* for D3 only -- note that u[j+...] change */
+		uj1 = u[j + 1];	/* for D3 only */
+		uj2 = u[j + 2];	/* for D3 only */
+		if (uj0 == v1) {
+			qhat = B;
+			rhat = uj1;
+			goto qhat_too_big;
+		} else {
+			u_long nn = COMBINE(uj0, uj1);
+			qhat = nn / v1;
+			rhat = nn % v1;
+		}
+		while (v2 * qhat > COMBINE(rhat, uj2)) {
+	qhat_too_big:
+			qhat--;
+			if ((rhat += v1) >= B)
+				break;
+		}
+		/*
+		 * D4: Multiply and subtract.
+		 * The variable `t' holds any borrows across the loop.
+		 * We split this up so that we do not require v[0] = 0,
+		 * and to eliminate a final special case.
+		 */
+		for (t = 0, i = n; i > 0; i--) {
+			t = u[i + j] - v[i] * qhat - t;
+			u[i + j] = LHALF(t);
+			t = (B - HHALF(t)) & (B - 1);
+		}
+		t = u[j] - t;
+		u[j] = LHALF(t);
+		/*
+		 * D5: test remainder.
+		 * There is a borrow if and only if HHALF(t) is nonzero;
+		 * in that (rare) case, qhat was too large (by exactly 1).
+		 * Fix it by adding v[1..n] to u[j..j+n].
+		 */
+		if (HHALF(t)) {
+			qhat--;
+			for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+				t += u[i + j] + v[i];
+				u[i + j] = LHALF(t);
+				t = HHALF(t);
+			}
+			u[j] = LHALF(u[j] + t);
+		}
+		q[j] = qhat;
+	} while (++j <= m);		/* D7: loop on j. */
+
+	/*
+	 * If caller wants the remainder, we have to calculate it as
+	 * u[m..m+n] >> d (this is at most n digits and thus fits in
+	 * u[m+1..m+n], but we may need more source digits).
+	 */
+	if (arq) {
+		if (d) {
+			for (i = m + n; i > m; --i)
+				u[i] = (u[i] >> d) |
+				    LHALF(u[i - 1] << (HALF_BITS - d));
+			u[i] = 0;
+		}
+		tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+		tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+		*arq = tmp.q;
+	}
+
+	tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+	tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+	return (tmp.q);
+}
diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..e490105
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,32 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+
+
+/* Architecture specific setup of thread creation */
+struct thread* arch_create_thread(char *name, void (*function)(void *),
+                                  void *data)
+{
+    struct thread *thread;
+
+    thread = xmalloc(struct thread);
+    /* We can't use lazy allocation here since the trap handler runs on the stack */
+    thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
+    thread->name = name;
+    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
+            thread->stack);
+
+    thread->sp = (unsigned long)thread->stack + STACK_SIZE;
+    /* Save pointer to the thread on the stack, used by current macro */
+    *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+    thread->ip = (unsigned long) function;
+    /* FIXME thread->r0 = (unsigned long)data; */
+
+    return thread;
+}
+
+void run_idle_thread(void)
+{
+	__asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), "r"(idle_thread->ip));
+	/* Never arrive here! */
+}
diff --git a/extras/mini-os/arch/arm/setup.c b/extras/mini-os/arch/arm/setup.c
new file mode 100644
index 0000000..f0b2f47
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,55 @@
+#include <mini-os/os.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <hypervisor.h>
+#include <arm/arch_mm.h>
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ */
+union start_info_union start_info_union;
+
+/*
+ * Shared page for communicating with the hypervisor.
+ * Events flags go here, for example.
+ */
+shared_info_t *HYPERVISOR_shared_info;
+
+extern char shared_info_page[PAGE_SIZE];
+
+void start_kernel(void);
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void arch_init(void *dtb_pointer)
+{
+    struct xen_add_to_physmap xatp;
+
+    memset(&__bss_start, 0, &_end - &__bss_start);
+
+    printk("dtb_pointer : %x\n", dtb_pointer);
+
+    /* Map shared_info page */
+	xatp.domid = DOMID_SELF;
+	xatp.idx = 0;
+	xatp.space = XENMAPSPACE_shared_info;
+	xatp.gpfn = virt_to_pfn(shared_info_page);
+	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
+		BUG();
+	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
+
+	start_kernel();
+}
+
+void
+arch_fini(void)
+{
+
+}
+
+void
+arch_do_exit(void)
+{
+}
diff --git a/extras/mini-os/arch/arm/time.c b/extras/mini-os/arch/arm/time.c
new file mode 100644
index 0000000..6dba1fe
--- /dev/null
+++ b/extras/mini-os/arch/arm/time.c
@@ -0,0 +1,232 @@
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/events.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <mini-os/time.h>
+#include <mini-os/lib.h>
+
+//#define VTIMER_DEBUG
+#ifdef VTIMER_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
+/************************************************************************
+ * Time functions
+ *************************************************************************/
+
+/* These are peridically updated in shared_info, and then copied here. */
+struct shadow_time_info {
+	uint64_t tsc_timestamp;     /* TSC at last update of time vals.  */
+	uint64_t system_timestamp;  /* Time, in nanosecs, since boot.    */
+	uint32_t tsc_to_nsec_mul;
+	uint32_t tsc_to_usec_mul;
+	int tsc_shift;
+	uint32_t version;
+};
+static struct timespec shadow_ts;
+static uint32_t shadow_ts_version;
+
+static struct shadow_time_info shadow;
+
+#define HANDLE_USEC_OVERFLOW(_tv)          \
+    do {                                   \
+        while ( (_tv)->tv_usec >= 1000000 ) \
+        {                                  \
+            (_tv)->tv_usec -= 1000000;      \
+            (_tv)->tv_sec++;                \
+        }                                  \
+    } while ( 0 )
+
+static inline int time_values_up_to_date(void)
+{
+	struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
+
+	return (shadow.version == src->version);
+}
+
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift)
+{
+	BUG();
+	return 0;
+}
+
+
+static unsigned long get_nsec_offset(void)
+{
+	return 0;
+#if FIXME
+	uint64_t now, delta;
+	rdtscll(now);
+	delta = now - shadow.tsc_timestamp;
+	return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
+#endif
+}
+
+
+static void get_time_values_from_xen(void)
+{
+	struct vcpu_time_info    *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
+
+ 	do {
+		shadow.version = src->version;
+		rmb();
+		shadow.tsc_timestamp     = src->tsc_timestamp;
+		shadow.system_timestamp  = src->system_time;
+		shadow.tsc_to_nsec_mul   = src->tsc_to_system_mul;
+		shadow.tsc_shift         = src->tsc_shift;
+		rmb();
+	}
+	while ((src->version & 1) | (shadow.version ^ src->version));
+
+	shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
+}
+
+
+
+
+/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+ *		Note: This function is required to return accurate
+ *		time even in the absence of multiple timer ticks.
+ */
+uint64_t monotonic_clock(void)
+{
+	uint64_t time;
+	uint32_t local_time_version;
+
+	do {
+		local_time_version = shadow.version;
+		rmb();
+		time = shadow.system_timestamp + get_nsec_offset();
+        if (!time_values_up_to_date())
+			get_time_values_from_xen();
+		rmb();
+	} while (local_time_version != shadow.version);
+
+	return time;
+}
+
+static void update_wallclock(void)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+
+	do {
+		shadow_ts_version = s->wc_version;
+		rmb();
+		shadow_ts.tv_sec  = s->wc_sec;
+		shadow_ts.tv_nsec = s->wc_nsec;
+		rmb();
+	}
+	while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
+}
+
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+    uint64_t nsec = monotonic_clock();
+    nsec += shadow_ts.tv_nsec;
+
+
+    tv->tv_sec = shadow_ts.tv_sec;
+    tv->tv_sec += NSEC_TO_SEC(nsec);
+    tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
+
+    return 0;
+}
+
+
+void block_domain(s_time_t until)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ASSERT(irqs_disabled());
+    if(monotonic_clock() < until)
+    {
+        HYPERVISOR_set_timer_op(until);
+        HYPERVISOR_sched_op(SCHEDOP_block, 0);
+        local_irq_disable();
+    }
+}
+
+
+/*
+ * Just a dummy
+ */
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign)
+{
+	DEBUG("Timer kick\n");
+    get_time_values_from_xen();
+	update_wallclock();
+}
+
+#define VTIMER_TICK 0x10000000
+void increment_vtimer_compare(uint64_t inc) {
+	uint32_t x, y;
+	uint64_t value;
+	__asm__ __volatile__("mrrc p15, 1, %0, %1, c14\n"
+			"isb":"=r"(x), "=r"(y));
+
+	// CompareValue = Counter + VTIMER_TICK
+	value = (0xFFFFFFFFFFFFFFFFULL & x) | ((0xFFFFFFFFFFFFFFFFULL & y) << 32);
+	DEBUG("Counter: %llx(x=%x and y=%x)\n", value, x, y);
+	value += inc;
+	DEBUG("New CompareValue : %llx\n", value);
+	x = 0xFFFFFFFFULL & value;
+	y = (value >> 32) & 0xFFFFFFFF;
+
+	__asm__ __volatile__("mcrr p15, 3, %0, %1, c14\n"
+			"isb"::"r"(x), "r"(y));
+
+	__asm__ __volatile__("mov %0, #0x1\n"
+				"mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+				"isb":"=r"(x));
+}
+
+static inline void enable_virtual_timer(void) {
+#if FIXME
+	uint32_t x, y;
+	uint64_t value;
+
+	__asm__ __volatile__("ldr %0, =0xffffffff\n"
+			"ldr %1, =0xffffffff\n"
+			"dsb\n"
+			"mcrr p15, 3, %0, %1, c14\n" /* set CompareValue to 0x0000ffff 0000ffff */
+			"isb\n"
+			"mov %0, #0x1\n"
+			"mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+			"isb":"=r"(x), "=r"(y));
+#else
+	increment_vtimer_compare(VTIMER_TICK);
+#endif
+}
+
+evtchn_port_t timer_port = -1;
+void arch_init_time(void)
+{
+	// FIXME: VIRQ_TIMER isn't supported under ARM, use ARM Generic Timer instead.
+    printk("Initialising timer interface\n");
+    timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0);
+    if(timer_port == -1)
+		BUG();
+    unmask_evtchn(timer_port);
+
+    enable_virtual_timer();
+}
+
+void arch_fini_time(void)
+{
+	if(timer_port != -1)
+	{
+		mask_evtchn(timer_port);
+		unbind_evtchn(timer_port);
+	}
+}
diff --git a/extras/mini-os/arch/arm/xenbus.c b/extras/mini-os/arch/arm/xenbus.c
new file mode 100644
index 0000000..76feabc
--- /dev/null
+++ b/extras/mini-os/arch/arm/xenbus.c
@@ -0,0 +1,36 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <xen/hvm/params.h>
+#include <xen/io/xs_wire.h>
+#include <mini-os/hypervisor.h>
+
+static inline int hvm_get_parameter(int idx, uint64_t *value)
+{
+	struct xen_hvm_param xhv;
+	int ret;
+
+	xhv.domid = DOMID_SELF;
+	xhv.index = idx;
+	ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+	if (ret < 0) {
+		BUG();
+	}
+	*value = xhv.value;
+	return ret;
+}
+
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {
+	uint64_t value;
+	uint64_t xenstore_pfn;
+
+	if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+		BUG();
+
+	*store_evtchn = (int)value;
+
+	if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+		BUG();
+	xenstore_pfn = (unsigned long)value;
+
+	*xenstore_buf = pfn_to_virt(xenstore_pfn);
+}
diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
new file mode 100644
index 0000000..87f8b77
--- /dev/null
+++ b/extras/mini-os/arch/x86/events.c
@@ -0,0 +1,28 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+
+#if defined(__x86_64__)
+char irqstack[2 * STACK_SIZE];
+
+static struct pda
+{
+    int irqcount;       /* offset 0 (used in x86_64.S) */
+    char *irqstackptr;  /*        8 */
+} cpu0_pda;
+#endif
+
+void arch_init_events(void) {
+#if defined(__x86_64__)
+    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
+    cpu0_pda.irqcount = -1;
+    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
+                                    & ~(STACK_SIZE - 1));
+#endif
+}
+
+void arch_fini_events(void) {
+#if defined(__x86_64__)
+    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 54046d3..6bb6d4b 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -28,6 +28,7 @@
 
 #include <mini-os/os.h>
 #include <mini-os/lib.h> /* for printk, memcpy */
+#include <xen/xen.h>
 
 /*
  * Shared page for communicating with the hypervisor.
@@ -87,14 +88,40 @@ static inline void sse_init(void) {
 #define sse_init()
 #endif
 
+
+void start_kernel(void);
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
 void
 arch_init(start_info_t *si)
 {
+    static char hello[] = "Bootstrapping...\n";
+
+    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
+
+    trap_init();
+
+    /* print out some useful information  */
+    printk("Xen Minimal OS!\n");
+    printk("  start_info: %p(VA)\n", si);
+    printk("    nr_pages: 0x%lx\n", si->nr_pages);
+    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
+    printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
+    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
+    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
+    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
+    printk("     mod_len: %lu\n", si->mod_len);
+    printk("       flags: 0x%x\n", (unsigned int)si->flags);
+    printk("    cmd_line: %s\n",
+           si->cmd_line ? (const char *)si->cmd_line : "NULL");
+
 	/*Initialize floating point unit */
-        fpu_init();
+	fpu_init();
 
-        /* Initialize SSE */
-        sse_init();
+	/* Initialize SSE */
+	sse_init();
 
 	/* Copy the start_info struct to a globally-accessible area. */
 	/* WARN: don't do printk before here, it uses information from
@@ -118,12 +145,15 @@ arch_init(start_info_t *si)
 		(unsigned long)failsafe_callback, 0);
 #endif
 
-
+	start_kernel();
 }
 
 void
 arch_fini(void)
 {
+	/* Reset traps */
+	trap_fini();
+
 #ifdef __i386__
 	HYPERVISOR_set_callbacks(0, 0, 0, 0);
 #else
@@ -132,9 +162,7 @@ arch_fini(void)
 }
 
 void
-arch_print_info(void)
+arch_do_exit(void)
 {
-	printk("  stack:      %p-%p\n", stack, stack + sizeof(stack));
+	stack_walk();
 }
-
-
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index 2c8d033..c57ee55 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -223,14 +223,14 @@ static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
 
 
 static evtchn_port_t port;
-void init_time(void)
+void arch_init_time(void)
 {
     printk("Initialising timer interface\n");
     port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
     unmask_evtchn(port);
 }
 
-void fini_time(void)
+void arch_fini_time(void)
 {
     /* Clear any pending timer */
     HYPERVISOR_set_timer_op(0);
diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index fb3e30a..b9aa392 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -20,7 +20,7 @@ _start:
         lss stack_start,%esp
         andl $(~(__STACK_SIZE-1)), %esp
         push %esi 
-        call start_kernel
+        call arch_init
 
 stack_start:
 	.long stack+(2*__STACK_SIZE), __KERNEL_SS
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index f022eb3..df3469e 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -21,7 +21,7 @@ _start:
         movq stack_start(%rip),%rsp
         andq $(~(__STACK_SIZE-1)), %rsp
         movq %rsi,%rdi
-        call start_kernel
+        call arch_init
 
 stack_start:
         .quad stack+(2*__STACK_SIZE)
diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c
new file mode 100644
index 0000000..5cda78d
--- /dev/null
+++ b/extras/mini-os/arch/x86/xenbus.c
@@ -0,0 +1,10 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/xmalloc.h>
+#include <xen/xen.h>
+#include <xen/io/xs_wire.h>
+
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {
+    *xenstore_buf = mfn_to_virt(start_info.store_mfn);
+    *store_evtchn = start_info.store_evtchn;
+}
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 5538bd4..c08fea9 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -157,7 +157,9 @@ void xprintk(const char *fmt, ...)
 void init_console(void)
 {   
     printk("Initialising console ... ");
+#ifndef __arm__
     xencons_ring_init();    
+#endif
     console_initialised = 1;
     /* This is also required to notify the daemon */
     printk("done.\n");
diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c
new file mode 100644
index 0000000..14301ae
--- /dev/null
+++ b/extras/mini-os/drivers/gic.c
@@ -0,0 +1,179 @@
+// ARM GIC implementation
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+
+//#define VGIC_DEBUG
+#ifdef VGIC_DEBUG
+#define DEBUG(_f, _a...) \
+    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+extern unsigned long IRQ_handler;
+
+struct gic {
+	volatile char *gicd_base;
+	volatile char *gicc_base;
+};
+
+static struct gic gic;
+
+// Distributor Interface
+#define GICD_CTLR		0x0
+#define GICD_ISENABLER	0x100
+#define GICD_PRIORITY	0x400
+#define GICD_ITARGETSR	0x800
+#define GICD_ICFGR		0xC00
+
+// CPU Interface
+#define GICC_CTLR	0x0
+#define GICC_PMR	0x4
+#define GICC_IAR	0xc
+#define GICC_EOIR	0x10
+#define GICC_HPPIR	0x18
+
+#define gicd(gic, offset) ((gic)->gicd_base + (offset))
+#define gicc(gic, offset) ((gic)->gicc_base + (offset))
+
+#define REG(addr) ((uint32_t *)(addr))
+
+static inline uint32_t REG_READ32(volatile uint32_t *addr)
+{
+	uint32_t value;
+	__asm__ __volatile__("ldr %0, [%1]":"=&r"(value):"r"(addr));
+	rmb();
+	return value;
+}
+
+static inline void REG_WRITE32(volatile uint32_t *addr, unsigned int value)
+{
+	__asm__ __volatile__("str %0, [%1]"::"r"(value), "r"(addr));
+	wmb();
+}
+
+static void gic_set_priority(struct gic *gic, unsigned char irq_number, unsigned char priority)
+{
+	uint32_t value;
+	value = REG_READ32(REG(gicd(gic, GICD_PRIORITY)) + irq_number);
+	value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
+	value |= priority << (8 * (irq_number & 0x3)); // add our priority
+	REG_WRITE32(REG(gicd(gic, GICD_PRIORITY)) + irq_number, value);
+}
+
+static void gic_route_interrupt(struct gic *gic, unsigned char irq_number, unsigned char cpu_set)
+{
+	uint32_t value;
+	value = REG_READ32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number);
+	value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
+	value |= cpu_set << (8 * (irq_number & 0x3)); // add our priority
+	REG_WRITE32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number, value);
+}
+
+static void gic_enable_interrupt(struct gic *gic, unsigned char irq_number,
+		unsigned char cpu_set, unsigned char level_sensitive, unsigned char ppi)
+{
+	void *set_enable_reg;
+	void *cfg_reg;
+
+	// set priority
+	gic_set_priority(gic, irq_number, 0x0);
+
+	// set target cpus for this interrupt
+	gic_route_interrupt(gic, irq_number, cpu_set);
+
+	// set level/edge triggered
+	cfg_reg = (void *)gicd(gic, GICD_ICFGR);
+	level_sensitive ? clear_bit((irq_number * 2) + 1, cfg_reg) : set_bit((irq_number * 2) + 1, cfg_reg);
+	if(ppi)
+		clear_bit((irq_number * 2), cfg_reg);
+
+	wmb();
+
+	// enable forwarding interrupt from distributor to cpu interface
+	set_enable_reg = (void *)gicd(gic, GICD_ISENABLER);
+	set_bit(irq_number, set_enable_reg);
+	wmb();
+}
+
+static void gic_enable_interrupts(struct gic *gic)
+{
+	// Global enable forwarding interrupts from distributor to cpu interface
+	REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000001);
+
+	// Global enable signalling of interrupt from the cpu interface
+	REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000001);
+}
+
+static void gic_disable_interrupts(struct gic *gic)
+{
+	// Global disable signalling of interrupt from the cpu interface
+	REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000000);
+
+	// Global disable forwarding interrupts from distributor to cpu interface
+	REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000000);
+}
+
+static void gic_cpu_set_priority(struct gic *gic, char priority)
+{
+	REG_WRITE32(REG(gicc(gic, GICC_PMR)), priority & 0x000000FF);
+}
+
+static void gic_set_handler(unsigned long gic_handler) {
+	IRQ_handler = gic_handler;
+}
+
+static unsigned long gic_readiar(struct gic *gic) {
+	return REG_READ32(REG(gicc(gic, GICC_IAR))) & 0x000003FF; // Interrupt ID
+}
+
+static void gic_eoir(struct gic *gic, uint32_t irq) {
+	REG_WRITE32(REG(gicc(gic, GICC_EOIR)), irq & 0x000003FF);
+}
+
+//FIXME Get event_irq from dt
+#define EVENTS_IRQ 31
+#define VIRTUALTIMER_IRQ 27
+
+//FIXME Move to a header file
+#define VTIMER_TICK 0x6000000
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+void increment_vtimer_compare(uint64_t inc);
+
+static void gic_handler(void) {
+	unsigned int irq = gic_readiar(&gic);
+
+	DEBUG("IRQ received : %i\n", irq);
+	switch(irq) {
+	case EVENTS_IRQ:
+		do_hypervisor_callback(NULL);
+		break;
+	case VIRTUALTIMER_IRQ:
+		timer_handler(0, NULL, 0);
+		increment_vtimer_compare(VTIMER_TICK);
+		break;
+	default:
+		DEBUG("Unhandled irq\n");
+		break;
+	}
+
+	DEBUG("EIRQ\n");
+
+	gic_eoir(&gic, irq);
+}
+
+void gic_init(void) {
+	// FIXME Get from dt!
+	gic.gicd_base = (char *)0x2c001000ULL;
+	gic.gicc_base = (char *)0x2c002000ULL;
+	wmb();
+
+	gic_set_handler((unsigned long)gic_handler);
+
+	gic_disable_interrupts(&gic);
+	gic_cpu_set_priority(&gic, 0xff);
+	gic_enable_interrupt(&gic, EVENTS_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 0 /* ppi */);
+	gic_enable_interrupt(&gic, VIRTUALTIMER_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 1 /* ppi */);
+	gic_enable_interrupts(&gic);
+}
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 2da9b01..84a30a3 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -47,9 +47,11 @@ void unbind_all_ports(void)
 
     for ( i = 0; i < NR_EVS; i++ )
     {
+#ifndef __arm__
         if ( i == start_info.console.domU.evtchn ||
              i == start_info.store_evtchn)
             continue;
+#endif
 
         if ( test_and_clear_bit(i, bound_ports) )
         {
@@ -167,44 +169,30 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
 	return op.port;
 }
 
-#if defined(__x86_64__)
-char irqstack[2 * STACK_SIZE];
-
-static struct pda
-{
-    int irqcount;       /* offset 0 (used in x86_64.S) */
-    char *irqstackptr;  /*        8 */
-} cpu0_pda;
-#endif
-
+void arch_init_events(void);
 /*
  * Initially all events are without a handler and disabled
  */
 void init_events(void)
 {
     int i;
-#if defined(__x86_64__)
-    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
-    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
-    cpu0_pda.irqcount = -1;
-    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
-                                    & ~(STACK_SIZE - 1));
-#endif
+
     /* initialize event handler */
     for ( i = 0; i < NR_EVS; i++ )
 	{
         ev_actions[i].handler = default_handler;
         mask_evtchn(i);
     }
+
+    arch_init_events();
 }
 
+void arch_fini_events(void);
 void fini_events(void)
 {
     /* Dealloc all events */
     unbind_all_ports();
-#if defined(__x86_64__)
-    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
-#endif
+    arch_fini_events();
 }
 
 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
@@ -262,7 +250,8 @@ int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
 
 int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
 {
-    int rc;
+    int rc = 0;
+#ifndef __arm__
     uint32_t sid;
     struct xen_flask_op op;
     op.cmd = FLASK_GET_PEER_SID;
@@ -277,6 +266,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
     op.u.sid_context.size = size;
     set_xen_guest_handle(op.u.sid_context.context, ctx);
     rc = _hypercall1(int, xsm_op, &op);
+#endif
     return rc;
 }
 
diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
index 7eb69be..abfbd29 100644
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -37,6 +37,7 @@
 #include <xen/grant_table.h>
 #include <inttypes.h>
 #include <mini-os/gntmap.h>
+#include <mini-os/hypervisor.h>
 
 //#define GNTMAP_DEBUG
 #ifdef GNTMAP_DEBUG
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 2f1b3d7..404d72c 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -19,6 +19,7 @@
 #include <mini-os/mm.h>
 #include <mini-os/gnttab.h>
 #include <mini-os/semaphore.h>
+#include <mini-os/hypervisor.h>
 
 #define NR_RESERVED_ENTRIES 8
 
diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..9c79d5d 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
     in_callback = 0;
 }
 
-void force_evtchn_callback(void)
-{
-    int save;
-    vcpu_info_t *vcpu;
-    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
-    save = vcpu->evtchn_upcall_mask;
-
-    while (vcpu->evtchn_upcall_pending) {
-        vcpu->evtchn_upcall_mask = 1;
-        barrier();
-        do_hypervisor_callback(NULL);
-        barrier();
-        vcpu->evtchn_upcall_mask = save;
-        barrier();
-    };
-}
-
 inline void mask_evtchn(uint32_t port)
 {
     shared_info_t *s = HYPERVISOR_shared_info;
@@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
               &vcpu_info->evtchn_pending_sel) )
     {
         vcpu_info->evtchn_upcall_pending = 1;
-        if ( !vcpu_info->evtchn_upcall_mask )
-            force_evtchn_callback();
+        force_evtchn_callback();
     }
 }
 
diff --git a/extras/mini-os/include/arm/arch_limits.h b/extras/mini-os/include/arm/arch_limits.h
new file mode 100644
index 0000000..bae99e1
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_limits.h
@@ -0,0 +1,9 @@
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#include <mm.h>
+
+#define __STACK_SIZE_PAGE_ORDER  2
+#define __STACK_SIZE (4 * PAGE_SIZE)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_mm.h b/extras/mini-os/include/arm/arch_mm.h
new file mode 100644
index 0000000..9b2cc03
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_mm.h
@@ -0,0 +1,37 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern char stack[];
+
+#define PAGE_SHIFT		12
+#define PAGE_SIZE		(1 << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#define L1_PAGETABLE_SHIFT      12
+
+#if 0
+#define VIRT_START                 ((unsigned long)&_text)
+#else
+#define VIRT_START                 ((unsigned long)0)
+#endif
+
+#define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
+#define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x)	((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x)	((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x)	((x) >> L1_PAGETABLE_SHIFT)
+
+#define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
+#define virt_to_mfn(_virt)         (0)
+#define mach_to_virt(_mach)        (0)
+#define virt_to_mach(_virt)        (0)
+#define mfn_to_virt(_mfn)          (0)
+#define pfn_to_virt(_pfn)          (to_virt(PFN_PHYS(_pfn)))
+
+// FIXME
+#define map_frames(f, n) (NULL)
+
+#endif
diff --git a/extras/mini-os/include/arm/arch_sched.h b/extras/mini-os/include/arm/arch_sched.h
new file mode 100644
index 0000000..31d9071
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_sched.h
@@ -0,0 +1,22 @@
+
+#ifndef __ARCH_SCHED_H__
+#define __ARCH_SCHED_H__
+
+#include "arch_limits.h"
+
+static inline struct thread* get_current(void)
+{
+   struct thread **current;
+   unsigned long sp;
+   __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
+	current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
+	return *current;
+}
+
+
+extern void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
+
+#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
+
+
+#endif /* __ARCH_SCHED_H__ */
diff --git a/extras/mini-os/include/arm/arch_spinlock.h b/extras/mini-os/include/arm/arch_spinlock.h
new file mode 100755
index 0000000..6677bc4
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_spinlock.h
@@ -0,0 +1,49 @@
+
+
+#ifndef __ARCH_ASM_SPINLOCK_H
+#define __ARCH_ASM_SPINLOCK_H
+
+#include "os.h"
+
+
+#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define arch_spin_is_locked(x)	(*(volatile signed char *)(&(x)->slock) <= 0)
+#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+/*
+ * This works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE)
+ * (PPro errata 66, 92)
+ */
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+	xchg(&lock->slock, 1);
+}
+
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+	return xchg(&lock->slock, 0) != 0 ? 1 : 0;
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+	volatile int was_locked;
+	do {
+		was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
+	} while(was_locked);
+}
+
+static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+{
+}
+
+#endif
diff --git a/extras/mini-os/include/arm/hypercall-arm32.h b/extras/mini-os/include/arm/hypercall-arm32.h
new file mode 100644
index 0000000..0343946
--- /dev/null
+++ b/extras/mini-os/include/arm/hypercall-arm32.h
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * hypercall-x86_64.h
+ * 
+ * Copied from XenLinux.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * 64-bit updates:
+ *   Benjamin Liu <benjamin.liu@intel.com>
+ *   Jun Nakajima <jun.nakajima@intel.com>
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_ARM_H__
+#define __HYPERCALL_ARM_H__
+
+#include <xen/xen.h>
+#include <xen/sched.h>
+#include <mini-os/mm.h>
+
+inline int
+HYPERVISOR_mmu_update(
+	mmu_update_t *req, int count, int *success_count, domid_t domid);
+
+inline int
+HYPERVISOR_mmuext_op(
+	struct mmuext_op *op, int count, int *success_count, domid_t domid);
+
+inline int
+HYPERVISOR_set_gdt(
+	unsigned long *frame_list, int entries);
+
+inline int
+HYPERVISOR_stack_switch(
+	unsigned long ss, unsigned long esp);
+
+inline int
+HYPERVISOR_set_callbacks(
+	unsigned long event_address, unsigned long failsafe_address, 
+	unsigned long syscall_address);
+
+inline int
+HYPERVISOR_fpu_taskswitch(
+	int set);
+
+inline int
+HYPERVISOR_sched_op(
+	int cmd, void *arg);
+
+static inline int
+HYPERVISOR_shutdown(
+	unsigned int reason)
+{
+	struct sched_shutdown shutdown = { .reason = reason };
+	return low_shutdown(&shutdown);
+}
+
+inline long
+HYPERVISOR_set_timer_op(
+	uint64_t timeout);
+
+inline int
+HYPERVISOR_set_debugreg(
+	int reg, unsigned long value);
+
+inline unsigned long
+HYPERVISOR_get_debugreg(
+	int reg);
+
+inline int
+HYPERVISOR_update_descriptor(
+	unsigned long ma, unsigned long word);
+
+inline int
+HYPERVISOR_memory_op(
+	unsigned int cmd, void *arg);
+
+inline int
+HYPERVISOR_multicall(
+	void *call_list, int nr_calls);
+
+inline int
+HYPERVISOR_update_va_mapping(
+	unsigned long va, pte_t new_val, unsigned long flags);
+
+inline int
+HYPERVISOR_event_channel_op(
+       int cmd, void *op);
+
+inline int
+HYPERVISOR_xen_version(
+	int cmd, void *arg);
+
+inline int
+HYPERVISOR_console_io(
+	int cmd, int count, char *str);
+
+inline int
+HYPERVISOR_physdev_op(
+	void *physdev_op);
+
+inline int
+HYPERVISOR_grant_table_op(
+	unsigned int cmd, void *uop, unsigned int count);
+
+inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid);
+
+inline int
+HYPERVISOR_vm_assist(
+	unsigned int cmd, unsigned int type);
+
+inline int
+HYPERVISOR_vcpu_op(
+	int cmd, int vcpuid, void *extra_args);
+
+inline int
+HYPERVISOR_set_segment_base(
+	int reg, unsigned long value);
+
+inline int
+HYPERVISOR_suspend(
+	unsigned long srec);
+
+inline int
+HYPERVISOR_nmi_op(
+	unsigned long op,
+	unsigned long arg);
+
+inline int
+HYPERVISOR_sysctl(
+	unsigned long op);
+
+inline int
+HYPERVISOR_domctl(
+	unsigned long op);
+
+inline int
+HYPERVISOR_hvm_op(
+	unsigned long op, void *arg);
+
+#endif /* __HYPERCALL_X86_64_H__ */
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
new file mode 100644
index 0000000..60e84f7
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,314 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/types.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+
+#define BUG() while(1){}
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+#if 0
+static inline void force_evtchn_callback(void)
+{
+    int save;
+    vcpu_info_t *vcpu;
+    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+    save = vcpu->evtchn_upcall_mask;
+
+    while (vcpu->evtchn_upcall_pending) {
+        vcpu->evtchn_upcall_mask = 1;
+        barrier();
+        do_hypervisor_callback(NULL);
+        barrier();
+        vcpu->evtchn_upcall_mask = save;
+        barrier();
+    };
+}
+#else
+#define force_evtchn_callback(void) do {} while(0)
+#endif
+
+// disable interrupts
+static inline __cli(void) {
+	int x;
+	__asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory");
+}
+
+// enable interrupts
+static inline __sti(void) {
+	int x;
+	__asm__ __volatile__("mrs %0, cpsr\n"
+						"bic %0, %0, #0x80\n"
+						"msr cpsr_c, %0"
+						:"=r"(x)::"memory");
+}
+
+static inline int irqs_disabled() {
+	int x;
+	__asm__ __volatile__("mrs %0, cpsr\n":"=r"(x)::"memory");
+	return (x & 0x80);
+}
+
+#define local_irq_save(x) { \
+	__asm__ __volatile__("mrs %0, cpsr;cpsid i; and %0, %0, #0x80":"=r"(x)::"memory");	\
+}
+
+#define local_irq_restore(x) {	\
+	__asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory");	\
+}
+
+#define local_save_flags(x)	{ \
+		__asm__ __volatile__("mrs %0, cpsr; and %0, %0, 0x80":"=r"(x)::"memory");	\
+}
+
+#define local_irq_disable()	__cli()
+#define local_irq_enable() __sti()
+
+#if defined(__arm__)
+#define mb() __asm__("dmb");
+#define rmb() __asm__("dmb");
+#define wmb() __asm__("dmb");
+#elif defined(__aarch64__)
+#define mb()
+#define rmb()
+#define wmb()
+#else
+#error undefined architecture
+#endif
+
+#define LOCK_PREFIX ""
+#define LOCK ""
+
+#define unlikely(x)  __builtin_expect((x),0)
+#define likely(x)  __builtin_expect((x),1)
+
+#define ADDR (*(volatile long *) addr)
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+#define __xg(x) ((volatile long *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+{
+	//TODO
+	unsigned volatile long y, tmp = 0;
+	switch(size){
+	case 1:
+#if CPU_EXCLUSIVE_LDST
+		__asm__ __volatile__("1:ldrexb %0, [%1]\n"
+			"strexb %3, %2, [%1]\n"
+			"cmp %3, #1\n"
+			"beq 1b\n\n"
+			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+		y = (*(char *)ptr) & 0x000000ff;
+		*((char *)ptr) = (char)x;
+#endif
+		break;
+	case 2:
+#if CPU_EXCLUSIVE_LDST
+		__asm__ __volatile__("1:ldrexh %0, [%1]\n"
+			"strexh %3, %2, [%1]\n"
+			"cmp %3, #1\n"
+			"beq 1b\n\n"
+			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+		y = (*(short *)ptr) & 0x0000ffff;
+		*((short *)ptr) = (short)x;
+#endif
+		break;
+	default: // 4
+#if CPU_EXCLUSIVE_LDST
+		__asm__ __volatile__("1:ldrex %0, [%1]\n"
+			"strex %3, %2, [%1]\n"
+			"cmp %3, #1\n"
+			"beq 1b\n\n"
+			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
+#else
+		y = (*(unsigned long *)ptr) & 0xffffffff;
+		*((unsigned long *)ptr) = x;
+#endif
+		break;
+	}
+    return y;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+	//TODO
+	unsigned long *tmp = (unsigned long *)addr;
+
+	int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
+	tmp[nr >> 5] &= ~(1 << (nr & 0x1f));
+    return x;
+}
+
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+	//TODO
+	unsigned long *tmp = (unsigned long *)addr;
+
+	int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
+	tmp[nr >> 5] |= (1 << (nr & 0x1f));
+    return x;
+}
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+	//TODO
+	unsigned long *tmp = (unsigned long *)addr;
+    return tmp[nr >> 5] & (1 << (nr & 0x1f));
+}
+
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
+{
+	//TODO:
+	unsigned long *tmp = (unsigned long *)addr;
+	return tmp[nr >> 5] & (1 << (nr & 0x1f));
+}
+
+//TODO
+#define test_bit(nr,addr) (((unsigned long *)addr)[nr >> 5] & (1 << (nr & 0x1f)))
+
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+	//TODO:
+	unsigned long *tmp = (unsigned long *)addr;
+	tmp[nr >> 5] |= (1 << (nr & 0x1f));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+	//TODO
+	unsigned long *tmp = (unsigned long *)addr;
+	tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f));
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+	//TODO
+	int index = 0;
+	while(!(word & (1 << index++))){};
+
+	return index - 1;
+}
+
+//FIXME
+#define rdtscll(val) (val = 0)
+
+#define wrmsr(msr,val1,val2) (0)
+
+#define wrmsrl(msr,val) wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32)
+
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64  ****************************/
+struct __synch_xchg_dummy { unsigned long a[100]; };
+#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
+
+#define synch_cmpxchg(ptr, old, new) (0)
+
+static inline unsigned long __synch_cmpxchg(volatile void *ptr,
+        unsigned long old,
+        unsigned long new, int size)
+{
+	//TODO:
+    //BUG();
+    return 0;
+}
+
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+	//TODO:
+	set_bit(nr, addr);
+}
+
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+	//TODO:
+    clear_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+	//TODO:
+	return test_and_set_bit(nr, addr);
+}
+
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+	//TODO:
+    return test_and_clear_bit(nr, addr);
+}
+
+static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
+{
+	//TODO:
+    return const_test_bit(nr, addr);
+}
+
+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
+{
+	//TODO:
+    return var_test_bit(nr, addr);
+}
+
+#define synch_test_bit(nr,addr) test_bit(nr, addr)
+
+
+#undef ADDR
+
+#endif /* not assembly */
+
+#endif
diff --git a/extras/mini-os/include/arm/traps.h b/extras/mini-os/include/arm/traps.h
new file mode 100644
index 0000000..b8ce784
--- /dev/null
+++ b/extras/mini-os/include/arm/traps.h
@@ -0,0 +1,20 @@
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+struct pt_regs {
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+};
+
+#endif
diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
index 3755b66..dade8fb 100644
--- a/extras/mini-os/include/console.h
+++ b/extras/mini-os/include/console.h
@@ -42,6 +42,7 @@
 #include <xen/grant_table.h>
 #include <xenbus.h>
 #include <xen/io/console.h>
+#include <xen/event_channel.h>
 #include <stdarg.h>
 
 struct consfront_dev {
diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
index a62cb78..ee288a0 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -13,16 +13,34 @@
 #define _HYPERVISOR_H_
 
 #include <mini-os/types.h>
+
 #include <xen/xen.h>
+
 #if defined(__i386__)
 #include <hypercall-x86_32.h>
 #elif defined(__x86_64__)
 #include <hypercall-x86_64.h>
+#elif defined(__arm__)
+#include <hypercall-arm32.h>
+#elif defined(__aarch64__)
+#include <hypercall-arm64.h>
 #else
 #error "Unsupported architecture"
 #endif
 #include <mini-os/traps.h>
 
+#ifdef __arm__
+struct start_info {
+    union {
+        struct {
+            xen_pfn_t mfn;
+            uint32_t  evtchn;
+        } domU;
+    } console;
+};
+typedef struct start_info start_info_t;
+#endif
+
 /*
  * a placeholder for the start of day information passed up from the hypervisor
  */
@@ -35,7 +53,6 @@ extern union start_info_union start_info_union;
 #define start_info (start_info_union.start_info)
 
 /* hypervisor.c */
-void force_evtchn_callback(void);
 void do_hypervisor_callback(struct pt_regs *regs);
 void mask_evtchn(uint32_t port);
 void unmask_evtchn(uint32_t port);
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..644c7de 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -29,6 +29,8 @@
 #include <xen/arch-x86_32.h>
 #elif defined(__x86_64__)
 #include <xen/arch-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <xen/arch-arm.h>
 #else
 #error "Unsupported architecture"
 #endif
diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
index 6640ede..781144c 100644
--- a/extras/mini-os/include/types.h
+++ b/extras/mini-os/include/types.h
@@ -27,7 +27,7 @@ typedef unsigned char       u_char;
 typedef unsigned int        u_int;
 typedef unsigned long       u_long;
 #endif
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
 typedef long long           quad_t;
 typedef unsigned long long  u_quad_t;
 
@@ -40,7 +40,7 @@ typedef unsigned long       u_quad_t;
 typedef struct { unsigned long pte; } pte_t;
 #endif /* __i386__ || __x86_64__ */
 
-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__aarch64__)
 #define __pte(x) ((pte_t) { (x) } )
 #else
 #define __pte(x) ({ unsigned long long _x = (x);        \
@@ -51,10 +51,10 @@ typedef struct { unsigned long pte; } pte_t;
 #include <limits.h>
 #include <stdint.h>
 #else
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
 typedef unsigned int        uintptr_t;
 typedef int                 intptr_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
 typedef unsigned long       uintptr_t;
 typedef long                intptr_t;
 #endif /* __i386__ || __x86_64__ */
@@ -64,10 +64,10 @@ typedef unsigned short uint16_t;
 typedef   signed short int16_t;
 typedef unsigned int uint32_t;
 typedef   signed int int32_t;
-#ifdef __i386__
+#if defined(__i386__) || defined(__arm__)
 typedef   signed long long int64_t;
 typedef unsigned long long uint64_t;
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__aarch64__)
 typedef   signed long int64_t;
 typedef unsigned long uint64_t;
 #endif
@@ -83,4 +83,65 @@ typedef intptr_t            ptrdiff_t;
 typedef long ssize_t;
 #endif
 
+#ifdef __arm__
+/*
+ * From
+ *	@(#)quad.h	8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef __BIG_ENDIAN
+#define _QUAD_HIGHWORD 0
+#define _QUAD_LOWWORD 1
+#else /* __LITTLE_ENDIAN */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+#endif
+
+/*
+ * Define high and low longwords.
+ */
+#define H               _QUAD_HIGHWORD
+#define L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define CHAR_BIT        8               /* number of bits in a char */
+#define QUAD_BITS       (sizeof(s64) * CHAR_BIT)
+#define LONG_BITS       (sizeof(long) * CHAR_BIT)
+#define HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
+
+#define B (1 << HALF_BITS) /* digit base */
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define HHALF(x)        ((x) >> HALF_BITS)
+#define LHALF(x)        ((x) & ((1 << HALF_BITS) - 1))
+#define LHUP(x)         ((x) << HALF_BITS)
+
+#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+    int64_t            q;              /* as a (signed) quad */
+    int64_t            uq;             /* as an unsigned quad */
+    long           sl[2];          /* as two signed longs */
+    unsigned long  ul[2];          /* as two unsigned longs */
+};
+
+/* select a type for digits in base B */
+typedef u_long digit;
+#endif
+
 #endif /* _TYPES_H_ */
diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h
index 23cfca7..3b74cd7 100644
--- a/extras/mini-os/include/x86/arch_mm.h
+++ b/extras/mini-os/include/x86/arch_mm.h
@@ -25,6 +25,8 @@
 #ifndef _ARCH_MM_H_
 #define _ARCH_MM_H_
 
+extern char stack[];
+
 #ifndef __ASSEMBLY__
 #include <xen/xen.h>
 #if defined(__i386__)
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index f193865..8eea1be 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -64,8 +64,6 @@ extern shared_info_t *HYPERVISOR_shared_info;
 void trap_init(void);
 void trap_fini(void);
 
-void arch_init(start_info_t *si);
-void arch_print_info(void);
 void arch_fini(void);
 
 
@@ -162,6 +160,23 @@ do {									\
  */
 typedef struct { volatile int counter; } atomic_t;
 
+static inline void force_evtchn_callback(void)
+{
+    int save;
+    vcpu_info_t *vcpu;
+    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+    save = vcpu->evtchn_upcall_mask;
+
+    while (vcpu->evtchn_upcall_pending) {
+        vcpu->evtchn_upcall_mask = 1;
+        barrier();
+        do_hypervisor_callback(NULL);
+        barrier();
+        vcpu->evtchn_upcall_mask = save;
+        barrier();
+    };
+}
+
 
 /************************** i386 *******************************/
 #ifdef __INSIDE_MINIOS__
diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
index 7083763..4581574 100644
--- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
+++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
@@ -37,6 +37,7 @@
 #include <xen/xen.h>
 #include <xen/sched.h>
 #include <mini-os/mm.h>
+#include <arch_mm.h>
 
 #define __STR(x) #x
 #define STR(x) __STR(x)
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 386be8f..de25921 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -27,7 +27,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <mini-os/os.h>
 #include <mini-os/hypervisor.h>
 #include <mini-os/mm.h>
 #include <mini-os/events.h>
@@ -118,40 +117,14 @@ __attribute__((weak)) int app_main(start_info_t *si)
     return 0;
 }
 
-/*
- * INITIAL C ENTRY POINT.
- */
-void start_kernel(start_info_t *si)
-{
-    static char hello[] = "Bootstrapping...\n";
-
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
-
-    arch_init(si);
-
-    trap_init();
-
-    /* print out some useful information  */
-    printk("Xen Minimal OS!\n");
-    printk("  start_info: %p(VA)\n", si);
-    printk("    nr_pages: 0x%lx\n", si->nr_pages);
-    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
-    printk("     pt_base: %p(VA)\n", (void *)si->pt_base); 
-    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
-    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list); 
-    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
-    printk("     mod_len: %lu\n", si->mod_len); 
-    printk("       flags: 0x%x\n", (unsigned int)si->flags);
-    printk("    cmd_line: %s\n",  
-           si->cmd_line ? (const char *)si->cmd_line : "NULL");
+void gic_init(void);
 
+void start_kernel(void)
+{
     /* Set up events. */
     init_events();
-    
-    /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
-    __sti();
 
-    arch_print_info();
+    __sti();
 
     setup_xen_features();
 
@@ -161,24 +134,58 @@ void start_kernel(start_info_t *si)
     /* Init time and timers. */
     init_time();
 
+#ifndef __arm__
     /* Init the console driver. */
     init_console();
+#endif
 
     /* Init grant tables */
     init_gnttab();
-    
+
     /* Init scheduler. */
     init_sched();
  
     /* Init XenBus */
     init_xenbus();
 
+
 #ifdef CONFIG_XENBUS
     create_thread("shutdown", shutdown_thread, NULL);
 #endif
 
+#ifdef __arm__
+    gic_init();
+#endif
+
+//#define VTIMER_TEST
+#ifdef VTIMER_TEST
+    while(1){
+		int x, y, z;
+    	z = 0;
+    	// counter
+    	__asm__ __volatile__("mrrc p15, 1, %0, %1, c14;isb":"=r"(x), "=r"(y));
+    	printk("Counter: %x-%x\n", x, y);
+
+    	__asm__ __volatile__("mrrc p15, 3, %0, %1, c14;isb":"=r"(x), "=r"(y));
+    	printk("CompareValue: %x-%x\n", x, y);
+
+    	// TimerValue
+    	__asm__ __volatile__("mrc p15, 0, %0, c14, c3, 0;isb":"=r"(x));
+    	printk("TimerValue: %x\n", x);
+
+    	// control register
+    	__asm__ __volatile__("mrc p15, 0, %0, c14, c3, 1;isb":"=r"(x));
+    	printk("ControlRegister: %x\n", x);
+    	while(z++ < 0xfffff){}
+    }
+#endif
+
     /* Call (possibly overridden) app_main() */
+#if defined(__arm__) || defined(__aarch64__)
+    app_main(NULL);
+#else
     app_main(&start_info);
+#endif
 
     /* Everything initialised, start idle thread */
     run_idle_thread();
@@ -205,13 +212,12 @@ void stop_kernel(void)
     /* Reset events. */
     fini_events();
 
-    /* Reset traps */
-    trap_fini();
-
     /* Reset arch details */
     arch_fini();
 }
 
+void arch_do_exit(void);
+
 /*
  * do_exit: This is called whenever an IRET fails in entry.S.
  * This will generally be because an application has got itself into
@@ -222,7 +228,7 @@ void stop_kernel(void)
 void do_exit(void)
 {
     printk("Do_exit called!\n");
-    stack_walk();
+    arch_do_exit();
     for( ;; )
     {
         struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index d2d5264..ab76018 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -213,22 +213,26 @@ static void init_page_allocator(unsigned long min, unsigned long max)
     min = round_pgup  (min);
     max = round_pgdown(max);
 
+
     /* Allocate space for the allocation bitmap. */
-    bitmap_size  = (max+1) >> (PAGE_SHIFT+3);
+    bitmap_size  = (max - min + 1) >> (PAGE_SHIFT+3);
     bitmap_size  = round_pgup(bitmap_size);
     alloc_bitmap = (unsigned long *)to_virt(min);
     min         += bitmap_size;
     range        = max - min;
 
+
     /* All allocated by default. */
     memset(alloc_bitmap, ~0, bitmap_size);
     /* Free up the memory we've been given to play with. */
     map_free(PHYS_PFN(min), range>>PAGE_SHIFT);
 
+
     /* The buddy lists are addressed in high memory. */
     min = (unsigned long) to_virt(min);
     max = (unsigned long) to_virt(max);
 
+
     while ( range != 0 )
     {
         /*
@@ -238,7 +242,6 @@ static void init_page_allocator(unsigned long min, unsigned long max)
         for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ )
             if ( min & (1UL<<i) ) break;
 
-
         ch = (chunk_head_t *)min;
         min   += (1UL<<i);
         range -= (1UL<<i);
@@ -399,9 +402,7 @@ void *sbrk(ptrdiff_t increment)
 
 void init_mm(void)
 {
-
     unsigned long start_pfn, max_pfn;
-
     printk("MM: Init\n");
 
     arch_init_mm(&start_pfn, &max_pfn);
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 174945e..a1cd3a9 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -100,15 +100,19 @@ void schedule(void)
         next = NULL;
         MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp)
         {
+        	DEBUG("Checking thread : %s (runnable:%i)\n", thread->name, is_runnable(thread));
             if (!is_runnable(thread) && thread->wakeup_time != 0LL)
             {
-                if (thread->wakeup_time <= now)
+                if (thread->wakeup_time <= now) {
+                	DEBUG("Wake thread : %s\n", thread->name);
                     wake(thread);
+                }
                 else if (thread->wakeup_time < min_wakeup_time)
                     min_wakeup_time = thread->wakeup_time;
             }
             if(is_runnable(thread)) 
             {
+            	DEBUG("Thread (%s) is runnable, put it next\n", thread->name);
                 next = thread;
                 /* Put this thread on the end of the list */
                 MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
@@ -145,6 +149,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data)
     unsigned long flags;
     /* Call architecture specific setup. */
     thread = arch_create_thread(name, function, data);
+    if(!thread)
+    	BUG(); //For now, FIXME should just return NULL
+
     /* Not runable, not exited, not sleeping */
     thread->flags = 0;
     thread->wakeup_time = 0LL;
diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c
new file mode 100644
index 0000000..4320241
--- /dev/null
+++ b/extras/mini-os/time.c
@@ -0,0 +1,12 @@
+void arch_init_time(void);
+void arch_fini_time(void);
+
+void init_time(void)
+{
+	arch_init_time();
+}
+
+void fini_time(void)
+{
+	arch_fini_time();
+}
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index 934f23b..8a99ee2 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -27,6 +27,7 @@
 #include <mini-os/wait.h>
 #include <xen/io/xs_wire.h>
 #include <mini-os/spinlock.h>
+#include <mini-os/hypervisor.h>
 #include <mini-os/xmalloc.h>
 
 #define min(x,y) ({                       \
@@ -43,6 +44,7 @@
 #endif
 
 static struct xenstore_domain_interface *xenstore_buf;
+static uint32_t store_evtchn;
 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
 
@@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
     return o_probe;
 }
 
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn);
+
 /* Initialise xenbus. */
 void init_xenbus(void)
 {
     int err;
     DEBUG("init_xenbus called.\n");
-    xenstore_buf = mfn_to_virt(start_info.store_mfn);
+
+    arch_init_xenbus(&xenstore_buf, &store_evtchn);
+
     create_thread("xenstore", xenbus_thread_func, NULL);
     DEBUG("buf at %p.\n", xenstore_buf);
-    err = bind_evtchn(start_info.store_evtchn,
+    err = bind_evtchn(store_evtchn,
 		      xenbus_evtchn_handler,
               NULL);
-    unmask_evtchn(start_info.store_evtchn);
-    printk("xenbus initialised on irq %d mfn %#lx\n",
-	   err, start_info.store_mfn);
+    unmask_evtchn(store_evtchn);
+    printk("xenbus initialised on event %d\n", err);
 }
 
 void fini_xenbus(void)
@@ -420,7 +425,7 @@ static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
     xenstore_buf->req_prod += len;
 
     /* Send evtchn to notify remote */
-    notify_remote_via_evtchn(start_info.store_evtchn);
+    notify_remote_via_evtchn(store_evtchn);
 }
 
 /* Send a mesasge to xenbus, in the same fashion as xb_write, and
@@ -445,6 +450,7 @@ xenbus_msg_reply(int type,
     remove_waiter(w, req_info[id].waitq);
     wake(current);
 
+    rmb();
     rep = req_info[id].reply;
     BUG_ON(rep->req_id != id);
     release_xenbus_id(id);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 4/4] mini-os: Added FDT support on ARM
  2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
                   ` (2 preceding siblings ...)
  2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
@ 2014-06-02 17:49 ` Thomas Leonard
  2014-06-06 13:51   ` Ian Campbell
  2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
  4 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-02 17:49 UTC (permalink / raw)
  To: xen-devel; +Cc: samuel.thibault, Thomas Leonard, stefano.stabellini

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: split out FDT support into a separate patch]
[talex5@gmail.com: replaced memmove with a BSD-licensed version]
[talex5@gmail.com: fixed "make clean" for FDT]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/COPYING                   |   27 +
 extras/mini-os/Makefile                  |   11 +
 extras/mini-os/include/fdt.h             |   60 ++
 extras/mini-os/include/lib.h             |    4 +-
 extras/mini-os/include/libfdt.h          | 1478 ++++++++++++++++++++++++++++++
 extras/mini-os/include/libfdt_env.h      |   37 +
 extras/mini-os/lib/fdt/fdt.c             |  222 +++++
 extras/mini-os/lib/fdt/fdt_empty_tree.c  |   84 ++
 extras/mini-os/lib/fdt/fdt_ro.c          |  574 ++++++++++++
 extras/mini-os/lib/fdt/fdt_rw.c          |  492 ++++++++++
 extras/mini-os/lib/fdt/fdt_strerror.c    |   96 ++
 extras/mini-os/lib/fdt/fdt_sw.c          |  256 ++++++
 extras/mini-os/lib/fdt/fdt_wip.c         |  118 +++
 extras/mini-os/lib/fdt/libfdt_internal.h |   95 ++
 extras/mini-os/lib/memmove.c             |   45 +
 extras/mini-os/lib/string.c              |   12 +
 16 files changed, 3610 insertions(+), 1 deletion(-)
 create mode 100644 extras/mini-os/include/fdt.h
 create mode 100644 extras/mini-os/include/libfdt.h
 create mode 100644 extras/mini-os/include/libfdt_env.h
 create mode 100644 extras/mini-os/lib/fdt/fdt.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_empty_tree.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_ro.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_rw.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_strerror.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_sw.c
 create mode 100644 extras/mini-os/lib/fdt/fdt_wip.c
 create mode 100644 extras/mini-os/lib/fdt/libfdt_internal.h
 create mode 100644 extras/mini-os/lib/memmove.c

diff --git a/extras/mini-os/COPYING b/extras/mini-os/COPYING
index 1d9df6c..b676bb6 100644
--- a/extras/mini-os/COPYING
+++ b/extras/mini-os/COPYING
@@ -34,3 +34,30 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.
 
+
+Copyright (c) 2005,2006, NLnetLabs
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of NLnetLabs nor the names of its
+      contributors may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 0fd38a8..cccf556 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -75,6 +75,16 @@ SUBDIRS := lib xenbus console
 ifeq ($(XEN_TARGET_ARCH),arm32)
 # ARM drivers
 src-y += drivers/gic.c
+
+# Device tree support
+SUBDIRS += lib/fdt
+src-y += lib/fdt/fdt.c
+src-y += lib/fdt/fdt_empty_tree.c
+src-y += lib/fdt/fdt_ro.c
+src-y += lib/fdt/fdt_rw.c
+src-y += lib/fdt/fdt_strerror.c
+src-y += lib/fdt/fdt_sw.c
+src-y += lib/fdt/fdt_wip.c
 endif
 
 src-$(CONFIG_BLKFRONT) += blkfront.c
@@ -104,6 +114,7 @@ endif
 src-y += lib/printf.c
 src-y += lib/stack_chk_fail.c
 src-y += lib/string.c
+src-y += lib/memmove.c
 src-y += lib/sys.c
 src-y += lib/xmalloc.c
 src-$(CONFIG_XENBUS) += lib/xs.c
diff --git a/extras/mini-os/include/fdt.h b/extras/mini-os/include/fdt.h
new file mode 100644
index 0000000..48ccfd9
--- /dev/null
+++ b/extras/mini-os/include/fdt.h
@@ -0,0 +1,60 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+	uint32_t magic;			 /* magic word FDT_MAGIC */
+	uint32_t totalsize;		 /* total size of DT block */
+	uint32_t off_dt_struct;		 /* offset to structure */
+	uint32_t off_dt_strings;	 /* offset to strings */
+	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
+	uint32_t version;		 /* format version */
+	uint32_t last_comp_version;	 /* last compatible version */
+
+	/* version 2 fields below */
+	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+	uint32_t size_dt_strings;	 /* size of the strings block */
+
+	/* version 17 fields below */
+	uint32_t size_dt_struct;	 /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+	uint64_t address;
+	uint64_t size;
+};
+
+struct fdt_node_header {
+	uint32_t tag;
+	char name[0];
+};
+
+struct fdt_property {
+	uint32_t tag;
+	uint32_t len;
+	uint32_t nameoff;
+	char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
+#define FDT_TAGSIZE	sizeof(uint32_t)
+
+#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
+#define FDT_END_NODE	0x2		/* End node */
+#define FDT_PROP	0x3		/* Property: name off,
+					   size, content */
+#define FDT_NOP		0x4		/* nop */
+#define FDT_END		0x9
+
+#define FDT_V1_SIZE	(7*sizeof(uint32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V16_SIZE	FDT_V3_SIZE
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+
+#endif /* _FDT_H */
diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index 935bede..74c210b 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -86,6 +86,7 @@ char	*strncpy(char * __restrict, const char * __restrict, size_t);
 
 char	*strstr(const char *, const char *);
 
+void *memmove(void * dest,const void *src,size_t count);
 void *memset(void *, int, size_t);
 
 char *strchr(const char *p, int ch);
@@ -95,7 +96,8 @@ char *strrchr(const char *p, int ch);
  *	@(#)systm.h	8.7 (Berkeley) 3/29/95
  * $FreeBSD$
  */
-void	*memcpy(void *to, const void *from, size_t len);
+void *memcpy(void *to, const void *from, size_t len);
+void *memchr(const void *s, int c, size_t n);
 
 size_t strnlen(const char *, size_t);
 #endif
diff --git a/extras/mini-os/include/libfdt.h b/extras/mini-os/include/libfdt.h
new file mode 100644
index 0000000..73f4975
--- /dev/null
+++ b/extras/mini-os/include/libfdt.h
@@ -0,0 +1,1478 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#define FDT_FIRST_SUPPORTED_VERSION	0x10
+#define FDT_LAST_SUPPORTED_VERSION	0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND	1
+	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS		2
+	/* FDT_ERR_EXISTS: Attemped to create a node or property which
+	 * already exists */
+#define FDT_ERR_NOSPACE		3
+	/* FDT_ERR_NOSPACE: Operation needed to expand the device
+	 * tree, but its buffer did not have sufficient space to
+	 * contain the expanded tree. Use fdt_open_into() to move the
+	 * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET	4
+	/* FDT_ERR_BADOFFSET: Function was passed a structure block
+	 * offset which is out-of-bounds, or which points to an
+	 * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH		5
+	/* FDT_ERR_BADPATH: Function was passed a badly formatted path
+	 * (e.g. missing a leading / for a function which requires an
+	 * absolute path) */
+#define FDT_ERR_BADPHANDLE	6
+	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+	 * value.  phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE	7
+	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
+	 * tree created by the sequential-write functions, which is
+	 * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED	8
+	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
+	 * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC	9
+	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+	 * device tree at all - it is missing the flattened device
+	 * tree magic number. */
+#define FDT_ERR_BADVERSION	10
+	/* FDT_ERR_BADVERSION: Given device tree has a version which
+	 * can't be handled by the requested operation.  For
+	 * read-write functions, this may mean that fdt_open_into() is
+	 * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE	11
+	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+	 * structure block or other serious error (e.g. misnested
+	 * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT	12
+	/* FDT_ERR_BADLAYOUT: For read-write functions, the given
+	 * device tree has it's sub-blocks in an order that the
+	 * function can't handle (memory reserve map, then structure,
+	 * then strings).  Use fdt_open_into() to reorganize the tree
+	 * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL	13
+	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+	 * Should never be returned, if it is, it indicates a bug in
+	 * libfdt itself. */
+
+#define FDT_ERR_MAX		13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these)                */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* Traversal functions                                                */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
+/**********************************************************************/
+/* General functions                                                  */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) 			(fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt)		(fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) 	(fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) 	(fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) 	(fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+	static inline void fdt_set_##name(void *fdt, uint32_t val) \
+	{ \
+		struct fdt_header *fdth = (struct fdt_header*)fdt; \
+		fdth->name = cpu_to_fdt32(val); \
+	}
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ *     0, if the buffer appears to contain a valid device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize.  The buffer may overlap
+ * with the existing device tree blob at fdt.  Therefore,
+ *     fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions                                                */
+/**********************************************************************/
+
+/**
+ * fdt_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map.  This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ *     the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name.  This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name.  name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ *	structure block offset of the requested subnode (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ *	structure block offset of the node with the requested path (>=0), on success
+ *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ *	-FDT_ERR_NOTFOUND, if the requested node does not exist
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retrieve the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset.  If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the node's name, on success
+ *		If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ *	structure block offset of the property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested node has no properties
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset.  This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ *	structure block offset of the next property (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the given property is the last in its node
+ *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset.  If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int nodeoffset,
+						    const char *name,
+						    int namelen, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset.  If lenp is
+ * non-NULL, the length of the property value is also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+					    const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+						      const char *name,
+						      int *lenp)
+{
+	return (struct fdt_property *)(uintptr_t)
+		fdt_get_property(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value).  If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.  If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *		if namep is non-NULL *namep contiains a pointer to the property
+ *		name.
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+				const char *name, int namelen, int *lenp);
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+			const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+				  const char *name, int *lenp)
+{
+	return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retrieve the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ *	the phandle of the node at nodeoffset, on success (!= 0, != -1)
+ *	0, if the node has no phandle, or another error occurs
+ */
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+				  const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias.  That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ *	a pointer to the expansion of the alias named 'name', of it exists
+ *	NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	0, on success
+ *		buf contains the absolute path of the node at
+ *		nodeoffset, as a NUL-terminated string.
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ *		characters and will not fit in the given buffer.
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth).  So
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node.  If the node at
+ * nodeoffset has depth D, then:
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ *	structure block offset of the node at node offset's ancestor
+ *		of depth supernodedepth (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+*	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node.  The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	depth of the node at nodeoffset (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ *	structure block offset of the parent of the node at nodeoffset
+ *		(>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ *					       propval, proplen);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ *						       propval, proplen);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_phandle() returns the offset of the node
+ * which has the given phandle value.  If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0), on success
+ *	-FDT_ERR_NOTFOUND, no node with that phandle exists
+ *	-FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ *	0, if the node has a 'compatible' property listing the given string
+ *	1, if the node has a 'compatible' property, but it does not list
+ *		the given string
+ *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * 	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions                                           */
+/**********************************************************************/
+
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len.  This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+					  const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+					  const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+					   const char *name, uint32_t val)
+{
+	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions                                         */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+	return fdt_property_u32(fdt, name, val);
+}
+#define fdt_property_string(fdt, name, str) \
+	fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions                                               */
+/**********************************************************************/
+
+int fdt_create_empty_tree(void *buf, int bufsize);
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new reservation entry
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ *		are less than n+1 reserve map entries)
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_mem_rsv(void *fdt, int n);
+
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string.  NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ *		to contain the new name
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len);
+
+/**
+ * fdt_setprop_u32 - set a property to a 32-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+				  uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+				  uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+				   uint32_t val)
+{
+	return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+				     const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+				     const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+				      const char *name, uint32_t val)
+{
+	return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node.  This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ *	structure block offset of the created nodeequested subnode (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *	-FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ *		the given name
+ *	-FDT_ERR_NOSPACE, if there is insufficient free space in the
+ *		blob to contain the new node
+ *	-FDT_ERR_NOSPACE
+ *	-FDT_ERR_BADLAYOUT
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions                                */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/extras/mini-os/include/libfdt_env.h b/extras/mini-os/include/libfdt_env.h
new file mode 100644
index 0000000..f91f137
--- /dev/null
+++ b/extras/mini-os/include/libfdt_env.h
@@ -0,0 +1,37 @@
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#ifdef _KERNEL
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/stdint.h>
+#else
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#endif
+
+#define EXTRACT_BYTE(n)	((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+	return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
+static inline uint32_t fdt32_to_cpu(uint32_t x)
+{
+	return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
+}
+#define cpu_to_fdt32(x) fdt32_to_cpu(x)
+
+static inline uint64_t fdt64_to_cpu(uint64_t x)
+{
+	return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
+		| (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
+}
+#define cpu_to_fdt64(x) fdt64_to_cpu(x)
+#undef EXTRACT_BYTE
+
+#endif /* _LIBFDT_ENV_H */
diff --git a/extras/mini-os/lib/fdt/fdt.c b/extras/mini-os/lib/fdt/fdt.c
new file mode 100644
index 0000000..e56833a
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt.c
@@ -0,0 +1,222 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		/* Complete tree */
+		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		/* Unfinished sequential-write blob */
+		if (fdt_size_dt_struct(fdt) == 0)
+			return -FDT_ERR_BADSTATE;
+	} else {
+		return -FDT_ERR_BADMAGIC;
+	}
+
+	return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
+{
+	const char *p;
+
+	if (fdt_version(fdt) >= 0x11)
+		if (((offset + len) < offset)
+		    || ((offset + len) > fdt_size_dt_struct(fdt)))
+			return NULL;
+
+	p = _fdt_offset_ptr(fdt, offset);
+
+	if (p + len < p)
+		return NULL;
+	return p;
+}
+
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
+{
+	const uint32_t *tagp, *lenp;
+	uint32_t tag;
+	int offset = startoffset;
+	const char *p;
+
+	*nextoffset = -FDT_ERR_TRUNCATED;
+	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+	if (!tagp)
+		return FDT_END; /* premature end */
+	tag = fdt32_to_cpu(*tagp);
+	offset += FDT_TAGSIZE;
+
+	*nextoffset = -FDT_ERR_BADSTRUCTURE;
+	switch (tag) {
+	case FDT_BEGIN_NODE:
+		/* skip name */
+		do {
+			p = fdt_offset_ptr(fdt, offset++, 1);
+		} while (p && (*p != '\0'));
+		if (!p)
+			return FDT_END; /* premature end */
+		break;
+
+	case FDT_PROP:
+		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+		if (!lenp)
+			return FDT_END; /* premature end */
+		/* skip-name offset, length and value */
+		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+			+ fdt32_to_cpu(*lenp);
+		break;
+
+	case FDT_END:
+	case FDT_END_NODE:
+	case FDT_NOP:
+		break;
+
+	default:
+		return FDT_END;
+	}
+
+	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+		return FDT_END; /* premature end */
+
+	*nextoffset = FDT_TAGALIGN(offset);
+	return tag;
+}
+
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+	if ((offset < 0) || (offset % FDT_TAGSIZE)
+	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+		return -FDT_ERR_BADOFFSET;
+
+	return offset;
+}
+
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+	if ((offset < 0) || (offset % FDT_TAGSIZE)
+	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+		return -FDT_ERR_BADOFFSET;
+
+	return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+	int nextoffset = 0;
+	uint32_t tag;
+
+	if (offset >= 0)
+		if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+			return nextoffset;
+
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		case FDT_BEGIN_NODE:
+			if (depth)
+				(*depth)++;
+			break;
+
+		case FDT_END_NODE:
+			if (depth && ((--(*depth)) < 0))
+				return nextoffset;
+			break;
+
+		case FDT_END:
+			if ((nextoffset >= 0)
+			    || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+				return -FDT_ERR_NOTFOUND;
+			else
+				return nextoffset;
+		}
+	} while (tag != FDT_BEGIN_NODE);
+
+	return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+	int len = strlen(s) + 1;
+	const char *last = strtab + tabsize - len;
+	const char *p;
+
+	for (p = strtab; p <= last; p++)
+		if (memcmp(p, s, len) == 0)
+			return p;
+	return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+	FDT_CHECK_HEADER(fdt);
+
+	if (fdt_totalsize(fdt) > bufsize)
+		return -FDT_ERR_NOSPACE;
+
+	memmove(buf, fdt, fdt_totalsize(fdt));
+	return 0;
+}
diff --git a/extras/mini-os/lib/fdt/fdt_empty_tree.c b/extras/mini-os/lib/fdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+	int err;
+
+	err = fdt_create(buf, bufsize);
+	if (err)
+		return err;
+
+	err = fdt_finish_reservemap(buf);
+	if (err)
+		return err;
+
+	err = fdt_begin_node(buf, "");
+	if (err)
+		return err;
+
+	err =  fdt_end_node(buf);
+	if (err)
+		return err;
+
+	err = fdt_finish(buf);
+	if (err)
+		return err;
+
+	return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/extras/mini-os/lib/fdt/fdt_ro.c b/extras/mini-os/lib/fdt/fdt_ro.c
new file mode 100644
index 0000000..02b6d68
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_ro.c
@@ -0,0 +1,574 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_nodename_eq(const void *fdt, int offset,
+			    const char *s, int len)
+{
+	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+	if (! p)
+		/* short match */
+		return 0;
+
+	if (memcmp(p, s, len) != 0)
+		return 0;
+
+	if (p[len] == '\0')
+		return 1;
+	else if (!memchr(s, '@', len) && (p[len] == '@'))
+		return 1;
+	else
+		return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+static int _fdt_string_eq(const void *fdt, int stroffset,
+			  const char *s, int len)
+{
+	const char *p = fdt_string(fdt, stroffset);
+
+	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+	FDT_CHECK_HEADER(fdt);
+	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+	return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+	int i = 0;
+
+	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+		i++;
+	return i;
+}
+
+static int _nextprop(const void *fdt, int offset)
+{
+	uint32_t tag;
+	int nextoffset;
+
+	do {
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			if (nextoffset >= 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			else
+				return nextoffset;
+
+		case FDT_PROP:
+			return offset;
+		}
+		offset = nextoffset;
+	} while (tag == FDT_NOP);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+			       const char *name, int namelen)
+{
+	int depth;
+
+	FDT_CHECK_HEADER(fdt);
+
+	for (depth = 0;
+	     (offset >= 0) && (depth >= 0);
+	     offset = fdt_next_node(fdt, offset, &depth))
+		if ((depth == 1)
+		    && _fdt_nodename_eq(fdt, offset, name, namelen))
+			return offset;
+
+	if (depth < 0)
+		return -FDT_ERR_NOTFOUND;
+	return offset; /* error */
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+		       const char *name)
+{
+	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+	const char *end = path + strlen(path);
+	const char *p = path;
+	int offset = 0;
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* see if we have an alias */
+	if (*path != '/') {
+		const char *q = strchr(path, '/');
+
+		if (!q)
+			q = end;
+
+		p = fdt_get_alias_namelen(fdt, p, q - p);
+		if (!p)
+			return -FDT_ERR_BADPATH;
+		offset = fdt_path_offset(fdt, p);
+
+		p = q;
+	}
+
+	while (*p) {
+		const char *q;
+
+		while (*p == '/')
+			p++;
+		if (! *p)
+			return offset;
+		q = strchr(p, '/');
+		if (! q)
+			q = end;
+
+		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+		if (offset < 0)
+			return offset;
+
+		p = q;
+	}
+
+	return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+	const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+	int err;
+
+	if (((err = fdt_check_header(fdt)) != 0)
+	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+			goto fail;
+
+	if (len)
+		*len = strlen(nh->name);
+
+	return nh->name;
+
+ fail:
+	if (len)
+		*len = err;
+	return NULL;
+}
+
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+	int offset;
+
+	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+		return offset;
+
+	return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp)
+{
+	int err;
+	const struct fdt_property *prop;
+
+	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+		if (lenp)
+			*lenp = err;
+		return NULL;
+	}
+
+	prop = _fdt_offset_ptr(fdt, offset);
+
+	if (lenp)
+		*lenp = fdt32_to_cpu(prop->len);
+
+	return prop;
+}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int offset,
+						    const char *name,
+						    int namelen, int *lenp)
+{
+	for (offset = fdt_first_property_offset(fdt, offset);
+	     (offset >= 0);
+	     (offset = fdt_next_property_offset(fdt, offset))) {
+		const struct fdt_property *prop;
+
+		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+			offset = -FDT_ERR_INTERNAL;
+			break;
+		}
+		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+				   name, namelen))
+			return prop;
+	}
+
+	if (lenp)
+		*lenp = offset;
+	return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+					    int nodeoffset,
+					    const char *name, int *lenp)
+{
+	return fdt_get_property_namelen(fdt, nodeoffset, name,
+					strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+				const char *name, int namelen, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+	if (! prop)
+		return NULL;
+
+	return prop->data;
+}
+
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+				  const char **namep, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property_by_offset(fdt, offset, lenp);
+	if (!prop)
+		return NULL;
+	if (namep)
+		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+			const char *name, int *lenp)
+{
+	return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+	const uint32_t *php;
+	int len;
+
+	/* FIXME: This is a bit sub-optimal, since we potentially scan
+	 * over all the properties twice. */
+	php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+	if (!php || (len != sizeof(*php))) {
+		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+		if (!php || (len != sizeof(*php)))
+			return 0;
+	}
+
+	return fdt32_to_cpu(*php);
+}
+
+const char *fdt_get_alias_namelen(const void *fdt,
+				  const char *name, int namelen)
+{
+	int aliasoffset;
+
+	aliasoffset = fdt_path_offset(fdt, "/aliases");
+	if (aliasoffset < 0)
+		return NULL;
+
+	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+	return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+	int pdepth = 0, p = 0;
+	int offset, depth, namelen;
+	const char *name;
+
+	FDT_CHECK_HEADER(fdt);
+
+	if (buflen < 2)
+		return -FDT_ERR_NOSPACE;
+
+	for (offset = 0, depth = 0;
+	     (offset >= 0) && (offset <= nodeoffset);
+	     offset = fdt_next_node(fdt, offset, &depth)) {
+		while (pdepth > depth) {
+			do {
+				p--;
+			} while (buf[p-1] != '/');
+			pdepth--;
+		}
+
+		if (pdepth >= depth) {
+			name = fdt_get_name(fdt, offset, &namelen);
+			if (!name)
+				return namelen;
+			if ((p + namelen + 1) <= buflen) {
+				memcpy(buf + p, name, namelen);
+				p += namelen;
+				buf[p++] = '/';
+				pdepth++;
+			}
+		}
+
+		if (offset == nodeoffset) {
+			if (pdepth < (depth + 1))
+				return -FDT_ERR_NOSPACE;
+
+			if (p > 1) /* special case so that root path is "/", not "" */
+				p--;
+			buf[p] = '\0';
+			return 0;
+		}
+	}
+
+	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+		return -FDT_ERR_BADOFFSET;
+	else if (offset == -FDT_ERR_BADOFFSET)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth)
+{
+	int offset, depth;
+	int supernodeoffset = -FDT_ERR_INTERNAL;
+
+	FDT_CHECK_HEADER(fdt);
+
+	if (supernodedepth < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	for (offset = 0, depth = 0;
+	     (offset >= 0) && (offset <= nodeoffset);
+	     offset = fdt_next_node(fdt, offset, &depth)) {
+		if (depth == supernodedepth)
+			supernodeoffset = offset;
+
+		if (offset == nodeoffset) {
+			if (nodedepth)
+				*nodedepth = depth;
+
+			if (supernodedepth > depth)
+				return -FDT_ERR_NOTFOUND;
+			else
+				return supernodeoffset;
+		}
+	}
+
+	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+		return -FDT_ERR_BADOFFSET;
+	else if (offset == -FDT_ERR_BADOFFSET)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+	int nodedepth;
+	int err;
+
+	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+	if (err)
+		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+	return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+	int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+	if (nodedepth < 0)
+		return nodedepth;
+	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+					    nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen)
+{
+	int offset;
+	const void *val;
+	int len;
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_getprop(), then if that didn't
+	 * find what we want, we scan over them again making our way
+	 * to the next node.  Still it's the easiest to implement
+	 * approach; performance can come later. */
+	for (offset = fdt_next_node(fdt, startoffset, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		val = fdt_getprop(fdt, offset, propname, &len);
+		if (val && (len == proplen)
+		    && (memcmp(val, propval, len) == 0))
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+	int offset;
+
+	if ((phandle == 0) || (phandle == -1))
+		return -FDT_ERR_BADPHANDLE;
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we
+	 * potentially scan each property of a node in
+	 * fdt_get_phandle(), then if that didn't find what
+	 * we want, we scan over them again making our way to the next
+	 * node.  Still it's the easiest to implement approach;
+	 * performance can come later. */
+	for (offset = fdt_next_node(fdt, -1, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		if (fdt_get_phandle(fdt, offset) == phandle)
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
+}
+
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+				    const char *str)
+{
+	int len = strlen(str);
+	const char *p;
+
+	while (listlen >= len) {
+		if (memcmp(str, strlist, len+1) == 0)
+			return 1;
+		p = memchr(strlist, '\0', listlen);
+		if (!p)
+			return 0; /* malformed strlist.. */
+		listlen -= (p-strlist) + 1;
+		strlist = p + 1;
+	}
+	return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible)
+{
+	const void *prop;
+	int len;
+
+	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+	if (!prop)
+		return len;
+	if (_fdt_stringlist_contains(prop, len, compatible))
+		return 0;
+	else
+		return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible)
+{
+	int offset, err;
+
+	FDT_CHECK_HEADER(fdt);
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_node_check_compatible(), then if
+	 * that didn't find what we want, we scan over them again
+	 * making our way to the next node.  Still it's the easiest to
+	 * implement approach; performance can come later. */
+	for (offset = fdt_next_node(fdt, startoffset, NULL);
+	     offset >= 0;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		err = fdt_node_check_compatible(fdt, offset, compatible);
+		if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+			return err;
+		else if (err == 0)
+			return offset;
+	}
+
+	return offset; /* error from fdt_next_node() */
+}
diff --git a/extras/mini-os/lib/fdt/fdt_rw.c b/extras/mini-os/lib/fdt/fdt_rw.c
new file mode 100644
index 0000000..24437df
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_rw.c
@@ -0,0 +1,492 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_blocks_misordered(const void *fdt,
+			      int mem_rsv_size, int struct_size)
+{
+	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
+		|| (fdt_off_dt_struct(fdt) <
+		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+		|| (fdt_off_dt_strings(fdt) <
+		    (fdt_off_dt_struct(fdt) + struct_size))
+		|| (fdt_totalsize(fdt) <
+		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int _fdt_rw_check_header(void *fdt)
+{
+	FDT_CHECK_HEADER(fdt);
+
+	if (fdt_version(fdt) < 17)
+		return -FDT_ERR_BADVERSION;
+	if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+				   fdt_size_dt_struct(fdt)))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_version(fdt) > 17)
+		fdt_set_version(fdt, 17);
+
+	return 0;
+}
+
+#define FDT_RW_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = _fdt_rw_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static inline int _fdt_data_size(void *fdt)
+{
+	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+{
+	char *p = splicepoint;
+	char *end = (char *)fdt + _fdt_data_size(fdt);
+
+	if (((p + oldlen) < p) || ((p + oldlen) > end))
+		return -FDT_ERR_BADOFFSET;
+	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+		return -FDT_ERR_NOSPACE;
+	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	return 0;
+}
+
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+			       int oldn, int newn)
+{
+	int delta = (newn - oldn) * sizeof(*p);
+	int err;
+	err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+	if (err)
+		return err;
+	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _fdt_splice_struct(void *fdt, void *p,
+			      int oldlen, int newlen)
+{
+	int delta = newlen - oldlen;
+	int err;
+
+	if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+		return err;
+
+	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _fdt_splice_string(void *fdt, int newlen)
+{
+	void *p = (char *)fdt
+		+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+	int err;
+
+	if ((err = _fdt_splice(fdt, p, 0, newlen)))
+		return err;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+	return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+	const char *p;
+	char *new;
+	int len = strlen(s) + 1;
+	int err;
+
+	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+	if (p)
+		/* found it */
+		return (p - strtab);
+
+	new = strtab + fdt_size_dt_strings(fdt);
+	err = _fdt_splice_string(fdt, len);
+	if (err)
+		return err;
+
+	memcpy(new, s, len);
+	return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int err;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+	err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+	if (err)
+		return err;
+
+	re->address = cpu_to_fdt64(address);
+	re->size = cpu_to_fdt64(size);
+	return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+	int err;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	if (n >= fdt_num_mem_rsv(fdt))
+		return -FDT_ERR_NOTFOUND;
+
+	err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+				int len, struct fdt_property **prop)
+{
+	int oldlen;
+	int err;
+
+	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (! (*prop))
+		return oldlen;
+
+	if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+				      FDT_TAGALIGN(len))))
+		return err;
+
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+			     int len, struct fdt_property **prop)
+{
+	int proplen;
+	int nextoffset;
+	int namestroff;
+	int err;
+
+	if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+		return nextoffset;
+
+	namestroff = _fdt_find_add_string(fdt, name);
+	if (namestroff < 0)
+		return namestroff;
+
+	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
+	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
+
+	err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+	if (err)
+		return err;
+
+	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
+	(*prop)->nameoff = cpu_to_fdt32(namestroff);
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+	char *namep;
+	int oldlen, newlen;
+	int err;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+	if (!namep)
+		return oldlen;
+
+	newlen = strlen(name);
+
+	err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+				 FDT_TAGALIGN(newlen+1));
+	if (err)
+		return err;
+
+	memcpy(namep, name, newlen+1);
+	return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+	if (err == -FDT_ERR_NOTFOUND)
+		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+	if (err)
+		return err;
+
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err, oldlen, newlen;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (prop) {
+		newlen = len + oldlen;
+		err = _fdt_splice_struct(fdt, prop->data,
+					 FDT_TAGALIGN(oldlen),
+					 FDT_TAGALIGN(newlen));
+		if (err)
+			return err;
+		prop->len = cpu_to_fdt32(newlen);
+		memcpy(prop->data + oldlen, val, len);
+	} else {
+		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		if (err)
+			return err;
+		memcpy(prop->data, val, len);
+	}
+	return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len, proplen;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+	return _fdt_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen)
+{
+	struct fdt_node_header *nh;
+	int offset, nextoffset;
+	int nodelen;
+	int err;
+	uint32_t tag;
+	uint32_t *endtag;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+	if (offset >= 0)
+		return -FDT_ERR_EXISTS;
+	else if (offset != -FDT_ERR_NOTFOUND)
+		return offset;
+
+	/* Try to place the new node after the parent's properties */
+	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+	nh = _fdt_offset_ptr_w(fdt, offset);
+	nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
+
+	err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+	if (err)
+		return err;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
+	memcpy(nh->name, name, namelen);
+	endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+	*endtag = cpu_to_fdt32(FDT_END_NODE);
+
+	return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+				  endoffset - nodeoffset, 0);
+}
+
+static void _fdt_packblocks(const char *old, char *new,
+			    int mem_rsv_size, int struct_size)
+{
+	int mem_rsv_off, struct_off, strings_off;
+
+	mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
+	struct_off = mem_rsv_off + mem_rsv_size;
+	strings_off = struct_off + struct_size;
+
+	memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+	fdt_set_off_mem_rsvmap(new, mem_rsv_off);
+
+	memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+	fdt_set_off_dt_struct(new, struct_off);
+	fdt_set_size_dt_struct(new, struct_size);
+
+	memmove(new + strings_off, old + fdt_off_dt_strings(old),
+		fdt_size_dt_strings(old));
+	fdt_set_off_dt_strings(new, strings_off);
+	fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+	int err;
+	int mem_rsv_size, struct_size;
+	int newsize;
+	const char *fdtstart = fdt;
+	const char *fdtend = fdtstart + fdt_totalsize(fdt);
+	char *tmp;
+
+	FDT_CHECK_HEADER(fdt);
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+
+	if (fdt_version(fdt) >= 17) {
+		struct_size = fdt_size_dt_struct(fdt);
+	} else {
+		struct_size = 0;
+		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+			;
+		if (struct_size < 0)
+			return struct_size;
+	}
+
+	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+		/* no further work necessary */
+		err = fdt_move(fdt, buf, bufsize);
+		if (err)
+			return err;
+		fdt_set_version(buf, 17);
+		fdt_set_size_dt_struct(buf, struct_size);
+		fdt_set_totalsize(buf, bufsize);
+		return 0;
+	}
+
+	/* Need to reorder */
+	newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+		+ struct_size + fdt_size_dt_strings(fdt);
+
+	if (bufsize < newsize)
+		return -FDT_ERR_NOSPACE;
+
+	/* First attempt to build converted tree at beginning of buffer */
+	tmp = buf;
+	/* But if that overlaps with the old tree... */
+	if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+		/* Try right after the old tree instead */
+		tmp = (char *)(uintptr_t)fdtend;
+		if ((tmp + newsize) > ((char *)buf + bufsize))
+			return -FDT_ERR_NOSPACE;
+	}
+
+	_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+	memmove(buf, tmp, newsize);
+
+	fdt_set_magic(buf, FDT_MAGIC);
+	fdt_set_totalsize(buf, bufsize);
+	fdt_set_version(buf, 17);
+	fdt_set_last_comp_version(buf, 16);
+	fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+	return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+	int mem_rsv_size;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+	_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+	fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+
+	return 0;
+}
diff --git a/extras/mini-os/lib/fdt/fdt_strerror.c b/extras/mini-os/lib/fdt/fdt_strerror.c
new file mode 100644
index 0000000..e6c3cee
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct fdt_errtabent {
+	const char *str;
+};
+
+#define FDT_ERRTABENT(val) \
+	[(val)] = { .str = #val, }
+
+static struct fdt_errtabent fdt_errtable[] = {
+	FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+	FDT_ERRTABENT(FDT_ERR_EXISTS),
+	FDT_ERRTABENT(FDT_ERR_NOSPACE),
+
+	FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+	FDT_ERRTABENT(FDT_ERR_BADPATH),
+	FDT_ERRTABENT(FDT_ERR_BADSTATE),
+
+	FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+	FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+	FDT_ERRTABENT(FDT_ERR_BADVERSION),
+	FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+	FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+	if (errval > 0)
+		return "<valid offset/length>";
+	else if (errval == 0)
+		return "<no error>";
+	else if (errval > -FDT_ERRTABSIZE) {
+		const char *s = fdt_errtable[-errval].str;
+
+		if (s)
+			return s;
+	}
+
+	return "<unknown error>";
+}
diff --git a/extras/mini-os/lib/fdt/fdt_sw.c b/extras/mini-os/lib/fdt/fdt_sw.c
new file mode 100644
index 0000000..55ebebf
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_sw.c
@@ -0,0 +1,256 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_sw_check_header(void *fdt)
+{
+	if (fdt_magic(fdt) != FDT_SW_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	/* FIXME: should check more details about the header state */
+	return 0;
+}
+
+#define FDT_SW_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = _fdt_sw_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static void *_fdt_grab_space(void *fdt, size_t len)
+{
+	int offset = fdt_size_dt_struct(fdt);
+	int spaceleft;
+
+	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+		- fdt_size_dt_strings(fdt);
+
+	if ((offset + len < offset) || (offset + len > spaceleft))
+		return NULL;
+
+	fdt_set_size_dt_struct(fdt, offset + len);
+	return _fdt_offset_ptr_w(fdt, offset);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+	void *fdt = buf;
+
+	if (bufsize < sizeof(struct fdt_header))
+		return -FDT_ERR_NOSPACE;
+
+	memset(buf, 0, bufsize);
+
+	fdt_set_magic(fdt, FDT_SW_MAGIC);
+	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_totalsize(fdt,  bufsize);
+
+	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+	fdt_set_off_dt_strings(fdt, bufsize);
+
+	return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int offset;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	if (fdt_size_dt_struct(fdt))
+		return -FDT_ERR_BADSTATE;
+
+	offset = fdt_off_dt_struct(fdt);
+	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+		return -FDT_ERR_NOSPACE;
+
+	re = (struct fdt_reserve_entry *)((char *)fdt + offset);
+	re->address = cpu_to_fdt64(addr);
+	re->size = cpu_to_fdt64(size);
+
+	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+	return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+	return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+	struct fdt_node_header *nh;
+	int namelen = strlen(name) + 1;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+	if (! nh)
+		return -FDT_ERR_NOSPACE;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memcpy(nh->name, name, namelen);
+	return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+	uint32_t *en;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+	if (! en)
+		return -FDT_ERR_NOSPACE;
+
+	*en = cpu_to_fdt32(FDT_END_NODE);
+	return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	const char *p;
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+	int struct_top, offset;
+
+	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	/* Add it */
+	offset = -strtabsize - len;
+	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	if (fdt_totalsize(fdt) + offset < struct_top)
+		return 0; /* no more room :( */
+
+	memcpy(strtab + offset, s, len);
+	fdt_set_size_dt_strings(fdt, strtabsize + len);
+	return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+	struct fdt_property *prop;
+	int nameoff;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	nameoff = _fdt_find_add_string(fdt, name);
+	if (nameoff == 0)
+		return -FDT_ERR_NOSPACE;
+
+	prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+	if (! prop)
+		return -FDT_ERR_NOSPACE;
+
+	prop->tag = cpu_to_fdt32(FDT_PROP);
+	prop->nameoff = cpu_to_fdt32(nameoff);
+	prop->len = cpu_to_fdt32(len);
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+	char *p = (char *)fdt;
+	uint32_t *end;
+	int oldstroffset, newstroffset;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	/* Add terminator */
+	end = _fdt_grab_space(fdt, sizeof(*end));
+	if (! end)
+		return -FDT_ERR_NOSPACE;
+	*end = cpu_to_fdt32(FDT_END);
+
+	/* Relocate the string table */
+	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+	fdt_set_off_dt_strings(fdt, newstroffset);
+
+	/* Walk the structure, correcting string offsets */
+	offset = 0;
+	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+		if (tag == FDT_PROP) {
+			struct fdt_property *prop =
+				_fdt_offset_ptr_w(fdt, offset);
+			int nameoff;
+
+			nameoff = fdt32_to_cpu(prop->nameoff);
+			nameoff += fdt_size_dt_strings(fdt);
+			prop->nameoff = cpu_to_fdt32(nameoff);
+		}
+		offset = nextoffset;
+	}
+	if (nextoffset < 0)
+		return nextoffset;
+
+	/* Finally, adjust the header */
+	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+	fdt_set_magic(fdt, FDT_MAGIC);
+	return 0;
+}
diff --git a/extras/mini-os/lib/fdt/fdt_wip.c b/extras/mini-os/lib/fdt/fdt_wip.c
new file mode 100644
index 0000000..6025fa1
--- /dev/null
+++ b/extras/mini-os/lib/fdt/fdt_wip.c
@@ -0,0 +1,118 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len)
+{
+	void *propval;
+	int proplen;
+
+	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	if (! propval)
+		return proplen;
+
+	if (proplen != len)
+		return -FDT_ERR_NOSPACE;
+
+	memcpy(propval, val, len);
+	return 0;
+}
+
+static void _fdt_nop_region(void *start, int len)
+{
+	uint32_t *p;
+
+	for (p = start; (char *)p < ((char *)start + len); p++)
+		*p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len;
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	_fdt_nop_region(prop, len + sizeof(*prop));
+
+	return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int offset)
+{
+	int depth = 0;
+
+	while ((offset >= 0) && (depth >= 0))
+		offset = fdt_next_node(fdt, offset, &depth);
+
+	return offset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+			endoffset - nodeoffset);
+	return 0;
+}
diff --git a/extras/mini-os/lib/fdt/libfdt_internal.h b/extras/mini-os/lib/fdt/libfdt_internal.h
new file mode 100644
index 0000000..381133b
--- /dev/null
+++ b/extras/mini-os/lib/fdt/libfdt_internal.h
@@ -0,0 +1,95 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <fdt.h>
+
+#define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
+
+#define FDT_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+	return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+	return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+	const struct fdt_reserve_entry *rsv_table =
+		(const struct fdt_reserve_entry *)
+		((const char *)fdt + fdt_off_mem_rsvmap(fdt));
+
+	return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+	return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+}
+
+#define FDT_SW_MAGIC		(~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/extras/mini-os/lib/memmove.c b/extras/mini-os/lib/memmove.c
new file mode 100644
index 0000000..0298b7c
--- /dev/null
+++ b/extras/mini-os/lib/memmove.c
@@ -0,0 +1,45 @@
+/*
+ *	memmove.c: memmove compat implementation.
+ *
+ *	Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+ *
+ * See COPYING for the license.
+*/
+
+#include <os.h>
+#include <mini-os/lib.h>
+
+#ifndef HAVE_LIBC
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+	uint8_t* from = (uint8_t*) src;
+	uint8_t* to = (uint8_t*) dest;
+
+	if (from == to || n == 0)
+		return dest;
+	if (to > from && to-from < (int)n) {
+		/* to overlaps with from */
+		/*  <from......>         */
+		/*         <to........>  */
+		/* copy in reverse, to avoid overwriting from */
+		int i;
+		for(i=n-1; i>=0; i--)
+			to[i] = from[i];
+		return dest;
+	}
+	if (from > to  && from-to < (int)n) {
+		/* to overlaps with from */
+		/*        <from......>   */
+		/*  <to........>         */
+		/* copy forwards, to avoid overwriting from */
+		size_t i;
+		for(i=0; i<n; i++)
+			to[i] = from[i];
+		return dest;
+	}
+	memcpy(dest, src, n);
+	return dest;
+}
+
+#endif
diff --git a/extras/mini-os/lib/string.c b/extras/mini-os/lib/string.c
index 8b24146..e0ad76d 100644
--- a/extras/mini-os/lib/string.c
+++ b/extras/mini-os/lib/string.c
@@ -225,4 +225,16 @@ int ffs(int i)
    return 0;
 }
 
+void *memchr(const void *s, int c, size_t n)
+{
+        if (n != 0) {
+                const unsigned char *p = s;
+
+                do {
+                        if (*p++ == (unsigned char)c)
+                                return ((void *)(uintptr_t)(p - 1));
+                } while (--n != 0);
+        }
+        return (NULL);
+}
 #endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] mini-os: Fixed shutdown thread
  2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
@ 2014-06-03  0:51   ` Samuel Thibault
  2014-06-03  9:01   ` Andrew Cooper
  1 sibling, 0 replies; 44+ messages in thread
From: Samuel Thibault @ 2014-06-03  0:51 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, stefano.stabellini

Thomas Leonard, le Mon 02 Jun 2014 18:49:54 +0100, a écrit :
> Before, it read "" and started a shutdown immediately. Now, it waits for
> a non-empty value and then actually shuts down.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

> ---
>  extras/mini-os/kernel.c | 16 ++++++++++++----
>  extras/mini-os/main.c   |  2 +-
>  2 files changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
> index ea409f4..386be8f 100644
> --- a/extras/mini-os/kernel.c
> +++ b/extras/mini-os/kernel.c
> @@ -69,6 +69,8 @@ void setup_xen_features(void)
>  __attribute__((weak)) void app_shutdown(unsigned reason)
>  {
>      printk("Shutdown requested: %d\n", reason);
> +    struct sched_shutdown sched_shutdown = { .reason = reason };
> +    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
>  }
>  
>  static void shutdown_thread(void *p)
> @@ -76,12 +78,18 @@ static void shutdown_thread(void *p)
>      const char *path = "control/shutdown";
>      const char *token = path;
>      xenbus_event_queue events = NULL;
> -    char *shutdown, *err;
> +    char *shutdown = NULL, *err;
>      unsigned int shutdown_reason;
>      xenbus_watch_path_token(XBT_NIL, path, token, &events);
> -    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL)
> +    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
>      {
> -        free(err);
> +        if (err)
> +            free(err);
> +        if (shutdown)
> +        {
> +            free(shutdown);
> +            shutdown = NULL;
> +        }
>          xenbus_wait_for_watch(&events);
>      }
>      err = xenbus_unwatch_path_token(XBT_NIL, path, token);
> @@ -106,7 +114,7 @@ static void shutdown_thread(void *p)
>  /* This should be overridden by the application we are linked against. */
>  __attribute__((weak)) int app_main(start_info_t *si)
>  {
> -    printk("Dummy main: start_info=%p\n", si);
> +    printk("kernel.c: dummy main: start_info=%p\n", si);
>      return 0;
>  }
>  
> diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
> index 73eb6fb..aec0586 100644
> --- a/extras/mini-os/main.c
> +++ b/extras/mini-os/main.c
> @@ -185,7 +185,7 @@ void _exit(int ret)
>  
>  int app_main(start_info_t *si)
>  {
> -    printk("Dummy main: start_info=%p\n", si);
> +    printk("main.c: dummy main: start_info=%p\n", si);
>      main_thread = create_thread("main", call_main, si);
>      return 0;
>  }
> -- 
> 1.9.3
> 

-- 
Samuel
<y> ça gaze ?
<l> prout
 -+- #ens-mim - ouvrez les fenêtres ! -+-

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/4] mini-os: Tidied up code
  2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
@ 2014-06-03  0:57   ` Samuel Thibault
  0 siblings, 0 replies; 44+ messages in thread
From: Samuel Thibault @ 2014-06-03  0:57 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, stefano.stabellini

Thomas Leonard, le Mon 02 Jun 2014 18:49:55 +0100, a écrit :
> +#define DEBUG(_f, _a...) \
> +    printk("MINI_OS(file=gntmap.c, line=%d) " _f "\n", __LINE__, ## _a)

While at it, this could use %s and __func__ to automatically print the
function name.

> --- a/extras/mini-os/include/x86/arch_spinlock.h
> +++ b/extras/mini-os/include/x86/arch_spinlock.h
> @@ -61,7 +61,7 @@
>  
>  static inline void _raw_spin_unlock(spinlock_t *lock)
>  {
> -	char oldval = 1;
> +	char oldval = ARCH_SPIN_LOCK_UNLOCKED;

It looks a bit odd to the compiler, but it's valid and better, indeed.

Apart from the __func__ nitpicking,

Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

Samuel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] mini-os: Fixed shutdown thread
  2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
  2014-06-03  0:51   ` Samuel Thibault
@ 2014-06-03  9:01   ` Andrew Cooper
  1 sibling, 0 replies; 44+ messages in thread
From: Andrew Cooper @ 2014-06-03  9:01 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel; +Cc: samuel.thibault, stefano.stabellini

On 02/06/2014 18:49, Thomas Leonard wrote:
> Before, it read "" and started a shutdown immediately. Now, it waits for
> a non-empty value and then actually shuts down.
>
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/kernel.c | 16 ++++++++++++----
>  extras/mini-os/main.c   |  2 +-
>  2 files changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
> index ea409f4..386be8f 100644
> --- a/extras/mini-os/kernel.c
> +++ b/extras/mini-os/kernel.c
> @@ -69,6 +69,8 @@ void setup_xen_features(void)
>  __attribute__((weak)) void app_shutdown(unsigned reason)
>  {
>      printk("Shutdown requested: %d\n", reason);
> +    struct sched_shutdown sched_shutdown = { .reason = reason };
> +    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
>  }
>  
>  static void shutdown_thread(void *p)
> @@ -76,12 +78,18 @@ static void shutdown_thread(void *p)
>      const char *path = "control/shutdown";
>      const char *token = path;
>      xenbus_event_queue events = NULL;
> -    char *shutdown, *err;
> +    char *shutdown = NULL, *err;
>      unsigned int shutdown_reason;
>      xenbus_watch_path_token(XBT_NIL, path, token, &events);
> -    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL)
> +    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
>      {
> -        free(err);
> +        if (err)
> +            free(err);

NULL is a perfectly valid parameter to free(). Please drop the if()

> +        if (shutdown)
> +        {
> +            free(shutdown);
> +            shutdown = NULL;
> +        }

Here as well.

~Andrew

>          xenbus_wait_for_watch(&events);
>      }
>      err = xenbus_unwatch_path_token(XBT_NIL, path, token);
> @@ -106,7 +114,7 @@ static void shutdown_thread(void *p)
>  /* This should be overridden by the application we are linked against. */
>  __attribute__((weak)) int app_main(start_info_t *si)
>  {
> -    printk("Dummy main: start_info=%p\n", si);
> +    printk("kernel.c: dummy main: start_info=%p\n", si);
>      return 0;
>  }
>  
> diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
> index 73eb6fb..aec0586 100644
> --- a/extras/mini-os/main.c
> +++ b/extras/mini-os/main.c
> @@ -185,7 +185,7 @@ void _exit(int ret)
>  
>  int app_main(start_info_t *si)
>  {
> -    printk("Dummy main: start_info=%p\n", si);
> +    printk("main.c: dummy main: start_info=%p\n", si);
>      main_thread = create_thread("main", call_main, si);
>      return 0;
>  }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] mini-os: Initial commit to port minios to ARM
  2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
@ 2014-06-03  9:12   ` Julien Grall
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Julien Grall @ 2014-06-03  9:12 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel; +Cc: samuel.thibault, stefano.stabellini

Hi Thomas,

Thank you for the port of Minos on ARM!

This patch is a bit complex to read (nearly 3000 lines).

There is some change in the common code. It might be easier to move all 
those changes in a separate patch.

Same for the code imported from NetBSD.

Regards,


On 02/06/14 18:49, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>
> On ARM, Mini-OS will boot and display some output on the Xen emergency
> console (only visible if Xen is compiled in debug mode). Tested with:
>
> make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
>    CONFIG_TEST=n CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
>    CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
>    CONFIG_CONSFRONT=n CONFIG_XC=n
>
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: made x86_64 support work again]
> [talex5@gmail.com: split into multiple patches]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>   extras/mini-os/ARM-TODO.txt                        |  19 +
>   extras/mini-os/Config.mk                           |   2 +
>   extras/mini-os/Makefile                            |  12 +
>   extras/mini-os/arch/arm/Makefile                   |  33 ++
>   extras/mini-os/arch/arm/arch.mk                    |   6 +
>   extras/mini-os/arch/arm/arm32.S                    | 211 +++++++++++
>   extras/mini-os/arch/arm/divsi3.S                   | 404 +++++++++++++++++++++
>   extras/mini-os/arch/arm/events.c                   |  24 ++
>   extras/mini-os/arch/arm/hypercalls32.S             |  88 +++++
>   extras/mini-os/arch/arm/ldivmod.S                  |  67 ++++
>   extras/mini-os/arch/arm/ldivmod_helper.c           |  66 ++++
>   extras/mini-os/arch/arm/minios-arm32.lds           |  73 ++++
>   extras/mini-os/arch/arm/mm.c                       |  44 +++
>   extras/mini-os/arch/arm/qdivrem.c                  | 270 ++++++++++++++
>   extras/mini-os/arch/arm/sched.c                    |  32 ++
>   extras/mini-os/arch/arm/setup.c                    |  55 +++
>   extras/mini-os/arch/arm/time.c                     | 232 ++++++++++++
>   extras/mini-os/arch/arm/xenbus.c                   |  36 ++
>   extras/mini-os/arch/x86/events.c                   |  28 ++
>   extras/mini-os/arch/x86/setup.c                    |  44 ++-
>   extras/mini-os/arch/x86/time.c                     |   4 +-
>   extras/mini-os/arch/x86/x86_32.S                   |   2 +-
>   extras/mini-os/arch/x86/x86_64.S                   |   2 +-
>   extras/mini-os/arch/x86/xenbus.c                   |  10 +
>   extras/mini-os/console/console.c                   |   2 +
>   extras/mini-os/drivers/gic.c                       | 179 +++++++++
>   extras/mini-os/events.c                            |  32 +-
>   extras/mini-os/gntmap.c                            |   1 +
>   extras/mini-os/gnttab.c                            |   1 +
>   extras/mini-os/hypervisor.c                        |  20 +-
>   extras/mini-os/include/arm/arch_limits.h           |   9 +
>   extras/mini-os/include/arm/arch_mm.h               |  37 ++
>   extras/mini-os/include/arm/arch_sched.h            |  22 ++
>   extras/mini-os/include/arm/arch_spinlock.h         |  49 +++
>   extras/mini-os/include/arm/hypercall-arm32.h       | 173 +++++++++
>   extras/mini-os/include/arm/os.h                    | 314 ++++++++++++++++
>   extras/mini-os/include/arm/traps.h                 |  20 +
>   extras/mini-os/include/console.h                   |   1 +
>   extras/mini-os/include/hypervisor.h                |  19 +-
>   extras/mini-os/include/mm.h                        |   2 +
>   extras/mini-os/include/types.h                     |  73 +++-
>   extras/mini-os/include/x86/arch_mm.h               |   2 +
>   extras/mini-os/include/x86/os.h                    |  19 +-
>   .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |   1 +
>   extras/mini-os/kernel.c                            |  78 ++--
>   extras/mini-os/mm.c                                |   9 +-
>   extras/mini-os/sched.c                             |   9 +-
>   extras/mini-os/time.c                              |  12 +
>   extras/mini-os/xenbus/xenbus.c                     |  18 +-
>   49 files changed, 2758 insertions(+), 108 deletions(-)
>   create mode 100644 extras/mini-os/ARM-TODO.txt
>   create mode 100755 extras/mini-os/arch/arm/Makefile
>   create mode 100644 extras/mini-os/arch/arm/arch.mk
>   create mode 100644 extras/mini-os/arch/arm/arm32.S
>   create mode 100644 extras/mini-os/arch/arm/divsi3.S
>   create mode 100644 extras/mini-os/arch/arm/events.c
>   create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>   create mode 100644 extras/mini-os/arch/arm/ldivmod.S
>   create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
>   create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
>   create mode 100644 extras/mini-os/arch/arm/mm.c
>   create mode 100644 extras/mini-os/arch/arm/qdivrem.c
>   create mode 100644 extras/mini-os/arch/arm/sched.c
>   create mode 100644 extras/mini-os/arch/arm/setup.c
>   create mode 100644 extras/mini-os/arch/arm/time.c
>   create mode 100644 extras/mini-os/arch/arm/xenbus.c
>   create mode 100644 extras/mini-os/arch/x86/events.c
>   create mode 100644 extras/mini-os/arch/x86/xenbus.c
>   create mode 100644 extras/mini-os/drivers/gic.c
>   create mode 100644 extras/mini-os/include/arm/arch_limits.h
>   create mode 100644 extras/mini-os/include/arm/arch_mm.h
>   create mode 100644 extras/mini-os/include/arm/arch_sched.h
>   create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
>   create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
>   create mode 100644 extras/mini-os/include/arm/os.h
>   create mode 100644 extras/mini-os/include/arm/traps.h
>   create mode 100644 extras/mini-os/time.c
>
> diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
> new file mode 100644
> index 0000000..57d531a
> --- /dev/null
> +++ b/extras/mini-os/ARM-TODO.txt
> @@ -0,0 +1,19 @@
> +* os.h bit manipulation, write optimized assembly code
> +* support abort exception handling ( and others )
> +* scheduling!
> +* use proper memory types and enable caches (L1 and L2)
> +* Use LDREX and STREX in xchg implementation ( code already there but it causes an abort, I think because of using strong-ordered memory with disabled L1 caches - something to do with the implementation of the monitor on cortex-a7 )
> +* gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler.
> +* use device tree instead of the currently hardcoded values
> +* Add virtual memory support and make vstart = 0 ( use 4k descriptors instead of 1M descriptors )
> +* sched
> +* fini_gnttab
> +* fini_time
> +* bind_*
> +* add multiple cpu support (?)
> +* map_frames
> +* clean up the code and remove redundent code between arm and x86
> +* remove start_info structure from the common code
> +* make sure that wallclock is functioning properly
> +* console support
> +* evtchn_get_peercontext
> diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
> index d61877b..4ecde54 100644
> --- a/extras/mini-os/Config.mk
> +++ b/extras/mini-os/Config.mk
> @@ -12,6 +12,8 @@ export XEN_INTERFACE_VERSION
>   # If not x86 then use $(XEN_TARGET_ARCH)
>   ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_)
>   TARGET_ARCH_FAM = x86
> +else ifeq ($(findstring arm,$(XEN_TARGET_ARCH)),arm)
> +TARGET_ARCH_FAM = arm
>   else
>   TARGET_ARCH_FAM = $(XEN_TARGET_ARCH)
>   endif
> diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
> index 50d038b..0fd38a8 100644
> --- a/extras/mini-os/Makefile
> +++ b/extras/mini-os/Makefile
> @@ -72,6 +72,11 @@ TARGET := mini-os
>   # Subdirectories common to mini-os
>   SUBDIRS := lib xenbus console
>
> +ifeq ($(XEN_TARGET_ARCH),arm32)
> +# ARM drivers
> +src-y += drivers/gic.c
> +endif
> +
>   src-$(CONFIG_BLKFRONT) += blkfront.c
>   src-$(CONFIG_TPMFRONT) += tpmfront.c
>   src-$(CONFIG_TPM_TIS) += tpm_tis.c
> @@ -82,6 +87,7 @@ src-$(CONFIG_FBFRONT) += fbfront.c
>   src-y += gntmap.c
>   src-y += gnttab.c
>   src-y += hypervisor.c
> +src-y += time.c
>   src-y += kernel.c
>   src-y += lock.c
>   src-y += main.c
> @@ -92,7 +98,9 @@ src-y += sched.c
>   src-$(CONFIG_TEST) += test.c
>
>   src-y += lib/ctype.c
> +ifneq ($(XEN_TARGET_ARCH),arm32)
>   src-y += lib/math.c
> +endif
>   src-y += lib/printf.c
>   src-y += lib/stack_chk_fail.c
>   src-y += lib/string.c
> @@ -178,7 +186,11 @@ $(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) $(APP_O) arch_lib
>   	$(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
>   	$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
>   	$(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
> +ifeq ($(XEN_TARGET_ARCH),arm32)
> +	$(OBJCOPY) -O binary $@ $@.img
> +else
>   	gzip -f -9 -c $@ >$@.gz
> +endif
>
>   .PHONY: clean arch_clean
>
> diff --git a/extras/mini-os/arch/arm/Makefile b/extras/mini-os/arch/arm/Makefile
> new file mode 100755
> index 0000000..d8ecc88
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/Makefile
> @@ -0,0 +1,33 @@
> +#
> +# x86 architecture specific makefiles.
> +# It's is used for x86_32, x86_32y and x86_64
> +#
> +
> +XEN_ROOT = $(CURDIR)/../../../..
> +include $(XEN_ROOT)/Config.mk
> +include ../../Config.mk
> +
> +# include arch.mk has to be before mini-os.mk!
> +
> +include arch.mk
> +include ../../minios.mk
> +
> +# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S
> +# This is handled in $(HEAD_ARCH_OBJ)
> +ARCH_SRCS := $(wildcard *.c)
> +
> +# The objects built from the sources.
> +ARCH_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ARCH_SRCS))
> +
> +ARCH_OBJS += hypercalls32.o divsi3.o ldivmod.o
> +
> +all: $(OBJ_DIR)/$(ARCH_LIB)
> +
> +# $(HEAD_ARCH_OBJ) is only build here, needed on linking
> +# in ../../Makefile.
> +$(OBJ_DIR)/$(ARCH_LIB): $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
> +	$(AR) rv $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS)
> +
> +clean:
> +	rm -f $(OBJ_DIR)/$(ARCH_LIB) $(ARCH_OBJS) $(OBJ_DIR)/$(HEAD_ARCH_OBJ)
> +
> diff --git a/extras/mini-os/arch/arm/arch.mk b/extras/mini-os/arch/arm/arch.mk
> new file mode 100644
> index 0000000..d2e0946
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/arch.mk
> @@ -0,0 +1,6 @@
> +ifeq ($(XEN_TARGET_ARCH),arm32)
> +ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__ #-DCPU_EXCLUSIVE_LDST
> +EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
> +EXTRA_SRC += arch/$(EXTRA_INC)
> +endif
> +
> diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
> new file mode 100644
> index 0000000..2dd0f6c
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/arm32.S
> @@ -0,0 +1,211 @@
> +#define PHYS_START (0x80008000)
> +
> +.section .text
> +
> +.globl _start
> +_start:
> +	@ zImage header
> +.rept   8
> +        mov     r0, r0
> +.endr
> +        b       1f
> +        .word   0x016f2818      @ Magic numbers to help the loader
> +        .word   _start		@ absolute load/run zImage address
> +        .word   _end - _start   @ zImage size
> +	@ end of zImage header
> +
> +1:
> +#if FIXME
> +@ core processor specific initialization
> +	@ Initialize ACTLR core register
> +	mrc p15, 0, <Rt>, c1, c0, 1
> +	mcr p15, 0, <Rt>, c1, c0, 1
> +#endif
> +
> +@ Save dtb pointer passed by the hypervisor
> +	mov	r4, r2		@ save dtb pointer
> +
> +@ Build pagetables
> +	bl	build_pagetables
> +
> +	ldr	r2, =page_dir
> +	MCR	p15, 0, r2, c2, c0, 0	@ set ttbr0
> +
> +	@ Set access permission for domains
> +	mov	r0, #0x3
> +	MCR	p15, 0, r0, c3, c0, 0
> +	isb
> +	
> +	ldr	r0, =mmu_switched
> +
> +	@ enable mmu / sctlr
> +	mrc	p15, 0, r1, c1, c0, 0	@ read sctlr
> +	orr	r1, r1, #0x1		@ enable mmu
> +	@orr	r1, r1, #0x4		@ enable cache
> +	orr	r1, r1, #0x02		@ enable barrier enable
> +	@mcr	p15, 0, r1, c1, c0, 0	@ write sctlr
> +	isb
> +
> +	@ jump to the virtual address now
> +	mov	pc, r0
> +
> +@ If we're here, then we're very lucky
> +mmu_switched:
> +
> +@ set VBAR = exception_vector_table
> +	@ SCTLR.V = 0
> +	adr	r0, exception_vector_table
> +	mcr	p15, 0, r0, c12, c0, 0
> +
> +@ load stack
> +	ldr	sp, =stack
> +	add	sp, sp, #(4*4*1024)
> +
> +
> +	mov	r0, r4		@ set r0 = dtb pointer
> +	b	arch_init
> +
> +
> +@ Populate the whole pagedir with 1MB section descriptors for now (1-1 mapping)
> +build_pagetables:
> +	ldr	r0, =(0x2 + (1 << 16) + (1<<19)) @ First section entry (sharable + NS ).
> +	ldr	r1, =page_dir
> +	add	r2, r1, #(4*4*1024) @ Limit
> +
> +1:
> +	str	r0, [r1] @ write the section entry
> +
> +	add	r0, r0, #(1 << 20) @ next physical page.
> +	add	r1, r1, #4 @ next pagedir entry
> +	cmp	r1, r2
> +	bne	1b
> +
> +	mov	pc, lr
> +
> +.pushsection .data
> +.align 13
> +.globl stack
> +stack:
> +	.fill (4*1024), 4, 0x0
> +.align 13
> +irqstack:
> +	.fill (1024), 4, 0x0
> +.globl shared_info_page
> +.align 13
> +shared_info_page:
> +	.fill (1024), 4, 0x0
> +.align	14
> +page_dir:
> +	.fill (4*1024), 4, 0x0
> +
> +.popsection
> +
> +@ exception base address
> +.align 5
> +.globl exception_vector_table
> +exception_vector_table:
> +	b	. @ reset
> +	b	. @ undefined instruction
> +	b	. @ supervisor call
> +	b	. @ prefetch call
> +	b	. @ prefetch abort
> +	b	. @ data abort //FIXME CLREX
> +	b	irq_handler @ irq
> +	b	firq_handler @ firq
> +
> +irq_handler:
> +firq_handler:
> +	ldr	sp, =irqstack
> +	add	sp, sp, #(4*1024)
> +
> +	@ Save registers
> +	stmda	sp!, {r0 - r12}
> +	stmda	sp!, {lr}
> +
> +	@ FIXME Find interrupt id and dispatch to the correct handler.
> +	@ If event_irq
> +	ldr	r0, IRQ_handler
> +	cmp	r0, #0
> +	beq	. @ If no IRQ handler was setup, just get stuck here!
> +
> +	adr	lr, 1f
> +	mov	pc, r0
> +1:
> +	@bl	do_hypervisor_callback
> +
> +	@ Restore registers
> +	ldmib	sp!, {lr}
> +	ldmib	sp!, {r0 - r12}
> +
> +	@ Return from IRQ
> +	subs	pc, lr, #4
> +
> +.globl IRQ_handler
> +IRQ_handler:
> +	.long	0x0
> +
> +
> +.globl __arch_switch_threads
> +@ r0 = &prev->sp & r1 = &(next->sp)
> +__arch_switch_threads:
> +	@ store sp, ip for prev thread
> +	str	sp, [r0] @ sp
> +	str	lr, [r0, #4] @ ip
> +	str	fp, [sp, #-4] @ store fp on the stack
> +	@ Load sp, ip for next thread
> +	ldr	sp, [r1] @ sp
> +	ldr	lr, [r1, #4] @ ip
> +	ldr	fp, [sp, #-4] @ restore fp from the stack
> +	mov	pc, lr
> +
> +#if 0
> +pagetables_code:
> +	bl	build_pagetables
> +
> +	ldr	r2, =(page_dir+PHYS_START)
> +	MCR	p15, 0, r2, c2, c0, 0	@ set ttbr0
> +
> +	@ Set access permission for domains
> +	mov	r0, #0x3
> +	MCR	p15, 0, r0, c3, c0, 0
> +
> +	ldr	r0, =mmu_switched
> +
> +	@ enable mmu / sctlr
> +	isb
> +	MRC	p15, 0, r1, c1, c0, 0	@ read sctlr
> +	orr	r1, r1, #0x1
> +	MCR	p15, 0, r1, c1, c0, 0	@ write sctlr
> +	MRC     p15, 0, r1, c0, c0, 0	@ read id reg
> +
> +	@ jump to the virtual address now
> +	mov	pc, r0
> +
> +mmu_switched:
> +	b	.
> +
> +build_pagetables:
> +	ldr	r2, =(page_dir + PHYS_START)
> +	ldr	r0, =(pagetable + PHYS_START + 1)
> +	str	r0, [r2]
> +
> +	ldr	r2, =(pagetable + PHYS_START)
> +	add	r1, r2, #1000
> +
> +	@ setup entry
> +	ldr	r0, =(PHYS_START + 0x3)
> +2:
> +	str	r0, [r2], #4
> +	add	r0, r0, #1 << 12
> +	cmp	r2, r1
> +	bne	2b
> +	mov	pc, lr
> +
> +.pushsection .data
> +.align	14
> +page_dir:
> +	.fill (1024), 4, 0x0
> +pagetable:
> +	.fill (1024*50), 4, 0x0
> +.popsection
> +#endif
> diff --git a/extras/mini-os/arch/arm/divsi3.S b/extras/mini-os/arch/arm/divsi3.S
> new file mode 100644
> index 0000000..fa92233
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/divsi3.S
> @@ -0,0 +1,404 @@
> +/*	$NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $	*/
> +
> +/*-
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#define ENTRY_NP(symbol) \
> +	.globl symbol;	\
> +	symbol:
> +
> +#define END(symbol)
> +
> +/*
> + * stack is aligned as there's a possibility of branching to L_overflow
> + * which makes a C call
> + */
> +
> +ENTRY_NP(__umodsi3)
> +	stmfd	sp!, {lr}
> +	sub	sp, sp, #4	/* align stack */
> +	bl	.L_udivide
> +	add	sp, sp, #4	/* unalign stack */
> +	mov	r0, r1
> +	ldmfd	sp!, {pc}
> +END(__umodsi3)
> +
> +ENTRY_NP(__modsi3)
> +	stmfd	sp!, {lr}
> +	sub	sp, sp, #4	/* align stack */
> +	bl	.L_divide
> +	add	sp, sp, #4	/* unalign stack */
> +	mov	r0, r1
> +	ldmfd	sp!, {pc}
> +
> +.L_overflow:
> +	/* XXX should cause a fatal error */
> +	mvn	r0, #0
> +	mov	pc, lr
> +
> +END(__modsi3)
> +
> +#ifdef __ARM_EABI__
> +ENTRY_NP(__aeabi_uidiv)
> +ENTRY_NP(__aeabi_uidivmod)
> +#endif
> +ENTRY_NP(__udivsi3)
> +.L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
> +	eor     r0, r1, r0
> +	eor     r1, r0, r1
> +	eor     r0, r1, r0
> +					/* r0 = r1 / r0; r1 = r1 % r0 */
> +	cmp	r0, #1
> +	bcc	.L_overflow
> +	beq	.L_divide_l0
> +	mov	ip, #0
> +	movs	r1, r1
> +	bpl	.L_divide_l1
> +	orr	ip, ip, #0x20000000	/* ip bit 0x20000000 = -ve r1 */
> +	movs	r1, r1, lsr #1
> +	orrcs	ip, ip, #0x10000000	/* ip bit 0x10000000 = bit 0 of r1 */
> +	b	.L_divide_l1
> +
> +.L_divide_l0:				/* r0 == 1 */
> +	mov	r0, r1
> +	mov	r1, #0
> +	mov	pc, lr
> +#ifdef __ARM_EABI__
> +END(__aeabi_uidiv)
> +END(__aeabi_uidivmod)
> +#endif
> +END(__udivsi3)
> +
> +#ifdef __ARM_EABI__
> +ENTRY_NP(__aeabi_idiv)
> +ENTRY_NP(__aeabi_idivmod)
> +#endif
> +ENTRY_NP(__divsi3)
> +.L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
> +	eor     r0, r1, r0
> +	eor     r1, r0, r1
> +	eor     r0, r1, r0
> +					/* r0 = r1 / r0; r1 = r1 % r0 */
> +	cmp	r0, #1
> +	bcc	.L_overflow
> +	beq	.L_divide_l0
> +	ands	ip, r0, #0x80000000
> +	rsbmi	r0, r0, #0
> +	ands	r2, r1, #0x80000000
> +	eor	ip, ip, r2
> +	rsbmi	r1, r1, #0
> +	orr	ip, r2, ip, lsr #1	/* ip bit 0x40000000 = -ve division */
> +					/* ip bit 0x80000000 = -ve remainder */
> +
> +.L_divide_l1:
> +	mov	r2, #1
> +	mov	r3, #0
> +
> +	/*
> +	 * If the highest bit of the dividend is set, we have to be
> +	 * careful when shifting the divisor. Test this.
> +	 */
> +	movs	r1,r1
> +	bpl	.L_old_code
> +
> +	/*
> +	 * At this point, the highest bit of r1 is known to be set.
> +	 * We abuse this below in the tst instructions.
> +	 */
> +	tst	r1, r0 /*, lsl #0 */
> +	bmi	.L_divide_b1
> +	tst	r1, r0, lsl #1
> +	bmi	.L_divide_b2
> +	tst	r1, r0, lsl #2
> +	bmi	.L_divide_b3
> +	tst	r1, r0, lsl #3
> +	bmi	.L_divide_b4
> +	tst	r1, r0, lsl #4
> +	bmi	.L_divide_b5
> +	tst	r1, r0, lsl #5
> +	bmi	.L_divide_b6
> +	tst	r1, r0, lsl #6
> +	bmi	.L_divide_b7
> +	tst	r1, r0, lsl #7
> +	bmi	.L_divide_b8
> +	tst	r1, r0, lsl #8
> +	bmi	.L_divide_b9
> +	tst	r1, r0, lsl #9
> +	bmi	.L_divide_b10
> +	tst	r1, r0, lsl #10
> +	bmi	.L_divide_b11
> +	tst	r1, r0, lsl #11
> +	bmi	.L_divide_b12
> +	tst	r1, r0, lsl #12
> +	bmi	.L_divide_b13
> +	tst	r1, r0, lsl #13
> +	bmi	.L_divide_b14
> +	tst	r1, r0, lsl #14
> +	bmi	.L_divide_b15
> +	tst	r1, r0, lsl #15
> +	bmi	.L_divide_b16
> +	tst	r1, r0, lsl #16
> +	bmi	.L_divide_b17
> +	tst	r1, r0, lsl #17
> +	bmi	.L_divide_b18
> +	tst	r1, r0, lsl #18
> +	bmi	.L_divide_b19
> +	tst	r1, r0, lsl #19
> +	bmi	.L_divide_b20
> +	tst	r1, r0, lsl #20
> +	bmi	.L_divide_b21
> +	tst	r1, r0, lsl #21
> +	bmi	.L_divide_b22
> +	tst	r1, r0, lsl #22
> +	bmi	.L_divide_b23
> +	tst	r1, r0, lsl #23
> +	bmi	.L_divide_b24
> +	tst	r1, r0, lsl #24
> +	bmi	.L_divide_b25
> +	tst	r1, r0, lsl #25
> +	bmi	.L_divide_b26
> +	tst	r1, r0, lsl #26
> +	bmi	.L_divide_b27
> +	tst	r1, r0, lsl #27
> +	bmi	.L_divide_b28
> +	tst	r1, r0, lsl #28
> +	bmi	.L_divide_b29
> +	tst	r1, r0, lsl #29
> +	bmi	.L_divide_b30
> +	tst	r1, r0, lsl #30
> +	bmi	.L_divide_b31
> +/*
> + * instead of:
> + *	tst	r1, r0, lsl #31
> + *	bmi	.L_divide_b32
> + */
> +	b	.L_divide_b32
> +
> +.L_old_code:
> +	cmp	r1, r0
> +	bcc	.L_divide_b0
> +	cmp	r1, r0, lsl #1
> +	bcc	.L_divide_b1
> +	cmp	r1, r0, lsl #2
> +	bcc	.L_divide_b2
> +	cmp	r1, r0, lsl #3
> +	bcc	.L_divide_b3
> +	cmp	r1, r0, lsl #4
> +	bcc	.L_divide_b4
> +	cmp	r1, r0, lsl #5
> +	bcc	.L_divide_b5
> +	cmp	r1, r0, lsl #6
> +	bcc	.L_divide_b6
> +	cmp	r1, r0, lsl #7
> +	bcc	.L_divide_b7
> +	cmp	r1, r0, lsl #8
> +	bcc	.L_divide_b8
> +	cmp	r1, r0, lsl #9
> +	bcc	.L_divide_b9
> +	cmp	r1, r0, lsl #10
> +	bcc	.L_divide_b10
> +	cmp	r1, r0, lsl #11
> +	bcc	.L_divide_b11
> +	cmp	r1, r0, lsl #12
> +	bcc	.L_divide_b12
> +	cmp	r1, r0, lsl #13
> +	bcc	.L_divide_b13
> +	cmp	r1, r0, lsl #14
> +	bcc	.L_divide_b14
> +	cmp	r1, r0, lsl #15
> +	bcc	.L_divide_b15
> +	cmp	r1, r0, lsl #16
> +	bcc	.L_divide_b16
> +	cmp	r1, r0, lsl #17
> +	bcc	.L_divide_b17
> +	cmp	r1, r0, lsl #18
> +	bcc	.L_divide_b18
> +	cmp	r1, r0, lsl #19
> +	bcc	.L_divide_b19
> +	cmp	r1, r0, lsl #20
> +	bcc	.L_divide_b20
> +	cmp	r1, r0, lsl #21
> +	bcc	.L_divide_b21
> +	cmp	r1, r0, lsl #22
> +	bcc	.L_divide_b22
> +	cmp	r1, r0, lsl #23
> +	bcc	.L_divide_b23
> +	cmp	r1, r0, lsl #24
> +	bcc	.L_divide_b24
> +	cmp	r1, r0, lsl #25
> +	bcc	.L_divide_b25
> +	cmp	r1, r0, lsl #26
> +	bcc	.L_divide_b26
> +	cmp	r1, r0, lsl #27
> +	bcc	.L_divide_b27
> +	cmp	r1, r0, lsl #28
> +	bcc	.L_divide_b28
> +	cmp	r1, r0, lsl #29
> +	bcc	.L_divide_b29
> +	cmp	r1, r0, lsl #30
> +	bcc	.L_divide_b30
> +.L_divide_b32:
> +	cmp	r1, r0, lsl #31
> +	subhs	r1, r1,r0, lsl #31
> +	addhs	r3, r3,r2, lsl #31
> +.L_divide_b31:
> +	cmp	r1, r0, lsl #30
> +	subhs	r1, r1,r0, lsl #30
> +	addhs	r3, r3,r2, lsl #30
> +.L_divide_b30:
> +	cmp	r1, r0, lsl #29
> +	subhs	r1, r1,r0, lsl #29
> +	addhs	r3, r3,r2, lsl #29
> +.L_divide_b29:
> +	cmp	r1, r0, lsl #28
> +	subhs	r1, r1,r0, lsl #28
> +	addhs	r3, r3,r2, lsl #28
> +.L_divide_b28:
> +	cmp	r1, r0, lsl #27
> +	subhs	r1, r1,r0, lsl #27
> +	addhs	r3, r3,r2, lsl #27
> +.L_divide_b27:
> +	cmp	r1, r0, lsl #26
> +	subhs	r1, r1,r0, lsl #26
> +	addhs	r3, r3,r2, lsl #26
> +.L_divide_b26:
> +	cmp	r1, r0, lsl #25
> +	subhs	r1, r1,r0, lsl #25
> +	addhs	r3, r3,r2, lsl #25
> +.L_divide_b25:
> +	cmp	r1, r0, lsl #24
> +	subhs	r1, r1,r0, lsl #24
> +	addhs	r3, r3,r2, lsl #24
> +.L_divide_b24:
> +	cmp	r1, r0, lsl #23
> +	subhs	r1, r1,r0, lsl #23
> +	addhs	r3, r3,r2, lsl #23
> +.L_divide_b23:
> +	cmp	r1, r0, lsl #22
> +	subhs	r1, r1,r0, lsl #22
> +	addhs	r3, r3,r2, lsl #22
> +.L_divide_b22:
> +	cmp	r1, r0, lsl #21
> +	subhs	r1, r1,r0, lsl #21
> +	addhs	r3, r3,r2, lsl #21
> +.L_divide_b21:
> +	cmp	r1, r0, lsl #20
> +	subhs	r1, r1,r0, lsl #20
> +	addhs	r3, r3,r2, lsl #20
> +.L_divide_b20:
> +	cmp	r1, r0, lsl #19
> +	subhs	r1, r1,r0, lsl #19
> +	addhs	r3, r3,r2, lsl #19
> +.L_divide_b19:
> +	cmp	r1, r0, lsl #18
> +	subhs	r1, r1,r0, lsl #18
> +	addhs	r3, r3,r2, lsl #18
> +.L_divide_b18:
> +	cmp	r1, r0, lsl #17
> +	subhs	r1, r1,r0, lsl #17
> +	addhs	r3, r3,r2, lsl #17
> +.L_divide_b17:
> +	cmp	r1, r0, lsl #16
> +	subhs	r1, r1,r0, lsl #16
> +	addhs	r3, r3,r2, lsl #16
> +.L_divide_b16:
> +	cmp	r1, r0, lsl #15
> +	subhs	r1, r1,r0, lsl #15
> +	addhs	r3, r3,r2, lsl #15
> +.L_divide_b15:
> +	cmp	r1, r0, lsl #14
> +	subhs	r1, r1,r0, lsl #14
> +	addhs	r3, r3,r2, lsl #14
> +.L_divide_b14:
> +	cmp	r1, r0, lsl #13
> +	subhs	r1, r1,r0, lsl #13
> +	addhs	r3, r3,r2, lsl #13
> +.L_divide_b13:
> +	cmp	r1, r0, lsl #12
> +	subhs	r1, r1,r0, lsl #12
> +	addhs	r3, r3,r2, lsl #12
> +.L_divide_b12:
> +	cmp	r1, r0, lsl #11
> +	subhs	r1, r1,r0, lsl #11
> +	addhs	r3, r3,r2, lsl #11
> +.L_divide_b11:
> +	cmp	r1, r0, lsl #10
> +	subhs	r1, r1,r0, lsl #10
> +	addhs	r3, r3,r2, lsl #10
> +.L_divide_b10:
> +	cmp	r1, r0, lsl #9
> +	subhs	r1, r1,r0, lsl #9
> +	addhs	r3, r3,r2, lsl #9
> +.L_divide_b9:
> +	cmp	r1, r0, lsl #8
> +	subhs	r1, r1,r0, lsl #8
> +	addhs	r3, r3,r2, lsl #8
> +.L_divide_b8:
> +	cmp	r1, r0, lsl #7
> +	subhs	r1, r1,r0, lsl #7
> +	addhs	r3, r3,r2, lsl #7
> +.L_divide_b7:
> +	cmp	r1, r0, lsl #6
> +	subhs	r1, r1,r0, lsl #6
> +	addhs	r3, r3,r2, lsl #6
> +.L_divide_b6:
> +	cmp	r1, r0, lsl #5
> +	subhs	r1, r1,r0, lsl #5
> +	addhs	r3, r3,r2, lsl #5
> +.L_divide_b5:
> +	cmp	r1, r0, lsl #4
> +	subhs	r1, r1,r0, lsl #4
> +	addhs	r3, r3,r2, lsl #4
> +.L_divide_b4:
> +	cmp	r1, r0, lsl #3
> +	subhs	r1, r1,r0, lsl #3
> +	addhs	r3, r3,r2, lsl #3
> +.L_divide_b3:
> +	cmp	r1, r0, lsl #2
> +	subhs	r1, r1,r0, lsl #2
> +	addhs	r3, r3,r2, lsl #2
> +.L_divide_b2:
> +	cmp	r1, r0, lsl #1
> +	subhs	r1, r1,r0, lsl #1
> +	addhs	r3, r3,r2, lsl #1
> +.L_divide_b1:
> +	cmp	r1, r0
> +	subhs	r1, r1, r0
> +	addhs	r3, r3, r2
> +.L_divide_b0:
> +
> +	tst	ip, #0x20000000
> +	bne	.L_udivide_l1
> +	mov	r0, r3
> +	cmp	ip, #0
> +	rsbmi	r1, r1, #0
> +	movs	ip, ip, lsl #1
> +	bicmi	r0, r0, #0x80000000	/* Fix incase we divided 0x80000000 */
> +	rsbmi	r0, r0, #0
> +	mov	pc, lr
> +
> +.L_udivide_l1:
> +	tst	ip, #0x10000000
> +	mov	r1, r1, lsl #1
> +	orrne	r1, r1, #1
> +	mov	r3, r3, lsl #1
> +	cmp	r1, r0
> +	subhs	r1, r1, r0
> +	addhs	r3, r3, r2
> +	mov	r0, r3
> +	mov	pc, lr
> +END(__aeabi_idiv)
> +END(__aeabi_idivmod)
> +END(__divsi3)
> +
> diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
> new file mode 100644
> index 0000000..6e579e7
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/events.c
> @@ -0,0 +1,24 @@
> +#include <mini-os/os.h>
> +#include <mini-os/events.h>
> +#include <mini-os/hypervisor.h>
> +
> +static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
> +{
> +	printk("Received a virq_debug event\n");
> +}
> +
> +evtchn_port_t debug_port = -1;
> +void arch_init_events(void) {
> +	debug_port = bind_virq(VIRQ_DEBUG, (evtchn_handler_t)virq_debug, 0);
> +	if(debug_port == -1)
> +		BUG();
> +	unmask_evtchn(debug_port);
> +}
> +
> +void arch_fini_events(void) {
> +	if(debug_port != -1)
> +	{
> +		mask_evtchn(debug_port);
> +		unbind_evtchn(debug_port);
> +	}
> +}
> diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
> new file mode 100644
> index 0000000..e2f21c4
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/hypercalls32.S
> @@ -0,0 +1,88 @@
> +#define __HYPERVISOR_set_trap_table        0
> +#define __HYPERVISOR_mmu_update            1
> +#define __HYPERVISOR_set_gdt               2
> +#define __HYPERVISOR_stack_switch          3
> +#define __HYPERVISOR_set_callbacks         4
> +#define __HYPERVISOR_fpu_taskswitch        5
> +#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
> +#define __HYPERVISOR_platform_op           7
> +#define __HYPERVISOR_set_debugreg          8
> +#define __HYPERVISOR_get_debugreg          9
> +#define __HYPERVISOR_update_descriptor    10
> +#define __HYPERVISOR_memory_op            12
> +#define __HYPERVISOR_multicall            13
> +#define __HYPERVISOR_update_va_mapping    14
> +#define __HYPERVISOR_set_timer_op         15
> +#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
> +#define __HYPERVISOR_xen_version          17
> +#define __HYPERVISOR_console_io           18
> +#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
> +#define __HYPERVISOR_grant_table_op       20
> +#define __HYPERVISOR_vm_assist            21
> +#define __HYPERVISOR_update_va_mapping_otherdomain 22
> +#define __HYPERVISOR_iret                 23 /* x86 only */
> +#define __HYPERVISOR_vcpu_op              24
> +#define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
> +#define __HYPERVISOR_mmuext_op            26
> +#define __HYPERVISOR_xsm_op               27
> +#define __HYPERVISOR_nmi_op               28
> +#define __HYPERVISOR_sched_op             29
> +#define __HYPERVISOR_callback_op          30
> +#define __HYPERVISOR_xenoprof_op          31
> +#define __HYPERVISOR_event_channel_op     32
> +#define __HYPERVISOR_physdev_op           33
> +#define __HYPERVISOR_hvm_op               34
> +#define __HYPERVISOR_sysctl               35
> +#define __HYPERVISOR_domctl               36
> +#define __HYPERVISOR_kexec_op             37
> +#define __HYPERVISOR_tmem_op              38
> +#define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
> +
> +
> +
> +#define __HVC(imm16) .long ((0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F)) & 0xFFFFFFFF)
> +
> +#define XEN_IMM 0xEA1
> +
> +#define HYPERCALL_SIMPLE(hypercall)		\
> +.globl HYPERVISOR_##hypercall;			\
> +.align 4,0x90;					\
> +HYPERVISOR_##hypercall:				\
> +        mov r12, #__HYPERVISOR_##hypercall;	\
> +        __HVC(XEN_IMM);				\
> +        mov pc, lr;
> +
> +#define _hypercall0 HYPERCALL_SIMPLE
> +#define _hypercall1 HYPERCALL_SIMPLE
> +#define _hypercall2 HYPERCALL_SIMPLE
> +#define _hypercall3 HYPERCALL_SIMPLE
> +#define _hypercall4 HYPERCALL_SIMPLE
> +
> +_hypercall1(set_trap_table);
> +_hypercall4(mmu_update);
> +_hypercall4(mmuext_op);
> +_hypercall2(set_gdt);
> +_hypercall2(stack_switch);
> +_hypercall3(set_callbacks);
> +_hypercall1(fpu_taskswitch);
> +_hypercall2(sched_op);
> +_hypercall1(set_timer_op);
> +_hypercall2(set_debugreg);
> +_hypercall1(get_debugreg);
> +_hypercall2(update_descriptor);
> +_hypercall2(memory_op);
> +_hypercall2(multicall);
> +_hypercall3(update_va_mapping);
> +_hypercall2(event_channel_op);
> +_hypercall2(xen_version);
> +_hypercall3(console_io);
> +_hypercall1(physdev_op);
> +_hypercall3(grant_table_op);
> +_hypercall4(update_va_mapping_otherdomain);
> +_hypercall2(vm_assist);
> +_hypercall3(vcpu_op);
> +_hypercall2(set_segment_base);
> +_hypercall2(nmi_op);
> +_hypercall1(sysctl);
> +_hypercall1(domctl);
> +_hypercall2(hvm_op);
> diff --git a/extras/mini-os/arch/arm/ldivmod.S b/extras/mini-os/arch/arm/ldivmod.S
> new file mode 100644
> index 0000000..7529826
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/ldivmod.S
> @@ -0,0 +1,67 @@
> +/*
> + * Copyright (C) 2012 Andrew Turner
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + */
> +
> +#define ENTRY_NP(symbol) \
> +	.globl symbol;	\
> +	symbol:
> +
> +#define END(symbol)
> +
> +/*
> + * These calculate:
> + * q = n / m
> + * With a remainer r.
> + *
> + * They take n in {r0, r1} and m in {r2, r3} then pass them into the
> + * helper function. The hepler functions return q in {r0, r1} as
> + * required by the API spec however r is returned on the stack. The
> + * ABI required us to return r in {r2, r3}.
> + *
> + * We need to allocate 8 bytes on the stack to store r, the link
> + * register, and a pointer to the space where the helper function
> + * will write r to. After returning from the helper fuinction we load
> + * the old link register and r from the stack and return.
> + */
> +ENTRY_NP(__aeabi_ldivmod)
> +	sub	sp, sp, #8	/* Space for the remainder */
> +	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
> +	bl	__kern_ldivmod
> +	ldr	lr, [sp, #4]	/* Restore lr */
> +	add	sp, sp, #8	/* Move sp to the remainder value */
> +	ldmfd	sp!, {r2, r3}	/* Load the remainder */
> +	mov	pc, lr
> +END(__aeabi_ldivmod)
> +
> +ENTRY_NP(__aeabi_uldivmod)
> +	sub	sp, sp, #8	/* Space for the remainder */
> +	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
> +	bl	__qdivrem
> +	ldr	lr, [sp, #4]	/* Restore lr */
> +	add	sp, sp, #8	/* Move sp to the remainder value */
> +	ldmfd	sp!, {r2, r3}	/* Load the remainder */
> +	mov	pc, lr
> +END(__aeabi_uldivmod)
> diff --git a/extras/mini-os/arch/arm/ldivmod_helper.c b/extras/mini-os/arch/arm/ldivmod_helper.c
> new file mode 100644
> index 0000000..f4dde48
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/ldivmod_helper.c
> @@ -0,0 +1,66 @@
> +/*
> + * Copyright (C) 2012 Andrew Turner
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + */
> +
> +#include <mini-os/types.h>
> +
> +u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
> +
> +quad_t
> +__divdi3(quad_t a, quad_t b)
> +{
> +        u_quad_t ua, ub, uq;
> +        int neg;
> +
> +        if (a < 0)
> +                ua = -(u_quad_t)a, neg = 1;
> +        else
> +                ua = a, neg = 0;
> +        if (b < 0)
> +                ub = -(u_quad_t)b, neg ^= 1;
> +        else
> +                ub = b;
> +        uq = __qdivrem(ua, ub, (u_quad_t *)0);
> +        return (neg ? -uq : uq);
> +}
> +
> +/*
> + * Helper for __aeabi_ldivmod.
> + * TODO: __divdi3 calls __qdivrem. We should do the same and use the
> + * remainder value rather than re-calculating it.
> + */
> +long long __kern_ldivmod(long long, long long, long long *);
> +
> +long long
> +__kern_ldivmod(long long n, long long m, long long *rem)
> +{
> +	long long q;
> +
> +	q = __divdi3(n, m);	/* q = n / m */
> +	*rem = n - m * q;
> +
> +	return q;
> +}
> diff --git a/extras/mini-os/arch/arm/minios-arm32.lds b/extras/mini-os/arch/arm/minios-arm32.lds
> new file mode 100755
> index 0000000..793f0de
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/minios-arm32.lds
> @@ -0,0 +1,73 @@
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> +  . = 0x80008000;
> +  _text = .;			/* Text and read-only data */
> +  .text : {
> +	*(.text)
> +	*(.gnu.warning)
> +	} = 0x9090
> +
> +  _etext = .;			/* End of text section */
> +
> +  .rodata : { *(.rodata) *(.rodata.*) }
> +  . = ALIGN(4096);
> +  _erodata = .;
> +
> +  /* newlib initialization functions */
> +  . = ALIGN(32 / 8);
> +  PROVIDE (__preinit_array_start = .);
> +  .preinit_array     : { *(.preinit_array) }
> +  PROVIDE (__preinit_array_end = .);
> +  PROVIDE (__init_array_start = .);
> +  .init_array     : { *(.init_array) }
> +  PROVIDE (__init_array_end = .);
> +  PROVIDE (__fini_array_start = .);
> +  .fini_array     : { *(.fini_array) }
> +  PROVIDE (__fini_array_end = .);
> +
> +  .ctors : {
> +        __CTOR_LIST__ = .;
> +        *(.ctors)
> +	CONSTRUCTORS
> +        LONG(0)
> +        __CTOR_END__ = .;
> +        }
> +
> +  .dtors : {
> +        __DTOR_LIST__ = .;
> +        *(.dtors)
> +        LONG(0)
> +        __DTOR_END__ = .;
> +        }
> +
> +  .data : {			/* Data */
> +	*(.data)
> +	}
> +
> +  _edata = .;			/* End of data section */
> +
> +  __bss_start = .;		/* BSS */
> +  .bss : {
> +	*(.bss)
> +        *(.app.bss)
> +	}
> +  _end = . ;
> +
> +  /* Sections to be discarded */
> +  /DISCARD/ : {
> +	*(.text.exit)
> +	*(.data.exit)
> +	*(.exitcall.exit)
> +	}
> +
> +  /* Stabs debugging sections.  */
> +  .stab 0 : { *(.stab) }
> +  .stabstr 0 : { *(.stabstr) }
> +  .stab.excl 0 : { *(.stab.excl) }
> +  .stab.exclstr 0 : { *(.stab.exclstr) }
> +  .stab.index 0 : { *(.stab.index) }
> +  .stab.indexstr 0 : { *(.stab.indexstr) }
> +  .comment 0 : { *(.comment) }
> +}
> diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
> new file mode 100644
> index 0000000..7e7ff06
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/mm.c
> @@ -0,0 +1,44 @@
> +#include <console.h>
> +#include <arm/arch_mm.h>
> +
> +#define PHYS_START (0x80008000 + (1000 * 4 * 1024))
> +#define PHYS_SIZE (40*1024*1024)
> +
> +static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
> +{
> +	// FIXME Create small pages descriptors here instead of the 1M superpages created earlier.
> +	return;
> +}
> +
> +unsigned long allocate_ondemand(unsigned long n, unsigned long alignment)
> +{
> +	// FIXME
> +	BUG();
> +}
> +
> +void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
> +{
> +	printk("    _text: %p(VA)\n", &_text);
> +	printk("    _etext: %p(VA)\n", &_etext);
> +	printk("    _erodata: %p(VA)\n", &_erodata);
> +	printk("    _edata: %p(VA)\n", &_edata);
> +	printk("    stack start: %p(VA)\n", stack);
> +	printk("    _end: %p(VA)\n", &_end);
> +
> +	// FIXME Get from dt!
> +	*start_pfn_p = (((unsigned long)&_end) >> PAGE_SHIFT) + 1000;
> +	*max_pfn_p = ((unsigned long)&_end + PHYS_SIZE) >> PAGE_SHIFT;
> +
> +	printk("    start_pfn: %lx\n", *start_pfn_p);
> +	printk("    max_pfn: %lx\n", *max_pfn_p);
> +
> +	build_pagetable(start_pfn_p, max_pfn_p);
> +}
> +
> +void arch_init_p2m(unsigned long max_pfn)
> +{
> +}
> +
> +void arch_init_demand_mapping_area(unsigned long cur_pfn)
> +{
> +}
> diff --git a/extras/mini-os/arch/arm/qdivrem.c b/extras/mini-os/arch/arm/qdivrem.c
> new file mode 100644
> index 0000000..0ab5733
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/qdivrem.c
> @@ -0,0 +1,270 @@
> +/*-
> + * Copyright (c) 1992, 1993
> + *	The Regents of the University of California.  All rights reserved.
> + *
> + * This software was developed by the Computer Systems Engineering group
> + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
> + * contributed to Berkeley.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 4. Neither the name of the University nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <mini-os/types.h>
> +
> +/*
> + * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
> + * section 4.3.1, pp. 257--259.
> + */
> +
> +#define	B	(1 << HALF_BITS)	/* digit base */
> +
> +/* Combine two `digits' to make a single two-digit number. */
> +#define	COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
> +
> +/* select a type for digits in base B: use unsigned short if they fit */
> +#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
> +typedef unsigned short digit;
> +#else
> +typedef u_long digit;
> +#endif
> +
> +/*
> + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
> + * `fall out' the left (there never will be any such anyway).
> + * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
> + */
> +static void
> +__shl(register digit *p, register int len, register int sh)
> +{
> +	register int i;
> +
> +	for (i = 0; i < len; i++)
> +		p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
> +	p[i] = LHALF(p[i] << sh);
> +}
> +
> +/*
> + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
> + *
> + * We do this in base 2-sup-HALF_BITS, so that all intermediate products
> + * fit within u_long.  As a consequence, the maximum length dividend and
> + * divisor are 4 `digits' in this base (they are shorter if they have
> + * leading zeros).
> + */
> +u_quad_t
> +__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
> +{
> +	union uu tmp;
> +	digit *u, *v, *q;
> +	register digit v1, v2;
> +	u_long qhat, rhat, t;
> +	int m, n, d, j, i;
> +	digit uspace[5], vspace[5], qspace[5];
> +
> +	/*
> +	 * Take care of special cases: divide by zero, and u < v.
> +	 */
> +	if (vq == 0) {
> +		/* divide by zero. */
> +		static volatile const unsigned int zero = 0;
> +
> +		tmp.ul[H] = tmp.ul[L] = 1 / zero;
> +		if (arq)
> +			*arq = uq;
> +		return (tmp.q);
> +	}
> +	if (uq < vq) {
> +		if (arq)
> +			*arq = uq;
> +		return (0);
> +	}
> +	u = &uspace[0];
> +	v = &vspace[0];
> +	q = &qspace[0];
> +
> +	/*
> +	 * Break dividend and divisor into digits in base B, then
> +	 * count leading zeros to determine m and n.  When done, we
> +	 * will have:
> +	 *	u = (u[1]u[2]...u[m+n]) sub B
> +	 *	v = (v[1]v[2]...v[n]) sub B
> +	 *	v[1] != 0
> +	 *	1 < n <= 4 (if n = 1, we use a different division algorithm)
> +	 *	m >= 0 (otherwise u < v, which we already checked)
> +	 *	m + n = 4
> +	 * and thus
> +	 *	m = 4 - n <= 2
> +	 */
> +	tmp.uq = uq;
> +	u[0] = 0;
> +	u[1] = HHALF(tmp.ul[H]);
> +	u[2] = LHALF(tmp.ul[H]);
> +	u[3] = HHALF(tmp.ul[L]);
> +	u[4] = LHALF(tmp.ul[L]);
> +	tmp.uq = vq;
> +	v[1] = HHALF(tmp.ul[H]);
> +	v[2] = LHALF(tmp.ul[H]);
> +	v[3] = HHALF(tmp.ul[L]);
> +	v[4] = LHALF(tmp.ul[L]);
> +	for (n = 4; v[1] == 0; v++) {
> +		if (--n == 1) {
> +			u_long rbj;	/* r*B+u[j] (not root boy jim) */
> +			digit q1, q2, q3, q4;
> +
> +			/*
> +			 * Change of plan, per exercise 16.
> +			 *	r = 0;
> +			 *	for j = 1..4:
> +			 *		q[j] = floor((r*B + u[j]) / v),
> +			 *		r = (r*B + u[j]) % v;
> +			 * We unroll this completely here.
> +			 */
> +			t = v[2];	/* nonzero, by definition */
> +			q1 = u[1] / t;
> +			rbj = COMBINE(u[1] % t, u[2]);
> +			q2 = rbj / t;
> +			rbj = COMBINE(rbj % t, u[3]);
> +			q3 = rbj / t;
> +			rbj = COMBINE(rbj % t, u[4]);
> +			q4 = rbj / t;
> +			if (arq)
> +				*arq = rbj % t;
> +			tmp.ul[H] = COMBINE(q1, q2);
> +			tmp.ul[L] = COMBINE(q3, q4);
> +			return (tmp.q);
> +		}
> +	}
> +
> +	/*
> +	 * By adjusting q once we determine m, we can guarantee that
> +	 * there is a complete four-digit quotient at &qspace[1] when
> +	 * we finally stop.
> +	 */
> +	for (m = 4 - n; u[1] == 0; u++)
> +		m--;
> +	for (i = 4 - m; --i >= 0;)
> +		q[i] = 0;
> +	q += 4 - m;
> +
> +	/*
> +	 * Here we run Program D, translated from MIX to C and acquiring
> +	 * a few minor changes.
> +	 *
> +	 * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
> +	 */
> +	d = 0;
> +	for (t = v[1]; t < B / 2; t <<= 1)
> +		d++;
> +	if (d > 0) {
> +		__shl(&u[0], m + n, d);		/* u <<= d */
> +		__shl(&v[1], n - 1, d);		/* v <<= d */
> +	}
> +	/*
> +	 * D2: j = 0.
> +	 */
> +	j = 0;
> +	v1 = v[1];	/* for D3 -- note that v[1..n] are constant */
> +	v2 = v[2];	/* for D3 */
> +	do {
> +		register digit uj0, uj1, uj2;
> +
> +		/*
> +		 * D3: Calculate qhat (\^q, in TeX notation).
> +		 * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
> +		 * let rhat = (u[j]*B + u[j+1]) mod v[1].
> +		 * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
> +		 * decrement qhat and increase rhat correspondingly.
> +		 * Note that if rhat >= B, v[2]*qhat < rhat*B.
> +		 */
> +		uj0 = u[j + 0];	/* for D3 only -- note that u[j+...] change */
> +		uj1 = u[j + 1];	/* for D3 only */
> +		uj2 = u[j + 2];	/* for D3 only */
> +		if (uj0 == v1) {
> +			qhat = B;
> +			rhat = uj1;
> +			goto qhat_too_big;
> +		} else {
> +			u_long nn = COMBINE(uj0, uj1);
> +			qhat = nn / v1;
> +			rhat = nn % v1;
> +		}
> +		while (v2 * qhat > COMBINE(rhat, uj2)) {
> +	qhat_too_big:
> +			qhat--;
> +			if ((rhat += v1) >= B)
> +				break;
> +		}
> +		/*
> +		 * D4: Multiply and subtract.
> +		 * The variable `t' holds any borrows across the loop.
> +		 * We split this up so that we do not require v[0] = 0,
> +		 * and to eliminate a final special case.
> +		 */
> +		for (t = 0, i = n; i > 0; i--) {
> +			t = u[i + j] - v[i] * qhat - t;
> +			u[i + j] = LHALF(t);
> +			t = (B - HHALF(t)) & (B - 1);
> +		}
> +		t = u[j] - t;
> +		u[j] = LHALF(t);
> +		/*
> +		 * D5: test remainder.
> +		 * There is a borrow if and only if HHALF(t) is nonzero;
> +		 * in that (rare) case, qhat was too large (by exactly 1).
> +		 * Fix it by adding v[1..n] to u[j..j+n].
> +		 */
> +		if (HHALF(t)) {
> +			qhat--;
> +			for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
> +				t += u[i + j] + v[i];
> +				u[i + j] = LHALF(t);
> +				t = HHALF(t);
> +			}
> +			u[j] = LHALF(u[j] + t);
> +		}
> +		q[j] = qhat;
> +	} while (++j <= m);		/* D7: loop on j. */
> +
> +	/*
> +	 * If caller wants the remainder, we have to calculate it as
> +	 * u[m..m+n] >> d (this is at most n digits and thus fits in
> +	 * u[m+1..m+n], but we may need more source digits).
> +	 */
> +	if (arq) {
> +		if (d) {
> +			for (i = m + n; i > m; --i)
> +				u[i] = (u[i] >> d) |
> +				    LHALF(u[i - 1] << (HALF_BITS - d));
> +			u[i] = 0;
> +		}
> +		tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
> +		tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
> +		*arq = tmp.q;
> +	}
> +
> +	tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
> +	tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
> +	return (tmp.q);
> +}
> diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c
> new file mode 100644
> index 0000000..e490105
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/sched.c
> @@ -0,0 +1,32 @@
> +#include <mini-os/sched.h>
> +#include <mini-os/xmalloc.h>
> +
> +
> +/* Architecture specific setup of thread creation */
> +struct thread* arch_create_thread(char *name, void (*function)(void *),
> +                                  void *data)
> +{
> +    struct thread *thread;
> +
> +    thread = xmalloc(struct thread);
> +    /* We can't use lazy allocation here since the trap handler runs on the stack */
> +    thread->stack = (char *)alloc_pages(STACK_SIZE_PAGE_ORDER);
> +    thread->name = name;
> +    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread,
> +            thread->stack);
> +
> +    thread->sp = (unsigned long)thread->stack + STACK_SIZE;
> +    /* Save pointer to the thread on the stack, used by current macro */
> +    *((unsigned long *)thread->stack) = (unsigned long)thread;
> +
> +    thread->ip = (unsigned long) function;
> +    /* FIXME thread->r0 = (unsigned long)data; */
> +
> +    return thread;
> +}
> +
> +void run_idle_thread(void)
> +{
> +	__asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), "r"(idle_thread->ip));
> +	/* Never arrive here! */
> +}
> diff --git a/extras/mini-os/arch/arm/setup.c b/extras/mini-os/arch/arm/setup.c
> new file mode 100644
> index 0000000..f0b2f47
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/setup.c
> @@ -0,0 +1,55 @@
> +#include <mini-os/os.h>
> +#include <xen/xen.h>
> +#include <xen/memory.h>
> +#include <hypervisor.h>
> +#include <arm/arch_mm.h>
> +
> +/*
> + * This structure contains start-of-day info, such as pagetable base pointer,
> + * address of the shared_info structure, and things like that.
> + */
> +union start_info_union start_info_union;
> +
> +/*
> + * Shared page for communicating with the hypervisor.
> + * Events flags go here, for example.
> + */
> +shared_info_t *HYPERVISOR_shared_info;
> +
> +extern char shared_info_page[PAGE_SIZE];
> +
> +void start_kernel(void);
> +
> +/*
> + * INITIAL C ENTRY POINT.
> + */
> +void arch_init(void *dtb_pointer)
> +{
> +    struct xen_add_to_physmap xatp;
> +
> +    memset(&__bss_start, 0, &_end - &__bss_start);
> +
> +    printk("dtb_pointer : %x\n", dtb_pointer);
> +
> +    /* Map shared_info page */
> +	xatp.domid = DOMID_SELF;
> +	xatp.idx = 0;
> +	xatp.space = XENMAPSPACE_shared_info;
> +	xatp.gpfn = virt_to_pfn(shared_info_page);
> +	if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
> +		BUG();
> +	HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
> +
> +	start_kernel();
> +}
> +
> +void
> +arch_fini(void)
> +{
> +
> +}
> +
> +void
> +arch_do_exit(void)
> +{
> +}
> diff --git a/extras/mini-os/arch/arm/time.c b/extras/mini-os/arch/arm/time.c
> new file mode 100644
> index 0000000..6dba1fe
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/time.c
> @@ -0,0 +1,232 @@
> +#include <mini-os/os.h>
> +#include <mini-os/hypervisor.h>
> +#include <mini-os/events.h>
> +#include <mini-os/traps.h>
> +#include <mini-os/types.h>
> +#include <mini-os/time.h>
> +#include <mini-os/lib.h>
> +
> +//#define VTIMER_DEBUG
> +#ifdef VTIMER_DEBUG
> +#define DEBUG(_f, _a...) \
> +    printk("MINI_OS(file=vtimer.c, line=%d) " _f , __LINE__, ## _a)
> +#else
> +#define DEBUG(_f, _a...)    ((void)0)
> +#endif
> +
> +
> +/************************************************************************
> + * Time functions
> + *************************************************************************/
> +
> +/* These are peridically updated in shared_info, and then copied here. */
> +struct shadow_time_info {
> +	uint64_t tsc_timestamp;     /* TSC at last update of time vals.  */
> +	uint64_t system_timestamp;  /* Time, in nanosecs, since boot.    */
> +	uint32_t tsc_to_nsec_mul;
> +	uint32_t tsc_to_usec_mul;
> +	int tsc_shift;
> +	uint32_t version;
> +};
> +static struct timespec shadow_ts;
> +static uint32_t shadow_ts_version;
> +
> +static struct shadow_time_info shadow;
> +
> +#define HANDLE_USEC_OVERFLOW(_tv)          \
> +    do {                                   \
> +        while ( (_tv)->tv_usec >= 1000000 ) \
> +        {                                  \
> +            (_tv)->tv_usec -= 1000000;      \
> +            (_tv)->tv_sec++;                \
> +        }                                  \
> +    } while ( 0 )
> +
> +static inline int time_values_up_to_date(void)
> +{
> +	struct vcpu_time_info *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
> +
> +	return (shadow.version == src->version);
> +}
> +
> +
> +/*
> + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
> + * yielding a 64-bit result.
> + */
> +static inline uint64_t scale_delta(uint64_t delta, uint32_t mul_frac, int shift)
> +{
> +	BUG();
> +	return 0;
> +}
> +
> +
> +static unsigned long get_nsec_offset(void)
> +{
> +	return 0;
> +#if FIXME
> +	uint64_t now, delta;
> +	rdtscll(now);
> +	delta = now - shadow.tsc_timestamp;
> +	return scale_delta(delta, shadow.tsc_to_nsec_mul, shadow.tsc_shift);
> +#endif
> +}
> +
> +
> +static void get_time_values_from_xen(void)
> +{
> +	struct vcpu_time_info    *src = &HYPERVISOR_shared_info->vcpu_info[0].time;
> +
> + 	do {
> +		shadow.version = src->version;
> +		rmb();
> +		shadow.tsc_timestamp     = src->tsc_timestamp;
> +		shadow.system_timestamp  = src->system_time;
> +		shadow.tsc_to_nsec_mul   = src->tsc_to_system_mul;
> +		shadow.tsc_shift         = src->tsc_shift;
> +		rmb();
> +	}
> +	while ((src->version & 1) | (shadow.version ^ src->version));
> +
> +	shadow.tsc_to_usec_mul = shadow.tsc_to_nsec_mul / 1000;
> +}
> +
> +
> +
> +
> +/* monotonic_clock(): returns # of nanoseconds passed since time_init()
> + *		Note: This function is required to return accurate
> + *		time even in the absence of multiple timer ticks.
> + */
> +uint64_t monotonic_clock(void)
> +{
> +	uint64_t time;
> +	uint32_t local_time_version;
> +
> +	do {
> +		local_time_version = shadow.version;
> +		rmb();
> +		time = shadow.system_timestamp + get_nsec_offset();
> +        if (!time_values_up_to_date())
> +			get_time_values_from_xen();
> +		rmb();
> +	} while (local_time_version != shadow.version);
> +
> +	return time;
> +}
> +
> +static void update_wallclock(void)
> +{
> +	shared_info_t *s = HYPERVISOR_shared_info;
> +
> +	do {
> +		shadow_ts_version = s->wc_version;
> +		rmb();
> +		shadow_ts.tv_sec  = s->wc_sec;
> +		shadow_ts.tv_nsec = s->wc_nsec;
> +		rmb();
> +	}
> +	while ((s->wc_version & 1) | (shadow_ts_version ^ s->wc_version));
> +}
> +
> +
> +int gettimeofday(struct timeval *tv, void *tz)
> +{
> +    uint64_t nsec = monotonic_clock();
> +    nsec += shadow_ts.tv_nsec;
> +
> +
> +    tv->tv_sec = shadow_ts.tv_sec;
> +    tv->tv_sec += NSEC_TO_SEC(nsec);
> +    tv->tv_usec = NSEC_TO_USEC(nsec % 1000000000UL);
> +
> +    return 0;
> +}
> +
> +
> +void block_domain(s_time_t until)
> +{
> +    struct timeval tv;
> +    gettimeofday(&tv, NULL);
> +    ASSERT(irqs_disabled());
> +    if(monotonic_clock() < until)
> +    {
> +        HYPERVISOR_set_timer_op(until);
> +        HYPERVISOR_sched_op(SCHEDOP_block, 0);
> +        local_irq_disable();
> +    }
> +}
> +
> +
> +/*
> + * Just a dummy
> + */
> +void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign)
> +{
> +	DEBUG("Timer kick\n");
> +    get_time_values_from_xen();
> +	update_wallclock();
> +}
> +
> +#define VTIMER_TICK 0x10000000
> +void increment_vtimer_compare(uint64_t inc) {
> +	uint32_t x, y;
> +	uint64_t value;
> +	__asm__ __volatile__("mrrc p15, 1, %0, %1, c14\n"
> +			"isb":"=r"(x), "=r"(y));
> +
> +	// CompareValue = Counter + VTIMER_TICK
> +	value = (0xFFFFFFFFFFFFFFFFULL & x) | ((0xFFFFFFFFFFFFFFFFULL & y) << 32);
> +	DEBUG("Counter: %llx(x=%x and y=%x)\n", value, x, y);
> +	value += inc;
> +	DEBUG("New CompareValue : %llx\n", value);
> +	x = 0xFFFFFFFFULL & value;
> +	y = (value >> 32) & 0xFFFFFFFF;
> +
> +	__asm__ __volatile__("mcrr p15, 3, %0, %1, c14\n"
> +			"isb"::"r"(x), "r"(y));
> +
> +	__asm__ __volatile__("mov %0, #0x1\n"
> +				"mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
> +				"isb":"=r"(x));
> +}
> +
> +static inline void enable_virtual_timer(void) {
> +#if FIXME
> +	uint32_t x, y;
> +	uint64_t value;
> +
> +	__asm__ __volatile__("ldr %0, =0xffffffff\n"
> +			"ldr %1, =0xffffffff\n"
> +			"dsb\n"
> +			"mcrr p15, 3, %0, %1, c14\n" /* set CompareValue to 0x0000ffff 0000ffff */
> +			"isb\n"
> +			"mov %0, #0x1\n"
> +			"mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
> +			"isb":"=r"(x), "=r"(y));
> +#else
> +	increment_vtimer_compare(VTIMER_TICK);
> +#endif
> +}
> +
> +evtchn_port_t timer_port = -1;
> +void arch_init_time(void)
> +{
> +	// FIXME: VIRQ_TIMER isn't supported under ARM, use ARM Generic Timer instead.
> +    printk("Initialising timer interface\n");
> +    timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0);
> +    if(timer_port == -1)
> +		BUG();
> +    unmask_evtchn(timer_port);
> +
> +    enable_virtual_timer();
> +}
> +
> +void arch_fini_time(void)
> +{
> +	if(timer_port != -1)
> +	{
> +		mask_evtchn(timer_port);
> +		unbind_evtchn(timer_port);
> +	}
> +}
> diff --git a/extras/mini-os/arch/arm/xenbus.c b/extras/mini-os/arch/arm/xenbus.c
> new file mode 100644
> index 0000000..76feabc
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/xenbus.c
> @@ -0,0 +1,36 @@
> +#include <mini-os/os.h>
> +#include <mini-os/mm.h>
> +#include <xen/hvm/params.h>
> +#include <xen/io/xs_wire.h>
> +#include <mini-os/hypervisor.h>
> +
> +static inline int hvm_get_parameter(int idx, uint64_t *value)
> +{
> +	struct xen_hvm_param xhv;
> +	int ret;
> +
> +	xhv.domid = DOMID_SELF;
> +	xhv.index = idx;
> +	ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
> +	if (ret < 0) {
> +		BUG();
> +	}
> +	*value = xhv.value;
> +	return ret;
> +}
> +
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {
> +	uint64_t value;
> +	uint64_t xenstore_pfn;
> +
> +	if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
> +		BUG();
> +
> +	*store_evtchn = (int)value;
> +
> +	if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
> +		BUG();
> +	xenstore_pfn = (unsigned long)value;
> +
> +	*xenstore_buf = pfn_to_virt(xenstore_pfn);
> +}
> diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
> new file mode 100644
> index 0000000..87f8b77
> --- /dev/null
> +++ b/extras/mini-os/arch/x86/events.c
> @@ -0,0 +1,28 @@
> +#include <mini-os/os.h>
> +#include <mini-os/mm.h>
> +
> +#if defined(__x86_64__)
> +char irqstack[2 * STACK_SIZE];
> +
> +static struct pda
> +{
> +    int irqcount;       /* offset 0 (used in x86_64.S) */
> +    char *irqstackptr;  /*        8 */
> +} cpu0_pda;
> +#endif
> +
> +void arch_init_events(void) {
> +#if defined(__x86_64__)
> +    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
> +    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
> +    cpu0_pda.irqcount = -1;
> +    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
> +                                    & ~(STACK_SIZE - 1));
> +#endif
> +}
> +
> +void arch_fini_events(void) {
> +#if defined(__x86_64__)
> +    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
> +#endif
> +}
> diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
> index 54046d3..6bb6d4b 100644
> --- a/extras/mini-os/arch/x86/setup.c
> +++ b/extras/mini-os/arch/x86/setup.c
> @@ -28,6 +28,7 @@
>
>   #include <mini-os/os.h>
>   #include <mini-os/lib.h> /* for printk, memcpy */
> +#include <xen/xen.h>
>
>   /*
>    * Shared page for communicating with the hypervisor.
> @@ -87,14 +88,40 @@ static inline void sse_init(void) {
>   #define sse_init()
>   #endif
>
> +
> +void start_kernel(void);
> +
> +/*
> + * INITIAL C ENTRY POINT.
> + */
>   void
>   arch_init(start_info_t *si)
>   {
> +    static char hello[] = "Bootstrapping...\n";
> +
> +    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
> +
> +    trap_init();
> +
> +    /* print out some useful information  */
> +    printk("Xen Minimal OS!\n");
> +    printk("  start_info: %p(VA)\n", si);
> +    printk("    nr_pages: 0x%lx\n", si->nr_pages);
> +    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
> +    printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
> +    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
> +    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
> +    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
> +    printk("     mod_len: %lu\n", si->mod_len);
> +    printk("       flags: 0x%x\n", (unsigned int)si->flags);
> +    printk("    cmd_line: %s\n",
> +           si->cmd_line ? (const char *)si->cmd_line : "NULL");
> +
>   	/*Initialize floating point unit */
> -        fpu_init();
> +	fpu_init();
>
> -        /* Initialize SSE */
> -        sse_init();
> +	/* Initialize SSE */
> +	sse_init();
>
>   	/* Copy the start_info struct to a globally-accessible area. */
>   	/* WARN: don't do printk before here, it uses information from
> @@ -118,12 +145,15 @@ arch_init(start_info_t *si)
>   		(unsigned long)failsafe_callback, 0);
>   #endif
>
> -
> +	start_kernel();
>   }
>
>   void
>   arch_fini(void)
>   {
> +	/* Reset traps */
> +	trap_fini();
> +
>   #ifdef __i386__
>   	HYPERVISOR_set_callbacks(0, 0, 0, 0);
>   #else
> @@ -132,9 +162,7 @@ arch_fini(void)
>   }
>
>   void
> -arch_print_info(void)
> +arch_do_exit(void)
>   {
> -	printk("  stack:      %p-%p\n", stack, stack + sizeof(stack));
> +	stack_walk();
>   }
> -
> -
> diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
> index 2c8d033..c57ee55 100644
> --- a/extras/mini-os/arch/x86/time.c
> +++ b/extras/mini-os/arch/x86/time.c
> @@ -223,14 +223,14 @@ static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
>
>
>   static evtchn_port_t port;
> -void init_time(void)
> +void arch_init_time(void)
>   {
>       printk("Initialising timer interface\n");
>       port = bind_virq(VIRQ_TIMER, &timer_handler, NULL);
>       unmask_evtchn(port);
>   }
>
> -void fini_time(void)
> +void arch_fini_time(void)
>   {
>       /* Clear any pending timer */
>       HYPERVISOR_set_timer_op(0);
> diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
> index fb3e30a..b9aa392 100644
> --- a/extras/mini-os/arch/x86/x86_32.S
> +++ b/extras/mini-os/arch/x86/x86_32.S
> @@ -20,7 +20,7 @@ _start:
>           lss stack_start,%esp
>           andl $(~(__STACK_SIZE-1)), %esp
>           push %esi
> -        call start_kernel
> +        call arch_init
>
>   stack_start:
>   	.long stack+(2*__STACK_SIZE), __KERNEL_SS
> diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
> index f022eb3..df3469e 100644
> --- a/extras/mini-os/arch/x86/x86_64.S
> +++ b/extras/mini-os/arch/x86/x86_64.S
> @@ -21,7 +21,7 @@ _start:
>           movq stack_start(%rip),%rsp
>           andq $(~(__STACK_SIZE-1)), %rsp
>           movq %rsi,%rdi
> -        call start_kernel
> +        call arch_init
>
>   stack_start:
>           .quad stack+(2*__STACK_SIZE)
> diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c
> new file mode 100644
> index 0000000..5cda78d
> --- /dev/null
> +++ b/extras/mini-os/arch/x86/xenbus.c
> @@ -0,0 +1,10 @@
> +#include <mini-os/os.h>
> +#include <mini-os/mm.h>
> +#include <mini-os/xmalloc.h>
> +#include <xen/xen.h>
> +#include <xen/io/xs_wire.h>
> +
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {
> +    *xenstore_buf = mfn_to_virt(start_info.store_mfn);
> +    *store_evtchn = start_info.store_evtchn;
> +}
> diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
> index 5538bd4..c08fea9 100644
> --- a/extras/mini-os/console/console.c
> +++ b/extras/mini-os/console/console.c
> @@ -157,7 +157,9 @@ void xprintk(const char *fmt, ...)
>   void init_console(void)
>   {
>       printk("Initialising console ... ");
> +#ifndef __arm__
>       xencons_ring_init();
> +#endif
>       console_initialised = 1;
>       /* This is also required to notify the daemon */
>       printk("done.\n");
> diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c
> new file mode 100644
> index 0000000..14301ae
> --- /dev/null
> +++ b/extras/mini-os/drivers/gic.c
> @@ -0,0 +1,179 @@
> +// ARM GIC implementation
> +
> +#include <mini-os/os.h>
> +#include <mini-os/hypervisor.h>
> +
> +//#define VGIC_DEBUG
> +#ifdef VGIC_DEBUG
> +#define DEBUG(_f, _a...) \
> +    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)
> +#else
> +#define DEBUG(_f, _a...)    ((void)0)
> +#endif
> +
> +extern unsigned long IRQ_handler;
> +
> +struct gic {
> +	volatile char *gicd_base;
> +	volatile char *gicc_base;
> +};
> +
> +static struct gic gic;
> +
> +// Distributor Interface
> +#define GICD_CTLR		0x0
> +#define GICD_ISENABLER	0x100
> +#define GICD_PRIORITY	0x400
> +#define GICD_ITARGETSR	0x800
> +#define GICD_ICFGR		0xC00
> +
> +// CPU Interface
> +#define GICC_CTLR	0x0
> +#define GICC_PMR	0x4
> +#define GICC_IAR	0xc
> +#define GICC_EOIR	0x10
> +#define GICC_HPPIR	0x18
> +
> +#define gicd(gic, offset) ((gic)->gicd_base + (offset))
> +#define gicc(gic, offset) ((gic)->gicc_base + (offset))
> +
> +#define REG(addr) ((uint32_t *)(addr))
> +
> +static inline uint32_t REG_READ32(volatile uint32_t *addr)
> +{
> +	uint32_t value;
> +	__asm__ __volatile__("ldr %0, [%1]":"=&r"(value):"r"(addr));
> +	rmb();
> +	return value;
> +}
> +
> +static inline void REG_WRITE32(volatile uint32_t *addr, unsigned int value)
> +{
> +	__asm__ __volatile__("str %0, [%1]"::"r"(value), "r"(addr));
> +	wmb();
> +}
> +
> +static void gic_set_priority(struct gic *gic, unsigned char irq_number, unsigned char priority)
> +{
> +	uint32_t value;
> +	value = REG_READ32(REG(gicd(gic, GICD_PRIORITY)) + irq_number);
> +	value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
> +	value |= priority << (8 * (irq_number & 0x3)); // add our priority
> +	REG_WRITE32(REG(gicd(gic, GICD_PRIORITY)) + irq_number, value);
> +}
> +
> +static void gic_route_interrupt(struct gic *gic, unsigned char irq_number, unsigned char cpu_set)
> +{
> +	uint32_t value;
> +	value = REG_READ32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number);
> +	value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0'
> +	value |= cpu_set << (8 * (irq_number & 0x3)); // add our priority
> +	REG_WRITE32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number, value);
> +}
> +
> +static void gic_enable_interrupt(struct gic *gic, unsigned char irq_number,
> +		unsigned char cpu_set, unsigned char level_sensitive, unsigned char ppi)
> +{
> +	void *set_enable_reg;
> +	void *cfg_reg;
> +
> +	// set priority
> +	gic_set_priority(gic, irq_number, 0x0);
> +
> +	// set target cpus for this interrupt
> +	gic_route_interrupt(gic, irq_number, cpu_set);
> +
> +	// set level/edge triggered
> +	cfg_reg = (void *)gicd(gic, GICD_ICFGR);
> +	level_sensitive ? clear_bit((irq_number * 2) + 1, cfg_reg) : set_bit((irq_number * 2) + 1, cfg_reg);
> +	if(ppi)
> +		clear_bit((irq_number * 2), cfg_reg);
> +
> +	wmb();
> +
> +	// enable forwarding interrupt from distributor to cpu interface
> +	set_enable_reg = (void *)gicd(gic, GICD_ISENABLER);
> +	set_bit(irq_number, set_enable_reg);
> +	wmb();
> +}
> +
> +static void gic_enable_interrupts(struct gic *gic)
> +{
> +	// Global enable forwarding interrupts from distributor to cpu interface
> +	REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000001);
> +
> +	// Global enable signalling of interrupt from the cpu interface
> +	REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000001);
> +}
> +
> +static void gic_disable_interrupts(struct gic *gic)
> +{
> +	// Global disable signalling of interrupt from the cpu interface
> +	REG_WRITE32(REG(gicc(gic, GICC_CTLR)), 0x00000000);
> +
> +	// Global disable forwarding interrupts from distributor to cpu interface
> +	REG_WRITE32(REG(gicd(gic, GICD_CTLR)), 0x00000000);
> +}
> +
> +static void gic_cpu_set_priority(struct gic *gic, char priority)
> +{
> +	REG_WRITE32(REG(gicc(gic, GICC_PMR)), priority & 0x000000FF);
> +}
> +
> +static void gic_set_handler(unsigned long gic_handler) {
> +	IRQ_handler = gic_handler;
> +}
> +
> +static unsigned long gic_readiar(struct gic *gic) {
> +	return REG_READ32(REG(gicc(gic, GICC_IAR))) & 0x000003FF; // Interrupt ID
> +}
> +
> +static void gic_eoir(struct gic *gic, uint32_t irq) {
> +	REG_WRITE32(REG(gicc(gic, GICC_EOIR)), irq & 0x000003FF);
> +}
> +
> +//FIXME Get event_irq from dt
> +#define EVENTS_IRQ 31
> +#define VIRTUALTIMER_IRQ 27
> +
> +//FIXME Move to a header file
> +#define VTIMER_TICK 0x6000000
> +void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
> +void increment_vtimer_compare(uint64_t inc);
> +
> +static void gic_handler(void) {
> +	unsigned int irq = gic_readiar(&gic);
> +
> +	DEBUG("IRQ received : %i\n", irq);
> +	switch(irq) {
> +	case EVENTS_IRQ:
> +		do_hypervisor_callback(NULL);
> +		break;
> +	case VIRTUALTIMER_IRQ:
> +		timer_handler(0, NULL, 0);
> +		increment_vtimer_compare(VTIMER_TICK);
> +		break;
> +	default:
> +		DEBUG("Unhandled irq\n");
> +		break;
> +	}
> +
> +	DEBUG("EIRQ\n");
> +
> +	gic_eoir(&gic, irq);
> +}
> +
> +void gic_init(void) {
> +	// FIXME Get from dt!
> +	gic.gicd_base = (char *)0x2c001000ULL;
> +	gic.gicc_base = (char *)0x2c002000ULL;
> +	wmb();
> +
> +	gic_set_handler((unsigned long)gic_handler);
> +
> +	gic_disable_interrupts(&gic);
> +	gic_cpu_set_priority(&gic, 0xff);
> +	gic_enable_interrupt(&gic, EVENTS_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 0 /* ppi */);
> +	gic_enable_interrupt(&gic, VIRTUALTIMER_IRQ /* interrupt number */, 0x1 /*cpu_set*/, 1 /*level_sensitive*/, 1 /* ppi */);
> +	gic_enable_interrupts(&gic);
> +}
> diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> index 2da9b01..84a30a3 100644
> --- a/extras/mini-os/events.c
> +++ b/extras/mini-os/events.c
> @@ -47,9 +47,11 @@ void unbind_all_ports(void)
>
>       for ( i = 0; i < NR_EVS; i++ )
>       {
> +#ifndef __arm__
>           if ( i == start_info.console.domU.evtchn ||
>                i == start_info.store_evtchn)
>               continue;
> +#endif
>
>           if ( test_and_clear_bit(i, bound_ports) )
>           {
> @@ -167,44 +169,30 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
>   	return op.port;
>   }
>
> -#if defined(__x86_64__)
> -char irqstack[2 * STACK_SIZE];
> -
> -static struct pda
> -{
> -    int irqcount;       /* offset 0 (used in x86_64.S) */
> -    char *irqstackptr;  /*        8 */
> -} cpu0_pda;
> -#endif
> -
> +void arch_init_events(void);
>   /*
>    * Initially all events are without a handler and disabled
>    */
>   void init_events(void)
>   {
>       int i;
> -#if defined(__x86_64__)
> -    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
> -    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
> -    cpu0_pda.irqcount = -1;
> -    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
> -                                    & ~(STACK_SIZE - 1));
> -#endif
> +
>       /* initialize event handler */
>       for ( i = 0; i < NR_EVS; i++ )
>   	{
>           ev_actions[i].handler = default_handler;
>           mask_evtchn(i);
>       }
> +
> +    arch_init_events();
>   }
>
> +void arch_fini_events(void);
>   void fini_events(void)
>   {
>       /* Dealloc all events */
>       unbind_all_ports();
> -#if defined(__x86_64__)
> -    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
> -#endif
> +    arch_fini_events();
>   }
>
>   void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
> @@ -262,7 +250,8 @@ int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
>
>   int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
>   {
> -    int rc;
> +    int rc = 0;
> +#ifndef __arm__
>       uint32_t sid;
>       struct xen_flask_op op;
>       op.cmd = FLASK_GET_PEER_SID;
> @@ -277,6 +266,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
>       op.u.sid_context.size = size;
>       set_xen_guest_handle(op.u.sid_context.context, ctx);
>       rc = _hypercall1(int, xsm_op, &op);
> +#endif
>       return rc;
>   }
>
> diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
> index 7eb69be..abfbd29 100644
> --- a/extras/mini-os/gntmap.c
> +++ b/extras/mini-os/gntmap.c
> @@ -37,6 +37,7 @@
>   #include <xen/grant_table.h>
>   #include <inttypes.h>
>   #include <mini-os/gntmap.h>
> +#include <mini-os/hypervisor.h>
>
>   //#define GNTMAP_DEBUG
>   #ifdef GNTMAP_DEBUG
> diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
> index 2f1b3d7..404d72c 100644
> --- a/extras/mini-os/gnttab.c
> +++ b/extras/mini-os/gnttab.c
> @@ -19,6 +19,7 @@
>   #include <mini-os/mm.h>
>   #include <mini-os/gnttab.h>
>   #include <mini-os/semaphore.h>
> +#include <mini-os/hypervisor.h>
>
>   #define NR_RESERVED_ENTRIES 8
>
> diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
> index b4688a0..9c79d5d 100644
> --- a/extras/mini-os/hypervisor.c
> +++ b/extras/mini-os/hypervisor.c
> @@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
>       in_callback = 0;
>   }
>
> -void force_evtchn_callback(void)
> -{
> -    int save;
> -    vcpu_info_t *vcpu;
> -    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> -    save = vcpu->evtchn_upcall_mask;
> -
> -    while (vcpu->evtchn_upcall_pending) {
> -        vcpu->evtchn_upcall_mask = 1;
> -        barrier();
> -        do_hypervisor_callback(NULL);
> -        barrier();
> -        vcpu->evtchn_upcall_mask = save;
> -        barrier();
> -    };
> -}
> -
>   inline void mask_evtchn(uint32_t port)
>   {
>       shared_info_t *s = HYPERVISOR_shared_info;
> @@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
>                 &vcpu_info->evtchn_pending_sel) )
>       {
>           vcpu_info->evtchn_upcall_pending = 1;
> -        if ( !vcpu_info->evtchn_upcall_mask )
> -            force_evtchn_callback();
> +        force_evtchn_callback();
>       }
>   }
>
> diff --git a/extras/mini-os/include/arm/arch_limits.h b/extras/mini-os/include/arm/arch_limits.h
> new file mode 100644
> index 0000000..bae99e1
> --- /dev/null
> +++ b/extras/mini-os/include/arm/arch_limits.h
> @@ -0,0 +1,9 @@
> +#ifndef __ARCH_LIMITS_H__
> +#define __ARCH_LIMITS_H__
> +
> +#include <mm.h>
> +
> +#define __STACK_SIZE_PAGE_ORDER  2
> +#define __STACK_SIZE (4 * PAGE_SIZE)
> +
> +#endif
> diff --git a/extras/mini-os/include/arm/arch_mm.h b/extras/mini-os/include/arm/arch_mm.h
> new file mode 100644
> index 0000000..9b2cc03
> --- /dev/null
> +++ b/extras/mini-os/include/arm/arch_mm.h
> @@ -0,0 +1,37 @@
> +#ifndef _ARCH_MM_H_
> +#define _ARCH_MM_H_
> +
> +extern char _text, _etext, _erodata, _edata, _end, __bss_start;
> +extern char stack[];
> +
> +#define PAGE_SHIFT		12
> +#define PAGE_SIZE		(1 << PAGE_SHIFT)
> +#define PAGE_MASK       (~(PAGE_SIZE-1))
> +
> +#define L1_PAGETABLE_SHIFT      12
> +
> +#if 0
> +#define VIRT_START                 ((unsigned long)&_text)
> +#else
> +#define VIRT_START                 ((unsigned long)0)
> +#endif
> +
> +#define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
> +#define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
> +
> +#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
> +#define PFN_DOWN(x)	((x) >> L1_PAGETABLE_SHIFT)
> +#define PFN_PHYS(x)	((uint64_t)(x) << L1_PAGETABLE_SHIFT)
> +#define PHYS_PFN(x)	((x) >> L1_PAGETABLE_SHIFT)
> +
> +#define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
> +#define virt_to_mfn(_virt)         (0)
> +#define mach_to_virt(_mach)        (0)
> +#define virt_to_mach(_virt)        (0)
> +#define mfn_to_virt(_mfn)          (0)
> +#define pfn_to_virt(_pfn)          (to_virt(PFN_PHYS(_pfn)))
> +
> +// FIXME
> +#define map_frames(f, n) (NULL)
> +
> +#endif
> diff --git a/extras/mini-os/include/arm/arch_sched.h b/extras/mini-os/include/arm/arch_sched.h
> new file mode 100644
> index 0000000..31d9071
> --- /dev/null
> +++ b/extras/mini-os/include/arm/arch_sched.h
> @@ -0,0 +1,22 @@
> +
> +#ifndef __ARCH_SCHED_H__
> +#define __ARCH_SCHED_H__
> +
> +#include "arch_limits.h"
> +
> +static inline struct thread* get_current(void)
> +{
> +   struct thread **current;
> +   unsigned long sp;
> +   __asm__ __volatile__ ("mov %0, sp":"=r"(sp));
> +	current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
> +	return *current;
> +}
> +
> +
> +extern void __arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
> +
> +#define arch_switch_threads(prev,next) __arch_switch_threads(&(prev)->sp, &(next)->sp)
> +
> +
> +#endif /* __ARCH_SCHED_H__ */
> diff --git a/extras/mini-os/include/arm/arch_spinlock.h b/extras/mini-os/include/arm/arch_spinlock.h
> new file mode 100755
> index 0000000..6677bc4
> --- /dev/null
> +++ b/extras/mini-os/include/arm/arch_spinlock.h
> @@ -0,0 +1,49 @@
> +
> +
> +#ifndef __ARCH_ASM_SPINLOCK_H
> +#define __ARCH_ASM_SPINLOCK_H
> +
> +#include "os.h"
> +
> +
> +#define ARCH_SPIN_LOCK_UNLOCKED { 1 }
> +
> +/*
> + * Simple spin lock operations.  There are two variants, one clears IRQ's
> + * on the local processor, one does not.
> + *
> + * We make no fairness assumptions. They have a cost.
> + */
> +
> +#define arch_spin_is_locked(x)	(*(volatile signed char *)(&(x)->slock) <= 0)
> +#define arch_spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
> +
> +/*
> + * This works. Despite all the confusion.
> + * (except on PPro SMP or if we are using OOSTORE)
> + * (PPro errata 66, 92)
> + */
> +
> +static inline void _raw_spin_unlock(spinlock_t *lock)
> +{
> +	xchg(&lock->slock, 1);
> +}
> +
> +static inline int _raw_spin_trylock(spinlock_t *lock)
> +{
> +	return xchg(&lock->slock, 0) != 0 ? 1 : 0;
> +}
> +
> +static inline void _raw_spin_lock(spinlock_t *lock)
> +{
> +	volatile int was_locked;
> +	do {
> +		was_locked = xchg(&lock->slock, 0) == 0 ? 1 : 0;
> +	} while(was_locked);
> +}
> +
> +static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
> +{
> +}
> +
> +#endif
> diff --git a/extras/mini-os/include/arm/hypercall-arm32.h b/extras/mini-os/include/arm/hypercall-arm32.h
> new file mode 100644
> index 0000000..0343946
> --- /dev/null
> +++ b/extras/mini-os/include/arm/hypercall-arm32.h
> @@ -0,0 +1,173 @@
> +/******************************************************************************
> + * hypercall-x86_64.h
> + *
> + * Copied from XenLinux.
> + *
> + * Copyright (c) 2002-2004, K A Fraser
> + *
> + * 64-bit updates:
> + *   Benjamin Liu <benjamin.liu@intel.com>
> + *   Jun Nakajima <jun.nakajima@intel.com>
> + *
> + * This file may be distributed separately from the Linux kernel, or
> + * incorporated into other software packages, subject to the following license:
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this source file (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use, copy, modify,
> + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> + * and to permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#ifndef __HYPERCALL_ARM_H__
> +#define __HYPERCALL_ARM_H__
> +
> +#include <xen/xen.h>
> +#include <xen/sched.h>
> +#include <mini-os/mm.h>
> +
> +inline int
> +HYPERVISOR_mmu_update(
> +	mmu_update_t *req, int count, int *success_count, domid_t domid);
> +
> +inline int
> +HYPERVISOR_mmuext_op(
> +	struct mmuext_op *op, int count, int *success_count, domid_t domid);
> +
> +inline int
> +HYPERVISOR_set_gdt(
> +	unsigned long *frame_list, int entries);
> +
> +inline int
> +HYPERVISOR_stack_switch(
> +	unsigned long ss, unsigned long esp);
> +
> +inline int
> +HYPERVISOR_set_callbacks(
> +	unsigned long event_address, unsigned long failsafe_address,
> +	unsigned long syscall_address);
> +
> +inline int
> +HYPERVISOR_fpu_taskswitch(
> +	int set);
> +
> +inline int
> +HYPERVISOR_sched_op(
> +	int cmd, void *arg);
> +
> +static inline int
> +HYPERVISOR_shutdown(
> +	unsigned int reason)
> +{
> +	struct sched_shutdown shutdown = { .reason = reason };
> +	return low_shutdown(&shutdown);
> +}
> +
> +inline long
> +HYPERVISOR_set_timer_op(
> +	uint64_t timeout);
> +
> +inline int
> +HYPERVISOR_set_debugreg(
> +	int reg, unsigned long value);
> +
> +inline unsigned long
> +HYPERVISOR_get_debugreg(
> +	int reg);
> +
> +inline int
> +HYPERVISOR_update_descriptor(
> +	unsigned long ma, unsigned long word);
> +
> +inline int
> +HYPERVISOR_memory_op(
> +	unsigned int cmd, void *arg);
> +
> +inline int
> +HYPERVISOR_multicall(
> +	void *call_list, int nr_calls);
> +
> +inline int
> +HYPERVISOR_update_va_mapping(
> +	unsigned long va, pte_t new_val, unsigned long flags);
> +
> +inline int
> +HYPERVISOR_event_channel_op(
> +       int cmd, void *op);
> +
> +inline int
> +HYPERVISOR_xen_version(
> +	int cmd, void *arg);
> +
> +inline int
> +HYPERVISOR_console_io(
> +	int cmd, int count, char *str);
> +
> +inline int
> +HYPERVISOR_physdev_op(
> +	void *physdev_op);
> +
> +inline int
> +HYPERVISOR_grant_table_op(
> +	unsigned int cmd, void *uop, unsigned int count);
> +
> +inline int
> +HYPERVISOR_update_va_mapping_otherdomain(
> +	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid);
> +
> +inline int
> +HYPERVISOR_vm_assist(
> +	unsigned int cmd, unsigned int type);
> +
> +inline int
> +HYPERVISOR_vcpu_op(
> +	int cmd, int vcpuid, void *extra_args);
> +
> +inline int
> +HYPERVISOR_set_segment_base(
> +	int reg, unsigned long value);
> +
> +inline int
> +HYPERVISOR_suspend(
> +	unsigned long srec);
> +
> +inline int
> +HYPERVISOR_nmi_op(
> +	unsigned long op,
> +	unsigned long arg);
> +
> +inline int
> +HYPERVISOR_sysctl(
> +	unsigned long op);
> +
> +inline int
> +HYPERVISOR_domctl(
> +	unsigned long op);
> +
> +inline int
> +HYPERVISOR_hvm_op(
> +	unsigned long op, void *arg);
> +
> +#endif /* __HYPERCALL_X86_64_H__ */
> +
> +/*
> + * Local variables:
> + *  c-file-style: "linux"
> + *  indent-tabs-mode: t
> + *  c-indent-level: 8
> + *  c-basic-offset: 8
> + *  tab-width: 8
> + * End:
> + */
> diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
> new file mode 100644
> index 0000000..60e84f7
> --- /dev/null
> +++ b/extras/mini-os/include/arm/os.h
> @@ -0,0 +1,314 @@
> +#ifndef _OS_H_
> +#define _OS_H_
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <mini-os/types.h>
> +#include <xen/xen.h>
> +
> +void arch_fini(void);
> +
> +#define BUG() while(1){}
> +
> +#define smp_processor_id() 0
> +
> +#define barrier() __asm__ __volatile__("": : :"memory")
> +
> +extern shared_info_t *HYPERVISOR_shared_info;
> +
> +#if 0
> +static inline void force_evtchn_callback(void)
> +{
> +    int save;
> +    vcpu_info_t *vcpu;
> +    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> +    save = vcpu->evtchn_upcall_mask;
> +
> +    while (vcpu->evtchn_upcall_pending) {
> +        vcpu->evtchn_upcall_mask = 1;
> +        barrier();
> +        do_hypervisor_callback(NULL);
> +        barrier();
> +        vcpu->evtchn_upcall_mask = save;
> +        barrier();
> +    };
> +}
> +#else
> +#define force_evtchn_callback(void) do {} while(0)
> +#endif
> +
> +// disable interrupts
> +static inline __cli(void) {
> +	int x;
> +	__asm__ __volatile__("mrs %0, cpsr;cpsid i":"=r"(x)::"memory");
> +}
> +
> +// enable interrupts
> +static inline __sti(void) {
> +	int x;
> +	__asm__ __volatile__("mrs %0, cpsr\n"
> +						"bic %0, %0, #0x80\n"
> +						"msr cpsr_c, %0"
> +						:"=r"(x)::"memory");
> +}
> +
> +static inline int irqs_disabled() {
> +	int x;
> +	__asm__ __volatile__("mrs %0, cpsr\n":"=r"(x)::"memory");
> +	return (x & 0x80);
> +}
> +
> +#define local_irq_save(x) { \
> +	__asm__ __volatile__("mrs %0, cpsr;cpsid i; and %0, %0, #0x80":"=r"(x)::"memory");	\
> +}
> +
> +#define local_irq_restore(x) {	\
> +	__asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory");	\
> +}
> +
> +#define local_save_flags(x)	{ \
> +		__asm__ __volatile__("mrs %0, cpsr; and %0, %0, 0x80":"=r"(x)::"memory");	\
> +}
> +
> +#define local_irq_disable()	__cli()
> +#define local_irq_enable() __sti()
> +
> +#if defined(__arm__)
> +#define mb() __asm__("dmb");
> +#define rmb() __asm__("dmb");
> +#define wmb() __asm__("dmb");
> +#elif defined(__aarch64__)
> +#define mb()
> +#define rmb()
> +#define wmb()
> +#else
> +#error undefined architecture
> +#endif
> +
> +#define LOCK_PREFIX ""
> +#define LOCK ""
> +
> +#define unlikely(x)  __builtin_expect((x),0)
> +#define likely(x)  __builtin_expect((x),1)
> +
> +#define ADDR (*(volatile long *) addr)
> +
> +/************************** arm *******************************/
> +#ifdef __INSIDE_MINIOS__
> +#if defined (__arm__)
> +#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
> +#define __xg(x) ((volatile long *)(x))
> +
> +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
> +{
> +	//TODO
> +	unsigned volatile long y, tmp = 0;
> +	switch(size){
> +	case 1:
> +#if CPU_EXCLUSIVE_LDST
> +		__asm__ __volatile__("1:ldrexb %0, [%1]\n"
> +			"strexb %3, %2, [%1]\n"
> +			"cmp %3, #1\n"
> +			"beq 1b\n\n"
> +			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
> +#else
> +		y = (*(char *)ptr) & 0x000000ff;
> +		*((char *)ptr) = (char)x;
> +#endif
> +		break;
> +	case 2:
> +#if CPU_EXCLUSIVE_LDST
> +		__asm__ __volatile__("1:ldrexh %0, [%1]\n"
> +			"strexh %3, %2, [%1]\n"
> +			"cmp %3, #1\n"
> +			"beq 1b\n\n"
> +			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
> +#else
> +		y = (*(short *)ptr) & 0x0000ffff;
> +		*((short *)ptr) = (short)x;
> +#endif
> +		break;
> +	default: // 4
> +#if CPU_EXCLUSIVE_LDST
> +		__asm__ __volatile__("1:ldrex %0, [%1]\n"
> +			"strex %3, %2, [%1]\n"
> +			"cmp %3, #1\n"
> +			"beq 1b\n\n"
> +			"dmb\n":"=&r"(y):"r"(ptr), "r"(x), "r"(tmp):"memory");
> +#else
> +		y = (*(unsigned long *)ptr) & 0xffffffff;
> +		*((unsigned long *)ptr) = x;
> +#endif
> +		break;
> +	}
> +    return y;
> +}
> +
> +/**
> + * test_and_clear_bit - Clear a bit and return its old value
> + * @nr: Bit to clear
> + * @addr: Address to count from
> + *
> + * This operation is atomic and cannot be reordered.
> + * It also implies a memory barrier.
> + */
> +static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
> +{
> +	//TODO
> +	unsigned long *tmp = (unsigned long *)addr;
> +
> +	int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
> +	tmp[nr >> 5] &= ~(1 << (nr & 0x1f));
> +    return x;
> +}
> +
> +static __inline__ int test_and_set_bit(int nr, volatile void * addr)
> +{
> +	//TODO
> +	unsigned long *tmp = (unsigned long *)addr;
> +
> +	int x = tmp[nr >> 5] & (1 << (nr & 0x1f));
> +	tmp[nr >> 5] |= (1 << (nr & 0x1f));
> +    return x;
> +}
> +
> +static __inline__ int constant_test_bit(int nr, const volatile void * addr)
> +{
> +	//TODO
> +	unsigned long *tmp = (unsigned long *)addr;
> +    return tmp[nr >> 5] & (1 << (nr & 0x1f));
> +}
> +
> +static __inline__ int variable_test_bit(int nr, volatile const void * addr)
> +{
> +	//TODO:
> +	unsigned long *tmp = (unsigned long *)addr;
> +	return tmp[nr >> 5] & (1 << (nr & 0x1f));
> +}
> +
> +//TODO
> +#define test_bit(nr,addr) (((unsigned long *)addr)[nr >> 5] & (1 << (nr & 0x1f)))
> +
> +
> +/**
> + * set_bit - Atomically set a bit in memory
> + * @nr: the bit to set
> + * @addr: the address to start counting from
> + *
> + * This function is atomic and may not be reordered.  See __set_bit()
> + * if you do not require the atomic guarantees.
> + * Note that @nr may be almost arbitrarily large; this function is not
> + * restricted to acting on a single-word quantity.
> + */
> +static __inline__ void set_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +	unsigned long *tmp = (unsigned long *)addr;
> +	tmp[nr >> 5] |= (1 << (nr & 0x1f));
> +}
> +
> +/**
> + * clear_bit - Clears a bit in memory
> + * @nr: Bit to clear
> + * @addr: Address to start counting from
> + *
> + * clear_bit() is atomic and may not be reordered.  However, it does
> + * not contain a memory barrier, so if it is used for locking purposes,
> + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
> + * in order to ensure changes are visible on other processors.
> + */
> +static __inline__ void clear_bit(int nr, volatile void * addr)
> +{
> +	//TODO
> +	unsigned long *tmp = (unsigned long *)addr;
> +	tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f));
> +}
> +
> +/**
> + * __ffs - find first bit in word.
> + * @word: The word to search
> + *
> + * Undefined if no bit exists, so code should check against 0 first.
> + */
> +static __inline__ unsigned long __ffs(unsigned long word)
> +{
> +	//TODO
> +	int index = 0;
> +	while(!(word & (1 << index++))){};
> +
> +	return index - 1;
> +}
> +
> +//FIXME
> +#define rdtscll(val) (val = 0)
> +
> +#define wrmsr(msr,val1,val2) (0)
> +
> +#define wrmsrl(msr,val) wrmsr(msr,(uint32_t)((uint64_t)(val)),((uint64_t)(val))>>32)
> +
> +
> +#else /* ifdef __arm__ */
> +#error "Unsupported architecture"
> +#endif
> +#endif /* ifdef __INSIDE_MINIOS */
> +
> +/********************* common arm32 and arm64  ****************************/
> +struct __synch_xchg_dummy { unsigned long a[100]; };
> +#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
> +
> +#define synch_cmpxchg(ptr, old, new) (0)
> +
> +static inline unsigned long __synch_cmpxchg(volatile void *ptr,
> +        unsigned long old,
> +        unsigned long new, int size)
> +{
> +	//TODO:
> +    //BUG();
> +    return 0;
> +}
> +
> +
> +static __inline__ void synch_set_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +	set_bit(nr, addr);
> +}
> +
> +static __inline__ void synch_clear_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +    clear_bit(nr, addr);
> +}
> +
> +static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +	return test_and_set_bit(nr, addr);
> +}
> +
> +static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +    return test_and_clear_bit(nr, addr);
> +}
> +
> +static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
> +{
> +	//TODO:
> +    return const_test_bit(nr, addr);
> +}
> +
> +static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
> +{
> +	//TODO:
> +    return var_test_bit(nr, addr);
> +}
> +
> +#define synch_test_bit(nr,addr) test_bit(nr, addr)
> +
> +
> +#undef ADDR
> +
> +#endif /* not assembly */
> +
> +#endif
> diff --git a/extras/mini-os/include/arm/traps.h b/extras/mini-os/include/arm/traps.h
> new file mode 100644
> index 0000000..b8ce784
> --- /dev/null
> +++ b/extras/mini-os/include/arm/traps.h
> @@ -0,0 +1,20 @@
> +#ifndef _TRAPS_H_
> +#define _TRAPS_H_
> +
> +struct pt_regs {
> +	unsigned long r0;
> +	unsigned long r1;
> +	unsigned long r2;
> +	unsigned long r3;
> +	unsigned long r4;
> +	unsigned long r5;
> +	unsigned long r6;
> +	unsigned long r7;
> +	unsigned long r8;
> +	unsigned long r9;
> +	unsigned long r10;
> +	unsigned long r11;
> +	unsigned long r12;
> +};
> +
> +#endif
> diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
> index 3755b66..dade8fb 100644
> --- a/extras/mini-os/include/console.h
> +++ b/extras/mini-os/include/console.h
> @@ -42,6 +42,7 @@
>   #include <xen/grant_table.h>
>   #include <xenbus.h>
>   #include <xen/io/console.h>
> +#include <xen/event_channel.h>
>   #include <stdarg.h>
>
>   struct consfront_dev {
> diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
> index a62cb78..ee288a0 100644
> --- a/extras/mini-os/include/hypervisor.h
> +++ b/extras/mini-os/include/hypervisor.h
> @@ -13,16 +13,34 @@
>   #define _HYPERVISOR_H_
>
>   #include <mini-os/types.h>
> +
>   #include <xen/xen.h>
> +
>   #if defined(__i386__)
>   #include <hypercall-x86_32.h>
>   #elif defined(__x86_64__)
>   #include <hypercall-x86_64.h>
> +#elif defined(__arm__)
> +#include <hypercall-arm32.h>
> +#elif defined(__aarch64__)
> +#include <hypercall-arm64.h>
>   #else
>   #error "Unsupported architecture"
>   #endif
>   #include <mini-os/traps.h>
>
> +#ifdef __arm__
> +struct start_info {
> +    union {
> +        struct {
> +            xen_pfn_t mfn;
> +            uint32_t  evtchn;
> +        } domU;
> +    } console;
> +};
> +typedef struct start_info start_info_t;
> +#endif
> +
>   /*
>    * a placeholder for the start of day information passed up from the hypervisor
>    */
> @@ -35,7 +53,6 @@ extern union start_info_union start_info_union;
>   #define start_info (start_info_union.start_info)
>
>   /* hypervisor.c */
> -void force_evtchn_callback(void);
>   void do_hypervisor_callback(struct pt_regs *regs);
>   void mask_evtchn(uint32_t port);
>   void unmask_evtchn(uint32_t port);
> diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
> index a94cd6d..644c7de 100644
> --- a/extras/mini-os/include/mm.h
> +++ b/extras/mini-os/include/mm.h
> @@ -29,6 +29,8 @@
>   #include <xen/arch-x86_32.h>
>   #elif defined(__x86_64__)
>   #include <xen/arch-x86_64.h>
> +#elif defined(__arm__) || defined(__aarch64__)
> +#include <xen/arch-arm.h>
>   #else
>   #error "Unsupported architecture"
>   #endif
> diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
> index 6640ede..781144c 100644
> --- a/extras/mini-os/include/types.h
> +++ b/extras/mini-os/include/types.h
> @@ -27,7 +27,7 @@ typedef unsigned char       u_char;
>   typedef unsigned int        u_int;
>   typedef unsigned long       u_long;
>   #endif
> -#ifdef __i386__
> +#if defined(__i386__) || defined(__arm__)
>   typedef long long           quad_t;
>   typedef unsigned long long  u_quad_t;
>
> @@ -40,7 +40,7 @@ typedef unsigned long       u_quad_t;
>   typedef struct { unsigned long pte; } pte_t;
>   #endif /* __i386__ || __x86_64__ */
>
> -#ifdef __x86_64__
> +#if defined(__x86_64__) || defined(__aarch64__)
>   #define __pte(x) ((pte_t) { (x) } )
>   #else
>   #define __pte(x) ({ unsigned long long _x = (x);        \
> @@ -51,10 +51,10 @@ typedef struct { unsigned long pte; } pte_t;
>   #include <limits.h>
>   #include <stdint.h>
>   #else
> -#ifdef __i386__
> +#if defined(__i386__) || defined(__arm__)
>   typedef unsigned int        uintptr_t;
>   typedef int                 intptr_t;
> -#elif defined(__x86_64__)
> +#elif defined(__x86_64__) || defined(__aarch64__)
>   typedef unsigned long       uintptr_t;
>   typedef long                intptr_t;
>   #endif /* __i386__ || __x86_64__ */
> @@ -64,10 +64,10 @@ typedef unsigned short uint16_t;
>   typedef   signed short int16_t;
>   typedef unsigned int uint32_t;
>   typedef   signed int int32_t;
> -#ifdef __i386__
> +#if defined(__i386__) || defined(__arm__)
>   typedef   signed long long int64_t;
>   typedef unsigned long long uint64_t;
> -#elif defined(__x86_64__)
> +#elif defined(__x86_64__) || defined(__aarch64__)
>   typedef   signed long int64_t;
>   typedef unsigned long uint64_t;
>   #endif
> @@ -83,4 +83,65 @@ typedef intptr_t            ptrdiff_t;
>   typedef long ssize_t;
>   #endif
>
> +#ifdef __arm__
> +/*
> + * From
> + *	@(#)quad.h	8.1 (Berkeley) 6/4/93
> + */
> +
> +#ifdef __BIG_ENDIAN
> +#define _QUAD_HIGHWORD 0
> +#define _QUAD_LOWWORD 1
> +#else /* __LITTLE_ENDIAN */
> +#define _QUAD_HIGHWORD 1
> +#define _QUAD_LOWWORD 0
> +#endif
> +
> +/*
> + * Define high and low longwords.
> + */
> +#define H               _QUAD_HIGHWORD
> +#define L               _QUAD_LOWWORD
> +
> +/*
> + * Total number of bits in a quad_t and in the pieces that make it up.
> + * These are used for shifting, and also below for halfword extraction
> + * and assembly.
> + */
> +#define CHAR_BIT        8               /* number of bits in a char */
> +#define QUAD_BITS       (sizeof(s64) * CHAR_BIT)
> +#define LONG_BITS       (sizeof(long) * CHAR_BIT)
> +#define HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
> +
> +#define B (1 << HALF_BITS) /* digit base */
> +/*
> + * Extract high and low shortwords from longword, and move low shortword of
> + * longword to upper half of long, i.e., produce the upper longword of
> + * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
> + *
> + * These are used in the multiply code, to split a longword into upper
> + * and lower halves, and to reassemble a product as a quad_t, shifted left
> + * (sizeof(long)*CHAR_BIT/2).
> + */
> +#define HHALF(x)        ((x) >> HALF_BITS)
> +#define LHALF(x)        ((x) & ((1 << HALF_BITS) - 1))
> +#define LHUP(x)         ((x) << HALF_BITS)
> +
> +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
> +
> +/*
> + * Depending on the desired operation, we view a `long long' (aka quad_t) in
> + * one or more of the following formats.
> + */
> +union uu {
> +    int64_t            q;              /* as a (signed) quad */
> +    int64_t            uq;             /* as an unsigned quad */
> +    long           sl[2];          /* as two signed longs */
> +    unsigned long  ul[2];          /* as two unsigned longs */
> +};
> +
> +/* select a type for digits in base B */
> +typedef u_long digit;
> +#endif
> +
>   #endif /* _TYPES_H_ */
> diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h
> index 23cfca7..3b74cd7 100644
> --- a/extras/mini-os/include/x86/arch_mm.h
> +++ b/extras/mini-os/include/x86/arch_mm.h
> @@ -25,6 +25,8 @@
>   #ifndef _ARCH_MM_H_
>   #define _ARCH_MM_H_
>
> +extern char stack[];
> +
>   #ifndef __ASSEMBLY__
>   #include <xen/xen.h>
>   #if defined(__i386__)
> diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
> index f193865..8eea1be 100644
> --- a/extras/mini-os/include/x86/os.h
> +++ b/extras/mini-os/include/x86/os.h
> @@ -64,8 +64,6 @@ extern shared_info_t *HYPERVISOR_shared_info;
>   void trap_init(void);
>   void trap_fini(void);
>
> -void arch_init(start_info_t *si);
> -void arch_print_info(void);
>   void arch_fini(void);
>
>
> @@ -162,6 +160,23 @@ do {									\
>    */
>   typedef struct { volatile int counter; } atomic_t;
>
> +static inline void force_evtchn_callback(void)
> +{
> +    int save;
> +    vcpu_info_t *vcpu;
> +    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> +    save = vcpu->evtchn_upcall_mask;
> +
> +    while (vcpu->evtchn_upcall_pending) {
> +        vcpu->evtchn_upcall_mask = 1;
> +        barrier();
> +        do_hypervisor_callback(NULL);
> +        barrier();
> +        vcpu->evtchn_upcall_mask = save;
> +        barrier();
> +    };
> +}
> +
>
>   /************************** i386 *******************************/
>   #ifdef __INSIDE_MINIOS__
> diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
> index 7083763..4581574 100644
> --- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
> +++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
> @@ -37,6 +37,7 @@
>   #include <xen/xen.h>
>   #include <xen/sched.h>
>   #include <mini-os/mm.h>
> +#include <arch_mm.h>
>
>   #define __STR(x) #x
>   #define STR(x) __STR(x)
> diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
> index 386be8f..de25921 100644
> --- a/extras/mini-os/kernel.c
> +++ b/extras/mini-os/kernel.c
> @@ -27,7 +27,6 @@
>    * DEALINGS IN THE SOFTWARE.
>    */
>
> -#include <mini-os/os.h>
>   #include <mini-os/hypervisor.h>
>   #include <mini-os/mm.h>
>   #include <mini-os/events.h>
> @@ -118,40 +117,14 @@ __attribute__((weak)) int app_main(start_info_t *si)
>       return 0;
>   }
>
> -/*
> - * INITIAL C ENTRY POINT.
> - */
> -void start_kernel(start_info_t *si)
> -{
> -    static char hello[] = "Bootstrapping...\n";
> -
> -    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
> -
> -    arch_init(si);
> -
> -    trap_init();
> -
> -    /* print out some useful information  */
> -    printk("Xen Minimal OS!\n");
> -    printk("  start_info: %p(VA)\n", si);
> -    printk("    nr_pages: 0x%lx\n", si->nr_pages);
> -    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
> -    printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
> -    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
> -    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
> -    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
> -    printk("     mod_len: %lu\n", si->mod_len);
> -    printk("       flags: 0x%x\n", (unsigned int)si->flags);
> -    printk("    cmd_line: %s\n",
> -           si->cmd_line ? (const char *)si->cmd_line : "NULL");
> +void gic_init(void);
>
> +void start_kernel(void)
> +{
>       /* Set up events. */
>       init_events();
> -
> -    /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
> -    __sti();
>
> -    arch_print_info();
> +    __sti();
>
>       setup_xen_features();
>
> @@ -161,24 +134,58 @@ void start_kernel(start_info_t *si)
>       /* Init time and timers. */
>       init_time();
>
> +#ifndef __arm__
>       /* Init the console driver. */
>       init_console();
> +#endif
>
>       /* Init grant tables */
>       init_gnttab();
> -
> +
>       /* Init scheduler. */
>       init_sched();
>
>       /* Init XenBus */
>       init_xenbus();
>
> +
>   #ifdef CONFIG_XENBUS
>       create_thread("shutdown", shutdown_thread, NULL);
>   #endif
>
> +#ifdef __arm__
> +    gic_init();
> +#endif
> +
> +//#define VTIMER_TEST
> +#ifdef VTIMER_TEST
> +    while(1){
> +		int x, y, z;
> +    	z = 0;
> +    	// counter
> +    	__asm__ __volatile__("mrrc p15, 1, %0, %1, c14;isb":"=r"(x), "=r"(y));
> +    	printk("Counter: %x-%x\n", x, y);
> +
> +    	__asm__ __volatile__("mrrc p15, 3, %0, %1, c14;isb":"=r"(x), "=r"(y));
> +    	printk("CompareValue: %x-%x\n", x, y);
> +
> +    	// TimerValue
> +    	__asm__ __volatile__("mrc p15, 0, %0, c14, c3, 0;isb":"=r"(x));
> +    	printk("TimerValue: %x\n", x);
> +
> +    	// control register
> +    	__asm__ __volatile__("mrc p15, 0, %0, c14, c3, 1;isb":"=r"(x));
> +    	printk("ControlRegister: %x\n", x);
> +    	while(z++ < 0xfffff){}
> +    }
> +#endif
> +
>       /* Call (possibly overridden) app_main() */
> +#if defined(__arm__) || defined(__aarch64__)
> +    app_main(NULL);
> +#else
>       app_main(&start_info);
> +#endif
>
>       /* Everything initialised, start idle thread */
>       run_idle_thread();
> @@ -205,13 +212,12 @@ void stop_kernel(void)
>       /* Reset events. */
>       fini_events();
>
> -    /* Reset traps */
> -    trap_fini();
> -
>       /* Reset arch details */
>       arch_fini();
>   }
>
> +void arch_do_exit(void);
> +
>   /*
>    * do_exit: This is called whenever an IRET fails in entry.S.
>    * This will generally be because an application has got itself into
> @@ -222,7 +228,7 @@ void stop_kernel(void)
>   void do_exit(void)
>   {
>       printk("Do_exit called!\n");
> -    stack_walk();
> +    arch_do_exit();
>       for( ;; )
>       {
>           struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
> diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
> index d2d5264..ab76018 100644
> --- a/extras/mini-os/mm.c
> +++ b/extras/mini-os/mm.c
> @@ -213,22 +213,26 @@ static void init_page_allocator(unsigned long min, unsigned long max)
>       min = round_pgup  (min);
>       max = round_pgdown(max);
>
> +
>       /* Allocate space for the allocation bitmap. */
> -    bitmap_size  = (max+1) >> (PAGE_SHIFT+3);
> +    bitmap_size  = (max - min + 1) >> (PAGE_SHIFT+3);
>       bitmap_size  = round_pgup(bitmap_size);
>       alloc_bitmap = (unsigned long *)to_virt(min);
>       min         += bitmap_size;
>       range        = max - min;
>
> +
>       /* All allocated by default. */
>       memset(alloc_bitmap, ~0, bitmap_size);
>       /* Free up the memory we've been given to play with. */
>       map_free(PHYS_PFN(min), range>>PAGE_SHIFT);
>
> +
>       /* The buddy lists are addressed in high memory. */
>       min = (unsigned long) to_virt(min);
>       max = (unsigned long) to_virt(max);
>
> +
>       while ( range != 0 )
>       {
>           /*
> @@ -238,7 +242,6 @@ static void init_page_allocator(unsigned long min, unsigned long max)
>           for ( i = PAGE_SHIFT; (1UL<<(i+1)) <= range; i++ )
>               if ( min & (1UL<<i) ) break;
>
> -
>           ch = (chunk_head_t *)min;
>           min   += (1UL<<i);
>           range -= (1UL<<i);
> @@ -399,9 +402,7 @@ void *sbrk(ptrdiff_t increment)
>
>   void init_mm(void)
>   {
> -
>       unsigned long start_pfn, max_pfn;
> -
>       printk("MM: Init\n");
>
>       arch_init_mm(&start_pfn, &max_pfn);
> diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
> index 174945e..a1cd3a9 100644
> --- a/extras/mini-os/sched.c
> +++ b/extras/mini-os/sched.c
> @@ -100,15 +100,19 @@ void schedule(void)
>           next = NULL;
>           MINIOS_TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp)
>           {
> +        	DEBUG("Checking thread : %s (runnable:%i)\n", thread->name, is_runnable(thread));
>               if (!is_runnable(thread) && thread->wakeup_time != 0LL)
>               {
> -                if (thread->wakeup_time <= now)
> +                if (thread->wakeup_time <= now) {
> +                	DEBUG("Wake thread : %s\n", thread->name);
>                       wake(thread);
> +                }
>                   else if (thread->wakeup_time < min_wakeup_time)
>                       min_wakeup_time = thread->wakeup_time;
>               }
>               if(is_runnable(thread))
>               {
> +            	DEBUG("Thread (%s) is runnable, put it next\n", thread->name);
>                   next = thread;
>                   /* Put this thread on the end of the list */
>                   MINIOS_TAILQ_REMOVE(&thread_list, thread, thread_list);
> @@ -145,6 +149,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data)
>       unsigned long flags;
>       /* Call architecture specific setup. */
>       thread = arch_create_thread(name, function, data);
> +    if(!thread)
> +    	BUG(); //For now, FIXME should just return NULL
> +
>       /* Not runable, not exited, not sleeping */
>       thread->flags = 0;
>       thread->wakeup_time = 0LL;
> diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c
> new file mode 100644
> index 0000000..4320241
> --- /dev/null
> +++ b/extras/mini-os/time.c
> @@ -0,0 +1,12 @@
> +void arch_init_time(void);
> +void arch_fini_time(void);
> +
> +void init_time(void)
> +{
> +	arch_init_time();
> +}
> +
> +void fini_time(void)
> +{
> +	arch_fini_time();
> +}
> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
> index 934f23b..8a99ee2 100644
> --- a/extras/mini-os/xenbus/xenbus.c
> +++ b/extras/mini-os/xenbus/xenbus.c
> @@ -27,6 +27,7 @@
>   #include <mini-os/wait.h>
>   #include <xen/io/xs_wire.h>
>   #include <mini-os/spinlock.h>
> +#include <mini-os/hypervisor.h>
>   #include <mini-os/xmalloc.h>
>
>   #define min(x,y) ({                       \
> @@ -43,6 +44,7 @@
>   #endif
>
>   static struct xenstore_domain_interface *xenstore_buf;
> +static uint32_t store_evtchn;
>   static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
>   DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
>
> @@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
>       return o_probe;
>   }
>
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn);
> +
>   /* Initialise xenbus. */
>   void init_xenbus(void)
>   {
>       int err;
>       DEBUG("init_xenbus called.\n");
> -    xenstore_buf = mfn_to_virt(start_info.store_mfn);
> +
> +    arch_init_xenbus(&xenstore_buf, &store_evtchn);
> +
>       create_thread("xenstore", xenbus_thread_func, NULL);
>       DEBUG("buf at %p.\n", xenstore_buf);
> -    err = bind_evtchn(start_info.store_evtchn,
> +    err = bind_evtchn(store_evtchn,
>   		      xenbus_evtchn_handler,
>                 NULL);
> -    unmask_evtchn(start_info.store_evtchn);
> -    printk("xenbus initialised on irq %d mfn %#lx\n",
> -	   err, start_info.store_mfn);
> +    unmask_evtchn(store_evtchn);
> +    printk("xenbus initialised on event %d\n", err);
>   }
>
>   void fini_xenbus(void)
> @@ -420,7 +425,7 @@ static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
>       xenstore_buf->req_prod += len;
>
>       /* Send evtchn to notify remote */
> -    notify_remote_via_evtchn(start_info.store_evtchn);
> +    notify_remote_via_evtchn(store_evtchn);
>   }
>
>   /* Send a mesasge to xenbus, in the same fashion as xb_write, and
> @@ -445,6 +450,7 @@ xenbus_msg_reply(int type,
>       remove_waiter(w, req_info[id].waitq);
>       wake(current);
>
> +    rmb();
>       rep = req_info[id].reply;
>       BUG_ON(rep->req_id != id);
>       release_xenbus_id(id);
>

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 0/7] mini-os: Preparing for ARM support
  2014-06-03  9:12   ` Julien Grall
@ 2014-06-04 16:06     ` Thomas Leonard
  2014-06-04 16:06       ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
                         ` (7 more replies)
  0 siblings, 8 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

This series is the initial part of Karim's ARM support, further broken up into
smaller patches. These patches do not actually add ARM support; they just
prepare the ground for later patches that do.

I also added a fix so that Mini-OS doesn't shut down immediately. This is
for x86 too, but I needed it because otherwise it's hard to test it.

Karim: I don't fully understand all of these; feel free to add more details (e.g.
to the rbm patch).

Karim Raslan (6):
  mini-os: Tidied up code
  mini-os: Moved events code under arch
  mini-os: Switched initial C entry point to arch_init
  mini-os: Moved arch-specific xenbus code under arch
  mini-os: Added rmb to xenbus code
  mini-os: Moved force_evtchn_callback to header

Thomas Leonard (1):
  mini-os: Fixed shutdown thread

 extras/mini-os/README                      |  7 +++--
 extras/mini-os/arch/x86/events.c           | 28 +++++++++++++++++
 extras/mini-os/arch/x86/setup.c            | 44 ++++++++++++++++++++++-----
 extras/mini-os/arch/x86/time.c             |  2 +-
 extras/mini-os/arch/x86/x86_32.S           |  2 +-
 extras/mini-os/arch/x86/x86_64.S           |  2 +-
 extras/mini-os/arch/x86/xenbus.c           | 10 ++++++
 extras/mini-os/console/console.c           |  2 +-
 extras/mini-os/events.c                    | 29 +++++-------------
 extras/mini-os/gntmap.c                    | 35 ++++++++++-----------
 extras/mini-os/hypervisor.c                | 20 +-----------
 extras/mini-os/include/hypervisor.h        |  1 -
 extras/mini-os/include/x86/arch_spinlock.h |  2 +-
 extras/mini-os/include/x86/os.h            | 19 ++++++++++--
 extras/mini-os/kernel.c                    | 49 ++++++++----------------------
 extras/mini-os/main.c                      |  2 +-
 extras/mini-os/sched.c                     |  3 ++
 extras/mini-os/xenbus/xenbus.c             | 20 +++++++-----
 18 files changed, 155 insertions(+), 122 deletions(-)
 create mode 100644 extras/mini-os/arch/x86/events.c
 create mode 100644 extras/mini-os/arch/x86/xenbus.c

-- 
2.0.0

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 1/7] mini-os: Fixed shutdown thread
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-04 16:06       ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
                         ` (6 subsequent siblings)
  7 siblings, 0 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

Before, it read "" and started a shutdown immediately. Now, it waits for
a non-empty value and then actually shuts down.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 extras/mini-os/kernel.c | 10 +++++++---
 extras/mini-os/main.c   |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index ea409f4..27e3c56 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -69,6 +69,8 @@ void setup_xen_features(void)
 __attribute__((weak)) void app_shutdown(unsigned reason)
 {
     printk("Shutdown requested: %d\n", reason);
+    struct sched_shutdown sched_shutdown = { .reason = reason };
+    HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
 }
 
 static void shutdown_thread(void *p)
@@ -76,12 +78,14 @@ static void shutdown_thread(void *p)
     const char *path = "control/shutdown";
     const char *token = path;
     xenbus_event_queue events = NULL;
-    char *shutdown, *err;
+    char *shutdown = NULL, *err;
     unsigned int shutdown_reason;
     xenbus_watch_path_token(XBT_NIL, path, token, &events);
-    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL)
+    while ((err = xenbus_read(XBT_NIL, path, &shutdown)) != NULL || !strcmp(shutdown, ""))
     {
         free(err);
+        free(shutdown);
+        shutdown = NULL;
         xenbus_wait_for_watch(&events);
     }
     err = xenbus_unwatch_path_token(XBT_NIL, path, token);
@@ -106,7 +110,7 @@ static void shutdown_thread(void *p)
 /* This should be overridden by the application we are linked against. */
 __attribute__((weak)) int app_main(start_info_t *si)
 {
-    printk("Dummy main: start_info=%p\n", si);
+    printk("kernel.c: dummy main: start_info=%p\n", si);
     return 0;
 }
 
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index 73eb6fb..aec0586 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -185,7 +185,7 @@ void _exit(int ret)
 
 int app_main(start_info_t *si)
 {
-    printk("Dummy main: start_info=%p\n", si);
+    printk("main.c: dummy main: start_info=%p\n", si);
     main_thread = create_thread("main", call_main, si);
     return 0;
 }
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 2/7] mini-os: Tidied up code
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
  2014-06-04 16:06       ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-04 16:22         ` Andrew Cooper
  2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
                         ` (5 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
[talex5@gmail.com: use __func__ in DEBUG macro]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/README                      |  7 ++++--
 extras/mini-os/arch/x86/time.c             |  2 +-
 extras/mini-os/console/console.c           |  2 +-
 extras/mini-os/events.c                    |  3 ++-
 extras/mini-os/gntmap.c                    | 35 ++++++++++++++----------------
 extras/mini-os/include/x86/arch_spinlock.h |  2 +-
 extras/mini-os/sched.c                     |  3 +++
 extras/mini-os/xenbus/xenbus.c             |  2 +-
 8 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/extras/mini-os/README b/extras/mini-os/README
index 710a303..bf49700 100644
--- a/extras/mini-os/README
+++ b/extras/mini-os/README
@@ -25,8 +25,11 @@ This includes:
 
 - to build it with much better libc support, see the stubdom/ directory
 
-- to start it do the following in domain0 (assuming xend is running)
-  # xm create domain_config
+- to start it do the following in domain0
+  # xm create domain_config # old style xend ( assuming xend is running )
+or
+  # xl create domain_config # using toolstack
+
 
 This starts the kernel and prints out a bunch of stuff and then once every
 second the system time.
diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
index 89bc382..2c8d033 100644
--- a/extras/mini-os/arch/x86/time.c
+++ b/extras/mini-os/arch/x86/time.c
@@ -212,7 +212,7 @@ void block_domain(s_time_t until)
 
 
 /*
- * Just a dummy 
+ * Just a dummy
  */
 static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
 {
diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
index 380f53c..5538bd4 100644
--- a/extras/mini-os/console/console.c
+++ b/extras/mini-os/console/console.c
@@ -124,7 +124,7 @@ void print(int direct, const char *fmt, va_list args)
     static char   buf[1024];
     
     (void)vsnprintf(buf, sizeof(buf), fmt, args);
- 
+
     if(direct)
     {
         (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 036b84b..2da9b01 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -138,7 +138,8 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
 	op.virq = virq;
 	op.vcpu = smp_processor_id();
 
-	if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op)) != 0 )
+	rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
+	if (rc != 0)
 	{
 		printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
 		return -1;
diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
index 22ed450..f6ab3ad 100644
--- a/extras/mini-os/gntmap.c
+++ b/extras/mini-os/gntmap.c
@@ -38,6 +38,15 @@
 #include <inttypes.h>
 #include <mini-os/gntmap.h>
 
+//#define GNTMAP_DEBUG
+#ifdef GNTMAP_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+
 #define DEFAULT_MAX_GRANTS 128
 
 struct gntmap_entry {
@@ -61,10 +70,8 @@ gntmap_find_free_entry(struct gntmap *map)
             return &map->entries[i];
     }
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_find_free_entry(map=%p): all %d entries full\n",
+    DEBUG("(map=%p): all %d entries full",
            map, map->nentries);
-#endif
     return NULL;
 }
 
@@ -83,9 +90,7 @@ gntmap_find_entry(struct gntmap *map, unsigned long addr)
 int
 gntmap_set_max_grants(struct gntmap *map, int count)
 {
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count);
-#endif
+    DEBUG("(map=%p, count=%d)", map, count);
 
     if (map->nentries != 0)
         return -EBUSY;
@@ -157,10 +162,8 @@ gntmap_munmap(struct gntmap *map, unsigned long start_address, int count)
     int i, rc;
     struct gntmap_entry *ent;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n",
+    DEBUG("(map=%p, start_address=%lx, count=%d)",
            map, start_address, count);
-#endif
 
     for (i = 0; i < count; i++) {
         ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i);
@@ -189,14 +192,12 @@ gntmap_map_grant_refs(struct gntmap *map,
     struct gntmap_entry *ent;
     int i;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", "
+    DEBUG("(map=%p, count=%" PRIu32 ", "
            "domids=%p [%" PRIu32 "...], domids_stride=%d, "
-           "refs=%p [%" PRIu32 "...], writable=%d)\n",
+           "refs=%p [%" PRIu32 "...], writable=%d)",
            map, count,
            domids, domids == NULL ? 0 : domids[0], domids_stride,
            refs, refs == NULL ? 0 : refs[0], writable);
-#endif
 
     (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS);
 
@@ -224,9 +225,7 @@ gntmap_map_grant_refs(struct gntmap *map,
 void
 gntmap_init(struct gntmap *map)
 {
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_init(map=%p)\n", map);
-#endif
+    DEBUG("(map=%p)", map);
     map->nentries = 0;
     map->entries = NULL;
 }
@@ -237,9 +236,7 @@ gntmap_fini(struct gntmap *map)
     struct gntmap_entry *ent;
     int i;
 
-#ifdef GNTMAP_DEBUG
-    printk("gntmap_fini(map=%p)\n", map);
-#endif
+    DEBUG("(map=%p)", map);
 
     for (i = 0; i < map->nentries; i++) {
         ent = &map->entries[i];
diff --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h
index c08b6f1..59f7b63 100644
--- a/extras/mini-os/include/x86/arch_spinlock.h
+++ b/extras/mini-os/include/x86/arch_spinlock.h
@@ -61,7 +61,7 @@
 
 static inline void _raw_spin_unlock(spinlock_t *lock)
 {
-	char oldval = 1;
+	char oldval = ARCH_SPIN_LOCK_UNLOCKED;
 	__asm__ __volatile__(
 		spin_unlock_string
 	);
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 5ac5c1c..174945e 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -85,6 +85,7 @@ void schedule(void)
         printk("Must not call schedule() from a callback\n");
         BUG();
     }
+
     if (flags) {
         printk("Must not call schedule() with IRQs disabled\n");
         BUG();
@@ -188,6 +189,8 @@ struct _reent *__getreent(void)
 	}
     }
 #endif
+#else
+#error Not implemented yet
 #endif
     return _reent;
 }
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index c5d9b02..934f23b 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -276,7 +276,7 @@ static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
 }
 
 static int nr_live_reqs;
-static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(req_lock);
 static DECLARE_WAIT_QUEUE_HEAD(req_wq);
 
 /* Release a xenbus identifier */
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 3/7] mini-os: Moved events code under arch
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
  2014-06-04 16:06       ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
  2014-06-04 16:06       ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-04 16:23         ` Julien Grall
  2014-06-06 13:57         ` Ian Campbell
  2014-06-04 16:06       ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
                         ` (4 subsequent siblings)
  7 siblings, 2 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/x86/events.c | 28 ++++++++++++++++++++++++++++
 extras/mini-os/events.c          | 26 ++++++--------------------
 2 files changed, 34 insertions(+), 20 deletions(-)
 create mode 100644 extras/mini-os/arch/x86/events.c

diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
new file mode 100644
index 0000000..87f8b77
--- /dev/null
+++ b/extras/mini-os/arch/x86/events.c
@@ -0,0 +1,28 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+
+#if defined(__x86_64__)
+char irqstack[2 * STACK_SIZE];
+
+static struct pda
+{
+    int irqcount;       /* offset 0 (used in x86_64.S) */
+    char *irqstackptr;  /*        8 */
+} cpu0_pda;
+#endif
+
+void arch_init_events(void) {
+#if defined(__x86_64__)
+    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
+    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
+    cpu0_pda.irqcount = -1;
+    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
+                                    & ~(STACK_SIZE - 1));
+#endif
+}
+
+void arch_fini_events(void) {
+#if defined(__x86_64__)
+    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
+#endif
+}
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 2da9b01..c2bda1a 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -167,44 +167,30 @@ evtchn_port_t bind_pirq(uint32_t pirq, int will_share,
 	return op.port;
 }
 
-#if defined(__x86_64__)
-char irqstack[2 * STACK_SIZE];
-
-static struct pda
-{
-    int irqcount;       /* offset 0 (used in x86_64.S) */
-    char *irqstackptr;  /*        8 */
-} cpu0_pda;
-#endif
-
+void arch_init_events(void);
 /*
  * Initially all events are without a handler and disabled
  */
 void init_events(void)
 {
     int i;
-#if defined(__x86_64__)
-    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
-    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
-    cpu0_pda.irqcount = -1;
-    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
-                                    & ~(STACK_SIZE - 1));
-#endif
+
     /* initialize event handler */
     for ( i = 0; i < NR_EVS; i++ )
 	{
         ev_actions[i].handler = default_handler;
         mask_evtchn(i);
     }
+
+    arch_init_events();
 }
 
+void arch_fini_events(void);
 void fini_events(void)
 {
     /* Dealloc all events */
     unbind_all_ports();
-#if defined(__x86_64__)
-    wrmsrl(0xc0000101, NULL); /* 0xc0000101 is MSR_GS_BASE */
-#endif
+    arch_fini_events();
 }
 
 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 4/7] mini-os: Switched initial C entry point to arch_init
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
                         ` (2 preceding siblings ...)
  2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-06 14:05         ` Ian Campbell
  2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
                         ` (3 subsequent siblings)
  7 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/x86/setup.c  | 44 ++++++++++++++++++++++++++++++++--------
 extras/mini-os/arch/x86/x86_32.S |  2 +-
 extras/mini-os/arch/x86/x86_64.S |  2 +-
 extras/mini-os/include/x86/os.h  |  2 --
 extras/mini-os/kernel.c          | 39 +++++------------------------------
 5 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 54046d3..58ede15 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -28,6 +28,7 @@
 
 #include <mini-os/os.h>
 #include <mini-os/lib.h> /* for printk, memcpy */
+#include <xen/xen.h>
 
 /*
  * Shared page for communicating with the hypervisor.
@@ -87,14 +88,40 @@ static inline void sse_init(void) {
 #define sse_init()
 #endif
 
+
+void start_kernel(void);
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
 void
 arch_init(start_info_t *si)
 {
+	static char hello[] = "Bootstrapping...\n";
+
+	(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
+
+	trap_init();
+
+	/* print out some useful information  */
+	printk("Xen Minimal OS!\n");
+	printk("  start_info: %p(VA)\n", si);
+	printk("    nr_pages: 0x%lx\n", si->nr_pages);
+	printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
+	printk("     pt_base: %p(VA)\n", (void *)si->pt_base);
+	printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
+	printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list);
+	printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
+	printk("     mod_len: %lu\n", si->mod_len);
+	printk("       flags: 0x%x\n", (unsigned int)si->flags);
+	printk("    cmd_line: %s\n",
+			si->cmd_line ? (const char *)si->cmd_line : "NULL");
+
 	/*Initialize floating point unit */
-        fpu_init();
+	fpu_init();
 
-        /* Initialize SSE */
-        sse_init();
+	/* Initialize SSE */
+	sse_init();
 
 	/* Copy the start_info struct to a globally-accessible area. */
 	/* WARN: don't do printk before here, it uses information from
@@ -118,12 +145,15 @@ arch_init(start_info_t *si)
 		(unsigned long)failsafe_callback, 0);
 #endif
 
-
+	start_kernel();
 }
 
 void
 arch_fini(void)
 {
+	/* Reset traps */
+	trap_fini();
+
 #ifdef __i386__
 	HYPERVISOR_set_callbacks(0, 0, 0, 0);
 #else
@@ -132,9 +162,7 @@ arch_fini(void)
 }
 
 void
-arch_print_info(void)
+arch_do_exit(void)
 {
-	printk("  stack:      %p-%p\n", stack, stack + sizeof(stack));
+	stack_walk();
 }
-
-
diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index fb3e30a..b9aa392 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -20,7 +20,7 @@ _start:
         lss stack_start,%esp
         andl $(~(__STACK_SIZE-1)), %esp
         push %esi 
-        call start_kernel
+        call arch_init
 
 stack_start:
 	.long stack+(2*__STACK_SIZE), __KERNEL_SS
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index f022eb3..df3469e 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -21,7 +21,7 @@ _start:
         movq stack_start(%rip),%rsp
         andq $(~(__STACK_SIZE-1)), %rsp
         movq %rsi,%rdi
-        call start_kernel
+        call arch_init
 
 stack_start:
         .quad stack+(2*__STACK_SIZE)
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index f193865..73b8297 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -64,8 +64,6 @@ extern shared_info_t *HYPERVISOR_shared_info;
 void trap_init(void);
 void trap_fini(void);
 
-void arch_init(start_info_t *si);
-void arch_print_info(void);
 void arch_fini(void);
 
 
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 27e3c56..1c1171a 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -114,40 +114,12 @@ __attribute__((weak)) int app_main(start_info_t *si)
     return 0;
 }
 
-/*
- * INITIAL C ENTRY POINT.
- */
-void start_kernel(start_info_t *si)
+void start_kernel(void)
 {
-    static char hello[] = "Bootstrapping...\n";
-
-    (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
-
-    arch_init(si);
-
-    trap_init();
-
-    /* print out some useful information  */
-    printk("Xen Minimal OS!\n");
-    printk("  start_info: %p(VA)\n", si);
-    printk("    nr_pages: 0x%lx\n", si->nr_pages);
-    printk("  shared_inf: 0x%08lx(MA)\n", si->shared_info);
-    printk("     pt_base: %p(VA)\n", (void *)si->pt_base); 
-    printk("nr_pt_frames: 0x%lx\n", si->nr_pt_frames);
-    printk("    mfn_list: %p(VA)\n", (void *)si->mfn_list); 
-    printk("   mod_start: 0x%lx(VA)\n", si->mod_start);
-    printk("     mod_len: %lu\n", si->mod_len); 
-    printk("       flags: 0x%x\n", (unsigned int)si->flags);
-    printk("    cmd_line: %s\n",  
-           si->cmd_line ? (const char *)si->cmd_line : "NULL");
-
     /* Set up events. */
     init_events();
-    
-    /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
-    __sti();
 
-    arch_print_info();
+    __sti();
 
     setup_xen_features();
 
@@ -201,13 +173,12 @@ void stop_kernel(void)
     /* Reset events. */
     fini_events();
 
-    /* Reset traps */
-    trap_fini();
-
     /* Reset arch details */
     arch_fini();
 }
 
+void arch_do_exit(void);
+
 /*
  * do_exit: This is called whenever an IRET fails in entry.S.
  * This will generally be because an application has got itself into
@@ -218,7 +189,7 @@ void stop_kernel(void)
 void do_exit(void)
 {
     printk("Do_exit called!\n");
-    stack_walk();
+    arch_do_exit();
     for( ;; )
     {
         struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
                         ` (3 preceding siblings ...)
  2014-06-04 16:06       ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-05 14:00         ` Julien Grall
  2014-06-06 14:07         ` Ian Campbell
  2014-06-04 16:06       ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
                         ` (2 subsequent siblings)
  7 siblings, 2 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/x86/xenbus.c | 10 ++++++++++
 extras/mini-os/xenbus/xenbus.c   | 17 +++++++++++------
 2 files changed, 21 insertions(+), 6 deletions(-)
 create mode 100644 extras/mini-os/arch/x86/xenbus.c

diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c
new file mode 100644
index 0000000..5cda78d
--- /dev/null
+++ b/extras/mini-os/arch/x86/xenbus.c
@@ -0,0 +1,10 @@
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/xmalloc.h>
+#include <xen/xen.h>
+#include <xen/io/xs_wire.h>
+
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {
+    *xenstore_buf = mfn_to_virt(start_info.store_mfn);
+    *store_evtchn = start_info.store_evtchn;
+}
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index 934f23b..d995020 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -27,6 +27,7 @@
 #include <mini-os/wait.h>
 #include <xen/io/xs_wire.h>
 #include <mini-os/spinlock.h>
+#include <mini-os/hypervisor.h>
 #include <mini-os/xmalloc.h>
 
 #define min(x,y) ({                       \
@@ -43,6 +44,7 @@
 #endif
 
 static struct xenstore_domain_interface *xenstore_buf;
+static uint32_t store_evtchn;
 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
 
@@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
     return o_probe;
 }
 
+void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn);
+
 /* Initialise xenbus. */
 void init_xenbus(void)
 {
     int err;
     DEBUG("init_xenbus called.\n");
-    xenstore_buf = mfn_to_virt(start_info.store_mfn);
+
+    arch_init_xenbus(&xenstore_buf, &store_evtchn);
+
     create_thread("xenstore", xenbus_thread_func, NULL);
     DEBUG("buf at %p.\n", xenstore_buf);
-    err = bind_evtchn(start_info.store_evtchn,
+    err = bind_evtchn(store_evtchn,
 		      xenbus_evtchn_handler,
               NULL);
-    unmask_evtchn(start_info.store_evtchn);
-    printk("xenbus initialised on irq %d mfn %#lx\n",
-	   err, start_info.store_mfn);
+    unmask_evtchn(store_evtchn);
+    printk("xenbus initialised on event %d\n", err);
 }
 
 void fini_xenbus(void)
@@ -420,7 +425,7 @@ static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
     xenstore_buf->req_prod += len;
 
     /* Send evtchn to notify remote */
-    notify_remote_via_evtchn(start_info.store_evtchn);
+    notify_remote_via_evtchn(store_evtchn);
 }
 
 /* Send a mesasge to xenbus, in the same fashion as xb_write, and
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
                         ` (4 preceding siblings ...)
  2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-05 13:55         ` Julien Grall
  2014-06-04 16:06       ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
  2014-06-04 16:12       ` [PATCH 0/7] mini-os: Preparing for ARM support Andrew Cooper
  7 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/xenbus/xenbus.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index d995020..8a99ee2 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -450,6 +450,7 @@ xenbus_msg_reply(int type,
     remove_waiter(w, req_info[id].waitq);
     wake(current);
 
+    rmb();
     rep = req_info[id].reply;
     BUG_ON(rep->req_id != id);
     release_xenbus_id(id);
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 7/7] mini-os: Moved force_evtchn_callback to header
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
                         ` (5 preceding siblings ...)
  2014-06-04 16:06       ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
@ 2014-06-04 16:06       ` Thomas Leonard
  2014-06-06 14:17         ` Ian Campbell
  2014-06-04 16:12       ` [PATCH 0/7] mini-os: Preparing for ARM support Andrew Cooper
  7 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-04 16:06 UTC (permalink / raw)
  To: xen-devel; +Cc: Thomas Leonard

From: Karim Raslan <karim.allah.ahmed@gmail.com>

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: separated from big ARM commit]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/hypervisor.c         | 20 +-------------------
 extras/mini-os/include/hypervisor.h |  1 -
 extras/mini-os/include/x86/os.h     | 17 +++++++++++++++++
 3 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..9c79d5d 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
     in_callback = 0;
 }
 
-void force_evtchn_callback(void)
-{
-    int save;
-    vcpu_info_t *vcpu;
-    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
-    save = vcpu->evtchn_upcall_mask;
-
-    while (vcpu->evtchn_upcall_pending) {
-        vcpu->evtchn_upcall_mask = 1;
-        barrier();
-        do_hypervisor_callback(NULL);
-        barrier();
-        vcpu->evtchn_upcall_mask = save;
-        barrier();
-    };
-}
-
 inline void mask_evtchn(uint32_t port)
 {
     shared_info_t *s = HYPERVISOR_shared_info;
@@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
               &vcpu_info->evtchn_pending_sel) )
     {
         vcpu_info->evtchn_upcall_pending = 1;
-        if ( !vcpu_info->evtchn_upcall_mask )
-            force_evtchn_callback();
+        force_evtchn_callback();
     }
 }
 
diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
index a62cb78..9e9cac8 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -35,7 +35,6 @@ extern union start_info_union start_info_union;
 #define start_info (start_info_union.start_info)
 
 /* hypervisor.c */
-void force_evtchn_callback(void);
 void do_hypervisor_callback(struct pt_regs *regs);
 void mask_evtchn(uint32_t port);
 void unmask_evtchn(uint32_t port);
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 73b8297..8eea1be 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -160,6 +160,23 @@ do {									\
  */
 typedef struct { volatile int counter; } atomic_t;
 
+static inline void force_evtchn_callback(void)
+{
+    int save;
+    vcpu_info_t *vcpu;
+    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+    save = vcpu->evtchn_upcall_mask;
+
+    while (vcpu->evtchn_upcall_pending) {
+        vcpu->evtchn_upcall_mask = 1;
+        barrier();
+        do_hypervisor_callback(NULL);
+        barrier();
+        vcpu->evtchn_upcall_mask = save;
+        barrier();
+    };
+}
+
 
 /************************** i386 *******************************/
 #ifdef __INSIDE_MINIOS__
-- 
2.0.0

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/7] mini-os: Preparing for ARM support
  2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
                         ` (6 preceding siblings ...)
  2014-06-04 16:06       ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
@ 2014-06-04 16:12       ` Andrew Cooper
  7 siblings, 0 replies; 44+ messages in thread
From: Andrew Cooper @ 2014-06-04 16:12 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On 04/06/14 17:06, Thomas Leonard wrote:
> This series is the initial part of Karim's ARM support, further broken up into
> smaller patches. These patches do not actually add ARM support; they just
> prepare the ground for later patches that do.
>
> I also added a fix so that Mini-OS doesn't shut down immediately. This is
> for x86 too, but I needed it because otherwise it's hard to test it.
>
> Karim: I don't fully understand all of these; feel free to add more details (e.g.
> to the rbm patch).

In future can you please start a new thread for each new series, rather
than hijacking a reply on the previous thread.

~Andrew

>
> Karim Raslan (6):
>   mini-os: Tidied up code
>   mini-os: Moved events code under arch
>   mini-os: Switched initial C entry point to arch_init
>   mini-os: Moved arch-specific xenbus code under arch
>   mini-os: Added rmb to xenbus code
>   mini-os: Moved force_evtchn_callback to header
>
> Thomas Leonard (1):
>   mini-os: Fixed shutdown thread
>
>  extras/mini-os/README                      |  7 +++--
>  extras/mini-os/arch/x86/events.c           | 28 +++++++++++++++++
>  extras/mini-os/arch/x86/setup.c            | 44 ++++++++++++++++++++++-----
>  extras/mini-os/arch/x86/time.c             |  2 +-
>  extras/mini-os/arch/x86/x86_32.S           |  2 +-
>  extras/mini-os/arch/x86/x86_64.S           |  2 +-
>  extras/mini-os/arch/x86/xenbus.c           | 10 ++++++
>  extras/mini-os/console/console.c           |  2 +-
>  extras/mini-os/events.c                    | 29 +++++-------------
>  extras/mini-os/gntmap.c                    | 35 ++++++++++-----------
>  extras/mini-os/hypervisor.c                | 20 +-----------
>  extras/mini-os/include/hypervisor.h        |  1 -
>  extras/mini-os/include/x86/arch_spinlock.h |  2 +-
>  extras/mini-os/include/x86/os.h            | 19 ++++++++++--
>  extras/mini-os/kernel.c                    | 49 ++++++++----------------------
>  extras/mini-os/main.c                      |  2 +-
>  extras/mini-os/sched.c                     |  3 ++
>  extras/mini-os/xenbus/xenbus.c             | 20 +++++++-----
>  18 files changed, 155 insertions(+), 122 deletions(-)
>  create mode 100644 extras/mini-os/arch/x86/events.c
>  create mode 100644 extras/mini-os/arch/x86/xenbus.c
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/7] mini-os: Tidied up code
  2014-06-04 16:06       ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
@ 2014-06-04 16:22         ` Andrew Cooper
  2014-06-05 10:24           ` Anil Madhavapeddy
  0 siblings, 1 reply; 44+ messages in thread
From: Andrew Cooper @ 2014-06-04 16:22 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On 04/06/14 17:06, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: separated from big ARM commit]
> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> [talex5@gmail.com: use __func__ in DEBUG macro]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/README                      |  7 ++++--
>  extras/mini-os/arch/x86/time.c             |  2 +-
>  extras/mini-os/console/console.c           |  2 +-
>  extras/mini-os/events.c                    |  3 ++-
>  extras/mini-os/gntmap.c                    | 35 ++++++++++++++----------------
>  extras/mini-os/include/x86/arch_spinlock.h |  2 +-
>  extras/mini-os/sched.c                     |  3 +++
>  extras/mini-os/xenbus/xenbus.c             |  2 +-
>  8 files changed, 30 insertions(+), 26 deletions(-)
>
> diff --git a/extras/mini-os/README b/extras/mini-os/README
> index 710a303..bf49700 100644
> --- a/extras/mini-os/README
> +++ b/extras/mini-os/README
> @@ -25,8 +25,11 @@ This includes:
>  
>  - to build it with much better libc support, see the stubdom/ directory
>  
> -- to start it do the following in domain0 (assuming xend is running)
> -  # xm create domain_config
> +- to start it do the following in domain0
> +  # xm create domain_config # old style xend ( assuming xend is running )
> +or
> +  # xl create domain_config # using toolstack
> +

Xend has been rm -rf'd from the codebase.  All new patches should drop
all references to it and just refer to xl.

>  
>  This starts the kernel and prints out a bunch of stuff and then once every
>  second the system time.
> diff --git a/extras/mini-os/arch/x86/time.c b/extras/mini-os/arch/x86/time.c
> index 89bc382..2c8d033 100644
> --- a/extras/mini-os/arch/x86/time.c
> +++ b/extras/mini-os/arch/x86/time.c
> @@ -212,7 +212,7 @@ void block_domain(s_time_t until)
>  
>  
>  /*
> - * Just a dummy 
> + * Just a dummy
>   */
>  static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
>  {
> diff --git a/extras/mini-os/console/console.c b/extras/mini-os/console/console.c
> index 380f53c..5538bd4 100644
> --- a/extras/mini-os/console/console.c
> +++ b/extras/mini-os/console/console.c
> @@ -124,7 +124,7 @@ void print(int direct, const char *fmt, va_list args)
>      static char   buf[1024];
>      
>      (void)vsnprintf(buf, sizeof(buf), fmt, args);
> - 
> +
>      if(direct)
>      {
>          (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
> diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> index 036b84b..2da9b01 100644
> --- a/extras/mini-os/events.c
> +++ b/extras/mini-os/events.c
> @@ -138,7 +138,8 @@ evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
>  	op.virq = virq;
>  	op.vcpu = smp_processor_id();
>  
> -	if ( (rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op)) != 0 )
> +	rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op);
> +	if (rc != 0)
>  	{
>  		printk("Failed to bind virtual IRQ %d with rc=%d\n", virq, rc);
>  		return -1;
> diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
> index 22ed450..f6ab3ad 100644
> --- a/extras/mini-os/gntmap.c
> +++ b/extras/mini-os/gntmap.c
> @@ -38,6 +38,15 @@
>  #include <inttypes.h>
>  #include <mini-os/gntmap.h>
>  
> +//#define GNTMAP_DEBUG
> +#ifdef GNTMAP_DEBUG
> +#define DEBUG(_f, _a...) \
> +    printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)

Is the "MINI_OS" prefix useful?  I suspect not so much.

~Andrew

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/7] mini-os: Moved events code under arch
  2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
@ 2014-06-04 16:23         ` Julien Grall
  2014-06-06 13:54           ` Ian Campbell
  2014-06-06 13:57         ` Ian Campbell
  1 sibling, 1 reply; 44+ messages in thread
From: Julien Grall @ 2014-06-04 16:23 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel, karim.allah.ahmed

Hi Thomas,

I'm not sure why you dropped everyone in cc (i.e Minios Maintainers &
Karim).

On 06/04/2014 05:06 PM, Thomas Leonard wrote:
> diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> index 2da9b01..c2bda1a 100644
> --- a/extras/mini-os/events.c
> +++ b/extras/mini-os/events.c


[..]

> +
> +    arch_init_events();
>  }
>  
> +void arch_fini_events(void);

It's better to define the prototype in an header so the compiler can
check if the function declaration is actually matching the prototype.

This will avoid error if someone decide to modify the function
declaration without modifying the call-site...

I'm planning to send a patch to enable -Wmissing-prototypes on the
hypervisor side. It might be a good idea to enable -Wmissing-prototypes
on mini-os.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/7] mini-os: Tidied up code
  2014-06-04 16:22         ` Andrew Cooper
@ 2014-06-05 10:24           ` Anil Madhavapeddy
  0 siblings, 0 replies; 44+ messages in thread
From: Anil Madhavapeddy @ 2014-06-05 10:24 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel, Thomas Leonard

On 4 Jun 2014, at 17:22, Andrew Cooper <Andrew.Cooper3@citrix.com> wrote:
>> diff --git a/extras/mini-os/gntmap.c b/extras/mini-os/gntmap.c
>> index 22ed450..f6ab3ad 100644
>> --- a/extras/mini-os/gntmap.c
>> +++ b/extras/mini-os/gntmap.c
>> @@ -38,6 +38,15 @@
>> #include <inttypes.h>
>> #include <mini-os/gntmap.h>
>> 
>> +//#define GNTMAP_DEBUG
>> +#ifdef GNTMAP_DEBUG
>> +#define DEBUG(_f, _a...) \
>> +    printk("MINI_OS(gntmap.c:%d): %s" _f "\n", __LINE__, __func__, ## _a)
> 
> Is the "MINI_OS" prefix useful?  I suspect not so much.

It's useful to distinguish the MiniOS console output from the application
libraries linked against it, since they all share the same console.

-anil

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-04 16:06       ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
@ 2014-06-05 13:55         ` Julien Grall
  2014-06-05 17:45           ` Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Julien Grall @ 2014-06-05 13:55 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel

Hi Thomas,

Thank you for the patch.

On 06/04/2014 05:06 PM, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: separated from big ARM commit]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/xenbus/xenbus.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
> index d995020..8a99ee2 100644
> --- a/extras/mini-os/xenbus/xenbus.c
> +++ b/extras/mini-os/xenbus/xenbus.c
> @@ -450,6 +450,7 @@ xenbus_msg_reply(int type,
>      remove_waiter(w, req_info[id].waitq);
>      wake(current);
>  
> +    rmb();

Could you explain in the commit message why this rmb is necessary?

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch
  2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
@ 2014-06-05 14:00         ` Julien Grall
  2014-06-06 14:07         ` Ian Campbell
  1 sibling, 0 replies; 44+ messages in thread
From: Julien Grall @ 2014-06-05 14:00 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel

Hi Thomas,

Thank you for the patch.

On 06/04/2014 05:06 PM, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: separated from big ARM commit]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/arch/x86/xenbus.c | 10 ++++++++++
>  extras/mini-os/xenbus/xenbus.c   | 17 +++++++++++------
>  2 files changed, 21 insertions(+), 6 deletions(-)
>  create mode 100644 extras/mini-os/arch/x86/xenbus.c
> 
> diff --git a/extras/mini-os/arch/x86/xenbus.c b/extras/mini-os/arch/x86/xenbus.c
> new file mode 100644
> index 0000000..5cda78d
> --- /dev/null
> +++ b/extras/mini-os/arch/x86/xenbus.c
> @@ -0,0 +1,10 @@
> +#include <mini-os/os.h>
> +#include <mini-os/mm.h>
> +#include <mini-os/xmalloc.h>
> +#include <xen/xen.h>
> +#include <xen/io/xs_wire.h>
> +
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn) {

The mini-os coding style requests the '{' on a newline for function
declaration.

> +    *xenstore_buf = mfn_to_virt(start_info.store_mfn);
> +    *store_evtchn = start_info.store_evtchn;
> +}
> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
> index 934f23b..d995020 100644
> --- a/extras/mini-os/xenbus/xenbus.c
> +++ b/extras/mini-os/xenbus/xenbus.c
> @@ -27,6 +27,7 @@
>  #include <mini-os/wait.h>
>  #include <xen/io/xs_wire.h>
>  #include <mini-os/spinlock.h>
> +#include <mini-os/hypervisor.h>
>  #include <mini-os/xmalloc.h>
>  
>  #define min(x,y) ({                       \
> @@ -43,6 +44,7 @@
>  #endif
>  
>  static struct xenstore_domain_interface *xenstore_buf;
> +static uint32_t store_evtchn;
>  static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
>  DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
>  
> @@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
>      return o_probe;
>  }
>  
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn);
> +

Likewise in the previous patch, this prototype should go in an header.
Maybe be include/xenbus.h?

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
                   ` (3 preceding siblings ...)
  2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
@ 2014-06-05 14:36 ` Oleksandr Tyshchenko
  2014-06-05 14:57   ` Samuel Thibault
  2014-06-05 17:31   ` Thomas Leonard
  4 siblings, 2 replies; 44+ messages in thread
From: Oleksandr Tyshchenko @ 2014-06-05 14:36 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, Stefano Stabellini, samuel.thibault


[-- Attachment #1.1: Type: text/plain, Size: 13283 bytes --]

Hi Thomas, all

Thank you,
it is very interesting for me since I am trying to port XEN stuff to
embedded OS and using Mini-OS
as example.

I tried to run Mini-OS as domU and I got a hypervisor crash at an early
initialization stage (

I took Mini-OS from github:
https://github.com/talex5/xen ("proposed" branch)
As I understand correctly this branch contains all necessary patches to
build
and verify Mini-OS on ARM (I so have thought because the last 4 commits
from this
branch correspond to patch series in current thread). Is it correct?

My configuration:
- hypervisor - XEN 4.4.0
- platform - ARM32
- dom0 - Linux Kernel 3.8
- domU - Mini-OS

/ # (d1) dtb_pointer : 87fff000
(XEN) Guest data abort: Translation fault at level 2
(XEN)     gva=7002e65c
(XEN)     gpa=000000007002e65c
(XEN)     size=2 sign=0 write=0 reg=1
(XEN)     eat=0 cm=0 s1ptw=0 dfsc=6
(XEN) dom1 IPA 0x000000007002e65c
(XEN) P2M @ 02840080 mfn:0xc2004
(XEN) 1ST[0x1] = 0x00400000c200367f
(XEN) 2ND[0x180] = 0x0000000000000000
(XEN) ----[ Xen-4.4.0  arm32  debug=y  Not tainted ]----
(XEN) CPU:    0
(XEN) PC:     8000d14c
(XEN) CPSR:   600001d3 MODE:32-bit Guest SVC
(XEN)      R0: 8001a22c R1: 8002b218 R2: 7002e65c R3: 7002e65c
(XEN)      R4: 87fff000 R5: 00000000 R6: 00000000 R7: 00000000
(XEN)      R8: 00000000 R9: 00000000 R10:00000000 R11:8001ff74 R12:deadbeef
(XEN) USR: SP: 00000000 LR: 00000000
(XEN) SVC: SP: 8001ff60 LR: 8000d468 SPSR:00000000
(XEN) ABT: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) UND: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) IRQ: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) FIQ: SP: 00000000 LR: c2c2c2c2 SPSR:00000000
(XEN) FIQ: R8: 00000000 R9: 00000000 R10:00000000 R11:00000000 R12:00000000
(XEN)
(XEN)      SCTLR: 00c50078
(XEN)        TCR: 00000000
(XEN)      TTBR0: 0000000080024000
(XEN)      TTBR1: 0000000000000000
(XEN)       IFAR: 00000000, IFSR: 00000000
(XEN)       DFAR: 00000000, DFSR: 00000000
(XEN)
(XEN)   VTCR_EL2: 80002558
(XEN)  VTTBR_EL2: 00020000c2004000
(XEN)
(XEN)  SCTLR_EL2: 30cd187f
(XEN)    HCR_EL2: 0000000000282835
(XEN)  TTBR0_EL2: 00000000fecdf000
(XEN)
(XEN)    ESR_EL2: 93810006
(XEN)  HPFAR_EL2: 00000000007002e0
(XEN)      HDFAR: 7002e65c
(XEN)      HIFAR: 00000000
(XEN)
(XEN) Guest stack trace from sp=8001ff60:
(XEN)    8002b218 8001a22c 80019324 8002b218 c2c2c2c2 8001ff8c 8001ff38
00000000
(XEN)    80022230 000003ff 00000000 80022230 00000000 00000000 800175bc
00000001
(XEN)    00000001 00000000 00000003 000003ff 8001ffbc 80017604 8001ffcc
8000d728
(XEN)    8001fffc 8001792c 8001a22c 87fff000 ffffffff 8002820c 00000000
87fff000
(XEN)    00007ff0 00000000 00000000 00000000 00080022 00000000 00000000
80008038
(XEN) domain_crash_sync called from traps.c:1573
(XEN) Domain 1 (vcpu#0) crashed on cpu#0:
(XEN) ----[ Xen-4.4.0  arm32  debug=y  Not tainted ]----
(XEN) CPU:    0
(XEN) PC:     8000d14c
(XEN) CPSR:   600001d3 MODE:32-bit Guest SVC
(XEN)      R0: 8001a22c R1: 8002b218 R2: 7002e65c R3: 7002e65c
(XEN)      R4: 87fff000 R5: 00000000 R6: 00000000 R7: 00000000
(XEN)      R8: 00000000 R9: 00000000 R10:00000000 R11:8001ff74 R12:deadbeef
(XEN) USR: SP: 00000000 LR: 00000000
(XEN) SVC: SP: 8001ff60 LR: 8000d468 SPSR:00000000
(XEN) ABT: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) UND: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) IRQ: SP: 00000000 LR: 00000000 SPSR:00000000
(XEN) FIQ: SP: 00000000 LR: c2c2c2c2 SPSR:00000000
(XEN) FIQ: R8: 00000000 R9: 00000000 R10:00000000 R11:00000000 R12:00000000
(XEN)
(XEN)      SCTLR: 00c50078
(XEN)        TCR: 00000000
(XEN)      TTBR0: 0000000080024000
(XEN)      TTBR1: 0000000000000000
(XEN)       IFAR: 00000000, IFSR: 00000000
(XEN)       DFAR: 00000000, DFSR: 00000000
(XEN)
(XEN)   VTCR_EL2: 80002558
(XEN)  VTTBR_EL2: 00020000c2004000
(XEN)
(XEN)  SCTLR_EL2: 30cd187f
(XEN)    HCR_EL2: 0000000000282835
(XEN)  TTBR0_EL2: 00000000fecdf000
(XEN)
(XEN)    ESR_EL2: 93810006
(XEN)  HPFAR_EL2: 00000000007002e0
(XEN)      HDFAR: 7002e65c
(XEN)      HIFAR: 00000000
(XEN)
(XEN) Guest stack trace from sp=8001ff60:
(XEN)    8002b218 8001a22c 80019324 8002b218 c2c2c2c2 8001ff8c 8001ff38
00000000
(XEN)    80022230 000003ff 00000000 80022230 00000000 00000000 800175bc
00000001
(XEN)    00000001 00000000 00000003 000003ff 8001ffbc 80017604 8001ffcc
8000d728
(XEN)    8001fffc 8001792c 8001a22c 87fff000 ffffffff 8002820c 00000000
87fff000
(XEN)    00007ff0 00000000 00000000 00000000 00080022 00000000 00000000
80008038
(XEN) mm.c:1192:d0 gnttab_mark_dirty not implemented yet

But the Mini-OS from "next" branch boots without crashes (I changed GIC
addresses only):

diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c
index 6b3fd93..ef567d2 100644
--- a/extras/mini-os/drivers/gic.c
+++ b/extras/mini-os/drivers/gic.c
@@ -184,6 +184,12 @@ void gic_init(void) {
             }
             gic.gicd_base = (char *) (long) fdt64_to_cpu(reg[0]);
             gic.gicc_base = (char *) (long) fdt64_to_cpu(reg[2]);
+            unsigned   cbar;
+            __asm__ __volatile__("mrc  p15, 4, %0, c15, c0, 0" :
"=r"(cbar));
+
+            gic.gicd_base = (char *) (cbar + 0x1000);
+            gic.gicc_base = (char *) (cbar + 0x2000);
+
             printk("Found GIC: gicd_base = %p, gicc_base = %p\n",
gic.gicd_base, gic.gicc_base);
             break;
         }


Also, could you, please, explain me some generic things about Mini-OS:
1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without
proper LIBC support will the Mini-OS to operate fully
(are there any restrictions?)
2. If yes, what should I do to build Mini-OS with proper LIBC support?
Unfortunately, it is not clear for me.


On Mon, Jun 2, 2014 at 8:49 PM, Thomas Leonard <talex5@gmail.com> wrote:

> This series is Karim's initial ARM support, broken up into smaller patches.
> I removed some debug code from the patch, fixed it to work on x86 again,
> and replaced memmove with a BSD-licensed version.
>
> I also added a fix so that Mini-OS doesn't shut down immediately. This is
> for x86 too, but I needed it because otherwise it's hard to test it.
>
> It's probably not worth worrying too much about the ARM support itself
> (there
> will be more patches coming shortly!) - the main thing is refactoring
> Mini-OS
> to support the new architecture.
>
> Karim Raslan (3):
>   mini-os: Tidied up code
>   mini-os: Initial commit to port minios to ARM
>   mini-os: Added FDT support on ARM
>
> Thomas Leonard (1):
>   mini-os: Fixed shutdown thread
>
>  extras/mini-os/ARM-TODO.txt                        |   19 +
>  extras/mini-os/COPYING                             |   27 +
>  extras/mini-os/Config.mk                           |    2 +
>  extras/mini-os/Makefile                            |   23 +
>  extras/mini-os/README                              |    7 +-
>  extras/mini-os/arch/arm/Makefile                   |   33 +
>  extras/mini-os/arch/arm/arch.mk                    |    6 +
>  extras/mini-os/arch/arm/arm32.S                    |  211 +++
>  extras/mini-os/arch/arm/divsi3.S                   |  404 ++++++
>  extras/mini-os/arch/arm/events.c                   |   24 +
>  extras/mini-os/arch/arm/hypercalls32.S             |   88 ++
>  extras/mini-os/arch/arm/ldivmod.S                  |   67 +
>  extras/mini-os/arch/arm/ldivmod_helper.c           |   66 +
>  extras/mini-os/arch/arm/minios-arm32.lds           |   73 +
>  extras/mini-os/arch/arm/mm.c                       |   44 +
>  extras/mini-os/arch/arm/qdivrem.c                  |  270 ++++
>  extras/mini-os/arch/arm/sched.c                    |   32 +
>  extras/mini-os/arch/arm/setup.c                    |   55 +
>  extras/mini-os/arch/arm/time.c                     |  232 +++
>  extras/mini-os/arch/arm/xenbus.c                   |   36 +
>  extras/mini-os/arch/x86/events.c                   |   28 +
>  extras/mini-os/arch/x86/setup.c                    |   44 +-
>  extras/mini-os/arch/x86/time.c                     |    6 +-
>  extras/mini-os/arch/x86/x86_32.S                   |    2 +-
>  extras/mini-os/arch/x86/x86_64.S                   |    2 +-
>  extras/mini-os/arch/x86/xenbus.c                   |   10 +
>  extras/mini-os/console/console.c                   |    4 +-
>  extras/mini-os/drivers/gic.c                       |  179 +++
>  extras/mini-os/events.c                            |   35 +-
>  extras/mini-os/gntmap.c                            |   34 +-
>  extras/mini-os/gnttab.c                            |    1 +
>  extras/mini-os/hypervisor.c                        |   20 +-
>  extras/mini-os/include/arm/arch_limits.h           |    9 +
>  extras/mini-os/include/arm/arch_mm.h               |   37 +
>  extras/mini-os/include/arm/arch_sched.h            |   22 +
>  extras/mini-os/include/arm/arch_spinlock.h         |   49 +
>  extras/mini-os/include/arm/hypercall-arm32.h       |  173 +++
>  extras/mini-os/include/arm/os.h                    |  314 +++++
>  extras/mini-os/include/arm/traps.h                 |   20 +
>  extras/mini-os/include/console.h                   |    1 +
>  extras/mini-os/include/fdt.h                       |   60 +
>  extras/mini-os/include/hypervisor.h                |   19 +-
>  extras/mini-os/include/lib.h                       |    4 +-
>  extras/mini-os/include/libfdt.h                    | 1478
> ++++++++++++++++++++
>  extras/mini-os/include/libfdt_env.h                |   37 +
>  extras/mini-os/include/mm.h                        |    2 +
>  extras/mini-os/include/types.h                     |   73 +-
>  extras/mini-os/include/x86/arch_mm.h               |    2 +
>  extras/mini-os/include/x86/arch_spinlock.h         |    2 +-
>  extras/mini-os/include/x86/os.h                    |   19 +-
>  .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |    1 +
>  extras/mini-os/kernel.c                            |   94 +-
>  extras/mini-os/lib/fdt/fdt.c                       |  222 +++
>  extras/mini-os/lib/fdt/fdt_empty_tree.c            |   84 ++
>  extras/mini-os/lib/fdt/fdt_ro.c                    |  574 ++++++++
>  extras/mini-os/lib/fdt/fdt_rw.c                    |  492 +++++++
>  extras/mini-os/lib/fdt/fdt_strerror.c              |   96 ++
>  extras/mini-os/lib/fdt/fdt_sw.c                    |  256 ++++
>  extras/mini-os/lib/fdt/fdt_wip.c                   |  118 ++
>  extras/mini-os/lib/fdt/libfdt_internal.h           |   95 ++
>  extras/mini-os/lib/memmove.c                       |   45 +
>  extras/mini-os/lib/string.c                        |   12 +
>  extras/mini-os/main.c                              |    2 +-
>  extras/mini-os/mm.c                                |    9 +-
>  extras/mini-os/sched.c                             |   12 +-
>  extras/mini-os/time.c                              |   12 +
>  extras/mini-os/xenbus/xenbus.c                     |   20 +-
>  67 files changed, 6410 insertions(+), 139 deletions(-)
>  create mode 100644 extras/mini-os/ARM-TODO.txt
>  create mode 100755 extras/mini-os/arch/arm/Makefile
>  create mode 100644 extras/mini-os/arch/arm/arch.mk
>  create mode 100644 extras/mini-os/arch/arm/arm32.S
>  create mode 100644 extras/mini-os/arch/arm/divsi3.S
>  create mode 100644 extras/mini-os/arch/arm/events.c
>  create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>  create mode 100644 extras/mini-os/arch/arm/ldivmod.S
>  create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
>  create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
>  create mode 100644 extras/mini-os/arch/arm/mm.c
>  create mode 100644 extras/mini-os/arch/arm/qdivrem.c
>  create mode 100644 extras/mini-os/arch/arm/sched.c
>  create mode 100644 extras/mini-os/arch/arm/setup.c
>  create mode 100644 extras/mini-os/arch/arm/time.c
>  create mode 100644 extras/mini-os/arch/arm/xenbus.c
>  create mode 100644 extras/mini-os/arch/x86/events.c
>  create mode 100644 extras/mini-os/arch/x86/xenbus.c
>  create mode 100644 extras/mini-os/drivers/gic.c
>  create mode 100644 extras/mini-os/include/arm/arch_limits.h
>  create mode 100644 extras/mini-os/include/arm/arch_mm.h
>  create mode 100644 extras/mini-os/include/arm/arch_sched.h
>  create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
>  create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
>  create mode 100644 extras/mini-os/include/arm/os.h
>  create mode 100644 extras/mini-os/include/arm/traps.h
>  create mode 100644 extras/mini-os/include/fdt.h
>  create mode 100644 extras/mini-os/include/libfdt.h
>  create mode 100644 extras/mini-os/include/libfdt_env.h
>  create mode 100644 extras/mini-os/lib/fdt/fdt.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_empty_tree.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_ro.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_rw.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_strerror.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_sw.c
>  create mode 100644 extras/mini-os/lib/fdt/fdt_wip.c
>  create mode 100644 extras/mini-os/lib/fdt/libfdt_internal.h
>  create mode 100644 extras/mini-os/lib/memmove.c
>  create mode 100644 extras/mini-os/time.c
>
> --
> 1.9.3
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
>



-- 

Oleksandr Tyshchenko | Embedded Dev
GlobalLogic
www.globallogic.com
<http://www.globallogic.com/>

[-- Attachment #1.2: Type: text/html, Size: 17558 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
@ 2014-06-05 14:57   ` Samuel Thibault
  2014-06-05 17:20     ` Oleksandr Tyshchenko
  2014-06-05 17:31   ` Thomas Leonard
  1 sibling, 1 reply; 44+ messages in thread
From: Samuel Thibault @ 2014-06-05 14:57 UTC (permalink / raw)
  To: Oleksandr Tyshchenko; +Cc: xen-devel, Thomas Leonard, Stefano Stabellini

Oleksandr Tyshchenko, le Thu 05 Jun 2014 17:36:05 +0300, a écrit :
> Also, could you, please, explain me some generic things about Mini-OS:
> 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without proper
> LIBC support will the Mini-OS to operate fully
> (are there any restrictions?)

It's not necessary to see mini-os booting, drivers working, and using
their interface. It is necessary to get the posix programming interface.

> 2. If yes, what should I do to build Mini-OS with proper LIBC support?

Most probably very little in mini-os, since the HAVE_LIBC code is very
portable. I however doen't know how much newlib supports the arm target.

Samuel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 14:57   ` Samuel Thibault
@ 2014-06-05 17:20     ` Oleksandr Tyshchenko
  0 siblings, 0 replies; 44+ messages in thread
From: Oleksandr Tyshchenko @ 2014-06-05 17:20 UTC (permalink / raw)
  To: Samuel Thibault, Oleksandr Tyshchenko, Thomas Leonard, xen-devel,
	Stefano Stabellini


[-- Attachment #1.1: Type: text/plain, Size: 973 bytes --]

Hi, Samuel

Thank you for clarifications


On Thu, Jun 5, 2014 at 5:57 PM, Samuel Thibault <
samuel.thibault@ens-lyon.org> wrote:

> Oleksandr Tyshchenko, le Thu 05 Jun 2014 17:36:05 +0300, a écrit :
> > Also, could you, please, explain me some generic things about Mini-OS:
> > 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without
> proper
> > LIBC support will the Mini-OS to operate fully
> > (are there any restrictions?)
>
> It's not necessary to see mini-os booting, drivers working, and using
> their interface. It is necessary to get the posix programming interface.
>
> > 2. If yes, what should I do to build Mini-OS with proper LIBC support?
>
> Most probably very little in mini-os, since the HAVE_LIBC code is very
> portable. I however doen't know how much newlib supports the arm target.
>
> Samuel
>



-- 

Oleksandr Tyshchenko | Embedded Dev
GlobalLogic
www.globallogic.com
<http://www.globallogic.com/>

[-- Attachment #1.2: Type: text/html, Size: 2995 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
  2014-06-05 14:57   ` Samuel Thibault
@ 2014-06-05 17:31   ` Thomas Leonard
  2014-06-05 18:07     ` Oleksandr Tyshchenko
  1 sibling, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-05 17:31 UTC (permalink / raw)
  To: Oleksandr Tyshchenko; +Cc: xen-devel, Stefano Stabellini, Samuel Thibault

On 5 June 2014 15:36, Oleksandr Tyshchenko
<oleksandr.tyshchenko@globallogic.com> wrote:
> Hi Thomas, all
>
> Thank you,
> it is very interesting for me since I am trying to port XEN stuff to
> embedded OS and using Mini-OS
> as example.
>
> I tried to run Mini-OS as domU and I got a hypervisor crash at an early
> initialization stage (
>
> I took Mini-OS from github:
> https://github.com/talex5/xen ("proposed" branch)
> As I understand correctly this branch contains all necessary patches to
> build
> and verify Mini-OS on ARM (I so have thought because the last 4 commits from
> this
> branch correspond to patch series in current thread). Is it correct?
>
> But the Mini-OS from "next" branch boots without crashes (I changed GIC
> addresses only):

Hi Oleksandr,

The "proposed" branch currently contain's only Karim Raslan's initial
ARM work. I have a series of patches on top of this (on the next
branch), but I was planning to get this initial support in first.

Possibly my "Fixed initialisation code" commit should be merged with
Karim's code into a single patch. On the other hand, it might be
clearer to keep them separate (especially for other people who have
built on Karim's original work, e.g. I see on github that Jonathan
Daugherty has a fork from there).

[...]

> Also, could you, please, explain me some generic things about Mini-OS:
> 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without proper
> LIBC support will the Mini-OS to operate fully
> (are there any restrictions?)

You only need HAVE_LIBC if you want to use your own libc. Without
HAVE_LIBC, minios provides its own versions of some basic functions
(memcmp, sprintf, etc). Mirage works without it, for example.

> 2. If yes, what should I do to build Mini-OS with proper LIBC support?
> Unfortunately, it is not clear for me.
>
>
> On Mon, Jun 2, 2014 at 8:49 PM, Thomas Leonard <talex5@gmail.com> wrote:
>>
>> This series is Karim's initial ARM support, broken up into smaller
>> patches.
>> I removed some debug code from the patch, fixed it to work on x86 again,
>> and replaced memmove with a BSD-licensed version.
>>
>> I also added a fix so that Mini-OS doesn't shut down immediately. This is
>> for x86 too, but I needed it because otherwise it's hard to test it.
>>
>> It's probably not worth worrying too much about the ARM support itself
>> (there
>> will be more patches coming shortly!) - the main thing is refactoring
>> Mini-OS
>> to support the new architecture.
>>
>> Karim Raslan (3):
>>   mini-os: Tidied up code
>>   mini-os: Initial commit to port minios to ARM
>>   mini-os: Added FDT support on ARM
>>
>> Thomas Leonard (1):
>>   mini-os: Fixed shutdown thread
>>
>>  extras/mini-os/ARM-TODO.txt                        |   19 +
>>  extras/mini-os/COPYING                             |   27 +
>>  extras/mini-os/Config.mk                           |    2 +
>>  extras/mini-os/Makefile                            |   23 +
>>  extras/mini-os/README                              |    7 +-
>>  extras/mini-os/arch/arm/Makefile                   |   33 +
>>  extras/mini-os/arch/arm/arch.mk                    |    6 +
>>  extras/mini-os/arch/arm/arm32.S                    |  211 +++
>>  extras/mini-os/arch/arm/divsi3.S                   |  404 ++++++
>>  extras/mini-os/arch/arm/events.c                   |   24 +
>>  extras/mini-os/arch/arm/hypercalls32.S             |   88 ++
>>  extras/mini-os/arch/arm/ldivmod.S                  |   67 +
>>  extras/mini-os/arch/arm/ldivmod_helper.c           |   66 +
>>  extras/mini-os/arch/arm/minios-arm32.lds           |   73 +
>>  extras/mini-os/arch/arm/mm.c                       |   44 +
>>  extras/mini-os/arch/arm/qdivrem.c                  |  270 ++++
>>  extras/mini-os/arch/arm/sched.c                    |   32 +
>>  extras/mini-os/arch/arm/setup.c                    |   55 +
>>  extras/mini-os/arch/arm/time.c                     |  232 +++
>>  extras/mini-os/arch/arm/xenbus.c                   |   36 +
>>  extras/mini-os/arch/x86/events.c                   |   28 +
>>  extras/mini-os/arch/x86/setup.c                    |   44 +-
>>  extras/mini-os/arch/x86/time.c                     |    6 +-
>>  extras/mini-os/arch/x86/x86_32.S                   |    2 +-
>>  extras/mini-os/arch/x86/x86_64.S                   |    2 +-
>>  extras/mini-os/arch/x86/xenbus.c                   |   10 +
>>  extras/mini-os/console/console.c                   |    4 +-
>>  extras/mini-os/drivers/gic.c                       |  179 +++
>>  extras/mini-os/events.c                            |   35 +-
>>  extras/mini-os/gntmap.c                            |   34 +-
>>  extras/mini-os/gnttab.c                            |    1 +
>>  extras/mini-os/hypervisor.c                        |   20 +-
>>  extras/mini-os/include/arm/arch_limits.h           |    9 +
>>  extras/mini-os/include/arm/arch_mm.h               |   37 +
>>  extras/mini-os/include/arm/arch_sched.h            |   22 +
>>  extras/mini-os/include/arm/arch_spinlock.h         |   49 +
>>  extras/mini-os/include/arm/hypercall-arm32.h       |  173 +++
>>  extras/mini-os/include/arm/os.h                    |  314 +++++
>>  extras/mini-os/include/arm/traps.h                 |   20 +
>>  extras/mini-os/include/console.h                   |    1 +
>>  extras/mini-os/include/fdt.h                       |   60 +
>>  extras/mini-os/include/hypervisor.h                |   19 +-
>>  extras/mini-os/include/lib.h                       |    4 +-
>>  extras/mini-os/include/libfdt.h                    | 1478
>> ++++++++++++++++++++
>>  extras/mini-os/include/libfdt_env.h                |   37 +
>>  extras/mini-os/include/mm.h                        |    2 +
>>  extras/mini-os/include/types.h                     |   73 +-
>>  extras/mini-os/include/x86/arch_mm.h               |    2 +
>>  extras/mini-os/include/x86/arch_spinlock.h         |    2 +-
>>  extras/mini-os/include/x86/os.h                    |   19 +-
>>  .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |    1 +
>>  extras/mini-os/kernel.c                            |   94 +-
>>  extras/mini-os/lib/fdt/fdt.c                       |  222 +++
>>  extras/mini-os/lib/fdt/fdt_empty_tree.c            |   84 ++
>>  extras/mini-os/lib/fdt/fdt_ro.c                    |  574 ++++++++
>>  extras/mini-os/lib/fdt/fdt_rw.c                    |  492 +++++++
>>  extras/mini-os/lib/fdt/fdt_strerror.c              |   96 ++
>>  extras/mini-os/lib/fdt/fdt_sw.c                    |  256 ++++
>>  extras/mini-os/lib/fdt/fdt_wip.c                   |  118 ++
>>  extras/mini-os/lib/fdt/libfdt_internal.h           |   95 ++
>>  extras/mini-os/lib/memmove.c                       |   45 +
>>  extras/mini-os/lib/string.c                        |   12 +
>>  extras/mini-os/main.c                              |    2 +-
>>  extras/mini-os/mm.c                                |    9 +-
>>  extras/mini-os/sched.c                             |   12 +-
>>  extras/mini-os/time.c                              |   12 +
>>  extras/mini-os/xenbus/xenbus.c                     |   20 +-
>>  67 files changed, 6410 insertions(+), 139 deletions(-)
>>  create mode 100644 extras/mini-os/ARM-TODO.txt
>>  create mode 100755 extras/mini-os/arch/arm/Makefile
>>  create mode 100644 extras/mini-os/arch/arm/arch.mk
>>  create mode 100644 extras/mini-os/arch/arm/arm32.S
>>  create mode 100644 extras/mini-os/arch/arm/divsi3.S
>>  create mode 100644 extras/mini-os/arch/arm/events.c
>>  create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>>  create mode 100644 extras/mini-os/arch/arm/ldivmod.S
>>  create mode 100644 extras/mini-os/arch/arm/ldivmod_helper.c
>>  create mode 100755 extras/mini-os/arch/arm/minios-arm32.lds
>>  create mode 100644 extras/mini-os/arch/arm/mm.c
>>  create mode 100644 extras/mini-os/arch/arm/qdivrem.c
>>  create mode 100644 extras/mini-os/arch/arm/sched.c
>>  create mode 100644 extras/mini-os/arch/arm/setup.c
>>  create mode 100644 extras/mini-os/arch/arm/time.c
>>  create mode 100644 extras/mini-os/arch/arm/xenbus.c
>>  create mode 100644 extras/mini-os/arch/x86/events.c
>>  create mode 100644 extras/mini-os/arch/x86/xenbus.c
>>  create mode 100644 extras/mini-os/drivers/gic.c
>>  create mode 100644 extras/mini-os/include/arm/arch_limits.h
>>  create mode 100644 extras/mini-os/include/arm/arch_mm.h
>>  create mode 100644 extras/mini-os/include/arm/arch_sched.h
>>  create mode 100755 extras/mini-os/include/arm/arch_spinlock.h
>>  create mode 100644 extras/mini-os/include/arm/hypercall-arm32.h
>>  create mode 100644 extras/mini-os/include/arm/os.h
>>  create mode 100644 extras/mini-os/include/arm/traps.h
>>  create mode 100644 extras/mini-os/include/fdt.h
>>  create mode 100644 extras/mini-os/include/libfdt.h
>>  create mode 100644 extras/mini-os/include/libfdt_env.h
>>  create mode 100644 extras/mini-os/lib/fdt/fdt.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_empty_tree.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_ro.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_rw.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_strerror.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_sw.c
>>  create mode 100644 extras/mini-os/lib/fdt/fdt_wip.c
>>  create mode 100644 extras/mini-os/lib/fdt/libfdt_internal.h
>>  create mode 100644 extras/mini-os/lib/memmove.c
>>  create mode 100644 extras/mini-os/time.c
>>
>> --
>> 1.9.3
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@lists.xen.org
>> http://lists.xen.org/xen-devel
>
>
>
>
> --
>
> Oleksandr Tyshchenko | Embedded Dev
> GlobalLogic
> www.globallogic.com



-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-05 13:55         ` Julien Grall
@ 2014-06-05 17:45           ` Thomas Leonard
  2014-06-06  4:59             ` karim.allah.ahmed
  0 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-05 17:45 UTC (permalink / raw)
  To: Karim Raslan; +Cc: xen-devel, Julien Grall

Hi Karim,

Do you remember what this rmb call is for? It's from your commit here:

https://github.com/KarimAllah/xen/commit/61e8edeb9eabdf575f6f8e7720d977f07d907579#diff-dd67cee31c935093d2c65298a1d5b267R455

https://github.com/KarimAllah/xen/blob/61e8edeb9eabdf575f6f8e7720d977f07d907579/extras/mini-os/xenbus/xenbus.c#L455

Also, if you have any information to add to the other commits, that
would be very useful:

https://github.com/talex5/xen/commits/sent-Jun-04



On 5 June 2014 14:55, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
> Thank you for the patch.
>
> On 06/04/2014 05:06 PM, Thomas Leonard wrote:
>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>
>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> [talex5@gmail.com: separated from big ARM commit]
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>> ---
>>  extras/mini-os/xenbus/xenbus.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
>> index d995020..8a99ee2 100644
>> --- a/extras/mini-os/xenbus/xenbus.c
>> +++ b/extras/mini-os/xenbus/xenbus.c
>> @@ -450,6 +450,7 @@ xenbus_msg_reply(int type,
>>      remove_waiter(w, req_info[id].waitq);
>>      wake(current);
>>
>> +    rmb();
>
> Could you explain in the commit message why this rmb is necessary?
>
> Regards,
>
> --
> Julien Grall



-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 17:31   ` Thomas Leonard
@ 2014-06-05 18:07     ` Oleksandr Tyshchenko
  2014-06-05 18:12       ` Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Oleksandr Tyshchenko @ 2014-06-05 18:07 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, Stefano Stabellini, Samuel Thibault


[-- Attachment #1.1: Type: text/plain, Size: 1596 bytes --]

> Hi Oleksandr,
>
> The "proposed" branch currently contain's only Karim Raslan's initial
> ARM work. I have a series of patches on top of this (on the next
> branch), but I was planning to get this initial support in first.
>
> Possibly my "Fixed initialisation code" commit should be merged with
> Karim's code into a single patch. On the other hand, it might be
> clearer to keep them separate (especially for other people who have
> built on Karim's original work, e.g. I see on github that Jonathan
> Daugherty has a fork from there).
>

I have applied your commit "Fixed initialisation code" on top of "proposed"
branch -> Mini-OS boots without crashes
and works as expected. It is very important commit!)

I have only one question. Why do you use those addresses for GIC for now:

    gic.gicd_base = (char *)0x2c001000ULL;
    gic.gicc_base = (char *)0x2c002000ULL;

With this I have a hypervisor crash(

I let the Mini-OS to read them from cpu regs. And in my case they are:
- 0x48211000
- 0x48212000


>
> > Also, could you, please, explain me some generic things about Mini-OS:
> > 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without
> proper
> > LIBC support will the Mini-OS to operate fully
> > (are there any restrictions?)
>
> You only need HAVE_LIBC if you want to use your own libc. Without
> HAVE_LIBC, minios provides its own versions of some basic functions
> (memcmp, sprintf, etc). Mirage works without it, for example.
>

OK. It is clear.
Thank you.

-- 

Oleksandr Tyshchenko | Embedded Dev
GlobalLogic
www.globallogic.com
<http://www.globallogic.com/>

[-- Attachment #1.2: Type: text/html, Size: 3865 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 18:07     ` Oleksandr Tyshchenko
@ 2014-06-05 18:12       ` Thomas Leonard
  2014-06-05 18:21         ` Oleksandr Tyshchenko
  0 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-05 18:12 UTC (permalink / raw)
  To: Oleksandr Tyshchenko; +Cc: xen-devel, Stefano Stabellini, Samuel Thibault

On 5 June 2014 19:07, Oleksandr Tyshchenko
<oleksandr.tyshchenko@globallogic.com> wrote:
>
>> Hi Oleksandr,
>>
>> The "proposed" branch currently contain's only Karim Raslan's initial
>> ARM work. I have a series of patches on top of this (on the next
>> branch), but I was planning to get this initial support in first.
>>
>> Possibly my "Fixed initialisation code" commit should be merged with
>> Karim's code into a single patch. On the other hand, it might be
>> clearer to keep them separate (especially for other people who have
>> built on Karim's original work, e.g. I see on github that Jonathan
>> Daugherty has a fork from there).
>
>
> I have applied your commit "Fixed initialisation code" on top of "proposed"
> branch -> Mini-OS boots without crashes
> and works as expected. It is very important commit!)
>
> I have only one question. Why do you use those addresses for GIC for now:
>
>     gic.gicd_base = (char *)0x2c001000ULL;
>     gic.gicc_base = (char *)0x2c002000ULL;

The commit "Get GIC addresses from FDT" should fix that for you.

> With this I have a hypervisor crash(
>
> I let the Mini-OS to read them from cpu regs. And in my case they are:
> - 0x48211000
> - 0x48212000
>
>>
>>
>> > Also, could you, please, explain me some generic things about Mini-OS:
>> > 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without
>> > proper
>> > LIBC support will the Mini-OS to operate fully
>> > (are there any restrictions?)
>>
>> You only need HAVE_LIBC if you want to use your own libc. Without
>> HAVE_LIBC, minios provides its own versions of some basic functions
>> (memcmp, sprintf, etc). Mirage works without it, for example.
>
>
> OK. It is clear.
> Thank you.
>
> --
>
> Oleksandr Tyshchenko | Embedded Dev
> GlobalLogic
> www.globallogic.com



-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 0/4] mini-os: initial ARM support
  2014-06-05 18:12       ` Thomas Leonard
@ 2014-06-05 18:21         ` Oleksandr Tyshchenko
  0 siblings, 0 replies; 44+ messages in thread
From: Oleksandr Tyshchenko @ 2014-06-05 18:21 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, Stefano Stabellini, Samuel Thibault


[-- Attachment #1.1: Type: text/plain, Size: 2289 bytes --]

I will keep it in mind.
Thank you.


On Thu, Jun 5, 2014 at 9:12 PM, Thomas Leonard <talex5@gmail.com> wrote:

> On 5 June 2014 19:07, Oleksandr Tyshchenko
> <oleksandr.tyshchenko@globallogic.com> wrote:
> >
> >> Hi Oleksandr,
> >>
> >> The "proposed" branch currently contain's only Karim Raslan's initial
> >> ARM work. I have a series of patches on top of this (on the next
> >> branch), but I was planning to get this initial support in first.
> >>
> >> Possibly my "Fixed initialisation code" commit should be merged with
> >> Karim's code into a single patch. On the other hand, it might be
> >> clearer to keep them separate (especially for other people who have
> >> built on Karim's original work, e.g. I see on github that Jonathan
> >> Daugherty has a fork from there).
> >
> >
> > I have applied your commit "Fixed initialisation code" on top of
> "proposed"
> > branch -> Mini-OS boots without crashes
> > and works as expected. It is very important commit!)
> >
> > I have only one question. Why do you use those addresses for GIC for now:
> >
> >     gic.gicd_base = (char *)0x2c001000ULL;
> >     gic.gicc_base = (char *)0x2c002000ULL;
>
> The commit "Get GIC addresses from FDT" should fix that for you.
>
> > With this I have a hypervisor crash(
> >
> > I let the Mini-OS to read them from cpu regs. And in my case they are:
> > - 0x48211000
> > - 0x48212000
> >
> >>
> >>
> >> > Also, could you, please, explain me some generic things about Mini-OS:
> >> > 1. Is HAVE_LIBC a necessary config? I mean if I build Mini-OS without
> >> > proper
> >> > LIBC support will the Mini-OS to operate fully
> >> > (are there any restrictions?)
> >>
> >> You only need HAVE_LIBC if you want to use your own libc. Without
> >> HAVE_LIBC, minios provides its own versions of some basic functions
> >> (memcmp, sprintf, etc). Mirage works without it, for example.
> >
> >
> > OK. It is clear.
> > Thank you.
> >
> > --
> >
> > Oleksandr Tyshchenko | Embedded Dev
> > GlobalLogic
> > www.globallogic.com
>
>
>
> --
> Dr Thomas Leonard        http://0install.net/
> GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
> GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA
>



-- 

Oleksandr Tyshchenko | Embedded Dev
GlobalLogic
www.globallogic.com
<http://www.globallogic.com/>

[-- Attachment #1.2: Type: text/html, Size: 4915 bytes --]

[-- Attachment #2: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-05 17:45           ` Thomas Leonard
@ 2014-06-06  4:59             ` karim.allah.ahmed
  2014-06-06 14:15               ` Ian Campbell
  0 siblings, 1 reply; 44+ messages in thread
From: karim.allah.ahmed @ 2014-06-06  4:59 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, Julien Grall

Hi,

Interestingly I find it very difficult to remember any of this code
since It was done during Christmas like 6 months ago :)

In any case, by looking at the patch it seems like rmb was required to
make sure that the reply message is visible to the current processor
when this thread wakes up and starts reading it.

I'll have a look at the other patches and put some comments there as well.

Regards.

On Thu, Jun 5, 2014 at 6:45 PM, Thomas Leonard <talex5@gmail.com> wrote:
> Hi Karim,
>
> Do you remember what this rmb call is for? It's from your commit here:
>
> https://github.com/KarimAllah/xen/commit/61e8edeb9eabdf575f6f8e7720d977f07d907579#diff-dd67cee31c935093d2c65298a1d5b267R455
>
> https://github.com/KarimAllah/xen/blob/61e8edeb9eabdf575f6f8e7720d977f07d907579/extras/mini-os/xenbus/xenbus.c#L455
>
> Also, if you have any information to add to the other commits, that
> would be very useful:
>
> https://github.com/talex5/xen/commits/sent-Jun-04
>
>
>
> On 5 June 2014 14:55, Julien Grall <julien.grall@linaro.org> wrote:
>> Hi Thomas,
>>
>> Thank you for the patch.
>>
>> On 06/04/2014 05:06 PM, Thomas Leonard wrote:
>>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>>
>>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>>> [talex5@gmail.com: separated from big ARM commit]
>>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>>> ---
>>>  extras/mini-os/xenbus/xenbus.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
>>> index d995020..8a99ee2 100644
>>> --- a/extras/mini-os/xenbus/xenbus.c
>>> +++ b/extras/mini-os/xenbus/xenbus.c
>>> @@ -450,6 +450,7 @@ xenbus_msg_reply(int type,
>>>      remove_waiter(w, req_info[id].waitq);
>>>      wake(current);
>>>
>>> +    rmb();
>>
>> Could you explain in the commit message why this rmb is necessary?
>>
>> Regards,
>>
>> --
>> Julien Grall
>
>
>
> --
> Dr Thomas Leonard        http://0install.net/
> GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
> GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA



-- 
Karim Allah Ahmed.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] mini-os: Added FDT support on ARM
  2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
@ 2014-06-06 13:51   ` Ian Campbell
  0 siblings, 0 replies; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 13:51 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, stefano.stabellini, samuel.thibault

On Mon, 2014-06-02 at 18:49 +0100, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>

I don't see this patch in the second batch of 7 patches, even though
there appears to be some overlap? I'm a bit confused as to what the
relationship between this 4 patch series and that 7 patch one is.

If they are separate (but related) series then git send-email
--subject-prefix='PATCH FOO' where FOO is some short descriptive tag
might help. For a new revision you should also use --reroll-count=N to
add the vN to the subject too.

Anyway, on to this patch...

WRT the subject, "FDT support" seems to mean "add the libfdt library",
rather than say, "consume an fdt on boot" or anything? In that case I
think "import libfdt" would be a better title.

You also add memmove.c, which should be mentioned somewhere.

Since this is importing a bunch of code from elsewhere please can you
mention the provenance (tree, website, ideally a revision) of this code
in the commit message so we know where to look for updates etc in the
future.

Ian.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/7] mini-os: Moved events code under arch
  2014-06-04 16:23         ` Julien Grall
@ 2014-06-06 13:54           ` Ian Campbell
  0 siblings, 0 replies; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 13:54 UTC (permalink / raw)
  To: Julien Grall; +Cc: xen-devel, Thomas Leonard

On Wed, 2014-06-04 at 17:23 +0100, Julien Grall wrote:
> Hi Thomas,
> 
> I'm not sure why you dropped everyone in cc (i.e Minios Maintainers &
> Karim).
> 
> On 06/04/2014 05:06 PM, Thomas Leonard wrote:
> > diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> > index 2da9b01..c2bda1a 100644
> > --- a/extras/mini-os/events.c
> > +++ b/extras/mini-os/events.c
> 
> 
> [..]
> 
> > +
> > +    arch_init_events();
> >  }
> >  
> > +void arch_fini_events(void);
> 
> It's better to define the prototype in an header so the compiler can
> check if the function declaration is actually matching the prototype.
> 
> This will avoid error if someone decide to modify the function
> declaration without modifying the call-site...
> 
> I'm planning to send a patch to enable -Wmissing-prototypes on the
> hypervisor side. It might be a good idea to enable -Wmissing-prototypes
> on mini-os.

It's a good idea but not a prerequisite for this series IMHO, although
any new cross module functions should have prototypes in headers not .c
files regardless.

Ian.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/7] mini-os: Moved events code under arch
  2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
  2014-06-04 16:23         ` Julien Grall
@ 2014-06-06 13:57         ` Ian Campbell
  1 sibling, 0 replies; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 13:57 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On Wed, 2014-06-04 at 17:06 +0100, Thomas Leonard wrote:
>  void init_events(void)
>  {
>      int i;
> -#if defined(__x86_64__)
> -    asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
> -    wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
> -    cpu0_pda.irqcount = -1;
> -    cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE)
> -                                    & ~(STACK_SIZE - 1));
> -#endif
> +
>      /* initialize event handler */
>      for ( i = 0; i < NR_EVS; i++ )
>  	{
>          ev_actions[i].handler = default_handler;
>          mask_evtchn(i);
>      }
> +
> +    arch_init_events();


I haven't actually validated that the code which has moved is unchanged,
I will take it on trust if you write in the commit message that this is
all code motion.

As well as the code motion this also changes the ordering of the arch
setup and this other loop. If that is deliberate please can you mention
it in the commit log as an exception to the pure code motion statement.

Other than that and the placement of prototypes (which as discussed
should be in a header) this looks good to me.

Ian.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/7] mini-os: Switched initial C entry point to arch_init
  2014-06-04 16:06       ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
@ 2014-06-06 14:05         ` Ian Campbell
  0 siblings, 0 replies; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 14:05 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On Wed, 2014-06-04 at 17:06 +0100, Thomas Leonard wrote:

As well as movign the initial C entry point this also seems to do a few
other things. Like refactoring arch cleanup in a similar way and
something going on with arch_print_info which I don't quite follow
(maybe it is just being deleted?).

Also this has the same issue with the prototypes being in the c files
instead of a header.

> -    
> -    /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
> -    __sti();
>  
> -    arch_print_info();
> +    __sti();

You've dropped what looks like a useful (if a bit SHOUTY!) comment here.

Ian.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch
  2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
  2014-06-05 14:00         ` Julien Grall
@ 2014-06-06 14:07         ` Ian Campbell
  1 sibling, 0 replies; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 14:07 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On Wed, 2014-06-04 at 17:06 +0100, Thomas Leonard wrote:
> @@ -325,20 +327,23 @@ static int allocate_xenbus_id(void)
>      return o_probe;
>  }
>  
> +void arch_init_xenbus(struct xenstore_domain_interface **xenstore_buf, uint32_t *store_evtchn);

Another one which should be in a header.

I think I shall stop mentioning these and assume that you'll audit all
of the patches.

The rest looks good, thankjs.

Ian.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-06  4:59             ` karim.allah.ahmed
@ 2014-06-06 14:15               ` Ian Campbell
  2014-06-06 15:10                 ` Samuel Thibault
  0 siblings, 1 reply; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 14:15 UTC (permalink / raw)
  To: karim.allah.ahmed
  Cc: xen-devel, Thomas Leonard, Julien Grall, Samuel Thibault

On Fri, 2014-06-06 at 05:59 +0100, karim.allah.ahmed@gmail.com wrote:
> In any case, by looking at the patch it seems like rmb was required to
> make sure that the reply message is visible to the current processor
> when this thread wakes up and starts reading it.

Can we assume (or arrange) that schedule() gives us this guarantee? Do
we want to?

I don't think the current schedule() common code guarantees this, and
obviously the x86 arch code doesn't care. Someone should decide...

> 
> I'll have a look at the other patches and put some comments there as well.
> 
> Regards.
> 
> On Thu, Jun 5, 2014 at 6:45 PM, Thomas Leonard <talex5@gmail.com> wrote:
> > Hi Karim,
> >
> > Do you remember what this rmb call is for? It's from your commit here:
> >
> > https://github.com/KarimAllah/xen/commit/61e8edeb9eabdf575f6f8e7720d977f07d907579#diff-dd67cee31c935093d2c65298a1d5b267R455
> >
> > https://github.com/KarimAllah/xen/blob/61e8edeb9eabdf575f6f8e7720d977f07d907579/extras/mini-os/xenbus/xenbus.c#L455
> >
> > Also, if you have any information to add to the other commits, that
> > would be very useful:
> >
> > https://github.com/talex5/xen/commits/sent-Jun-04
> >
> >
> >
> > On 5 June 2014 14:55, Julien Grall <julien.grall@linaro.org> wrote:
> >> Hi Thomas,
> >>
> >> Thank you for the patch.
> >>
> >> On 06/04/2014 05:06 PM, Thomas Leonard wrote:
> >>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> >>>
> >>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> >>> [talex5@gmail.com: separated from big ARM commit]
> >>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> >>> ---
> >>>  extras/mini-os/xenbus/xenbus.c | 1 +
> >>>  1 file changed, 1 insertion(+)
> >>>
> >>> diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
> >>> index d995020..8a99ee2 100644
> >>> --- a/extras/mini-os/xenbus/xenbus.c
> >>> +++ b/extras/mini-os/xenbus/xenbus.c
> >>> @@ -450,6 +450,7 @@ xenbus_msg_reply(int type,
> >>>      remove_waiter(w, req_info[id].waitq);
> >>>      wake(current);
> >>>
> >>> +    rmb();
> >>
> >> Could you explain in the commit message why this rmb is necessary?
> >>
> >> Regards,
> >>
> >> --
> >> Julien Grall
> >
> >
> >
> > --
> > Dr Thomas Leonard        http://0install.net/
> > GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
> > GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA
> 
> 
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 7/7] mini-os: Moved force_evtchn_callback to header
  2014-06-04 16:06       ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
@ 2014-06-06 14:17         ` Ian Campbell
  2014-06-09 11:54           ` Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 14:17 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel

On Wed, 2014-06-04 at 17:06 +0100, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>

Why is this being done?

> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: separated from big ARM commit]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/hypervisor.c         | 20 +-------------------
>  extras/mini-os/include/hypervisor.h |  1 -
>  extras/mini-os/include/x86/os.h     | 17 +++++++++++++++++
>  3 files changed, 18 insertions(+), 20 deletions(-)
> 
> diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
> index b4688a0..9c79d5d 100644
> --- a/extras/mini-os/hypervisor.c
> +++ b/extras/mini-os/hypervisor.c
> @@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
>      in_callback = 0;
>  }
>  
> -void force_evtchn_callback(void)
> -{
> -    int save;
> -    vcpu_info_t *vcpu;
> -    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> -    save = vcpu->evtchn_upcall_mask;
> -
> -    while (vcpu->evtchn_upcall_pending) {
> -        vcpu->evtchn_upcall_mask = 1;
> -        barrier();
> -        do_hypervisor_callback(NULL);
> -        barrier();
> -        vcpu->evtchn_upcall_mask = save;
> -        barrier();
> -    };
> -}
> -
>  inline void mask_evtchn(uint32_t port)
>  {
>      shared_info_t *s = HYPERVISOR_shared_info;
> @@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
>                &vcpu_info->evtchn_pending_sel) )
>      {
>          vcpu_info->evtchn_upcall_pending = 1;
> -        if ( !vcpu_info->evtchn_upcall_mask )
> -            force_evtchn_callback();
> +        force_evtchn_callback();

If this is something to do with the code motion then I'm not sure what,
it certainly needs to be explained somewhere.

>      }
>  }
>  
> diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
> index a62cb78..9e9cac8 100644
> --- a/extras/mini-os/include/hypervisor.h
> +++ b/extras/mini-os/include/hypervisor.h
> @@ -35,7 +35,6 @@ extern union start_info_union start_info_union;
>  #define start_info (start_info_union.start_info)
>  
>  /* hypervisor.c */
> -void force_evtchn_callback(void);
>  void do_hypervisor_callback(struct pt_regs *regs);
>  void mask_evtchn(uint32_t port);
>  void unmask_evtchn(uint32_t port);
> diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
> index 73b8297..8eea1be 100644
> --- a/extras/mini-os/include/x86/os.h
> +++ b/extras/mini-os/include/x86/os.h
> @@ -160,6 +160,23 @@ do {									\
>   */
>  typedef struct { volatile int counter; } atomic_t;
>  
> +static inline void force_evtchn_callback(void)
> +{
> +    int save;
> +    vcpu_info_t *vcpu;
> +    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> +    save = vcpu->evtchn_upcall_mask;
> +
> +    while (vcpu->evtchn_upcall_pending) {
> +        vcpu->evtchn_upcall_mask = 1;
> +        barrier();
> +        do_hypervisor_callback(NULL);
> +        barrier();
> +        vcpu->evtchn_upcall_mask = save;
> +        barrier();
> +    };
> +}
> +
>  
>  /************************** i386 *******************************/
>  #ifdef __INSIDE_MINIOS__

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-06 14:15               ` Ian Campbell
@ 2014-06-06 15:10                 ` Samuel Thibault
  2014-06-06 16:40                   ` Ian Campbell
  0 siblings, 1 reply; 44+ messages in thread
From: Samuel Thibault @ 2014-06-06 15:10 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Thomas Leonard, Julien Grall, xen-devel

Ian Campbell, le Fri 06 Jun 2014 15:15:42 +0100, a écrit :
> On Fri, 2014-06-06 at 05:59 +0100, karim.allah.ahmed@gmail.com wrote:
> > In any case, by looking at the patch it seems like rmb was required to
> > make sure that the reply message is visible to the current processor
> > when this thread wakes up and starts reading it.
> 
> Can we assume (or arrange) that schedule() gives us this guarantee? Do
> we want to?

I'd tend to think something like that, yes. More precisely, thread
wait/wake primitives usually provide a barrier: events before the wake
are supposed to complete before the wait returns. So both should have a
memory barrier.

Samuel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-06 15:10                 ` Samuel Thibault
@ 2014-06-06 16:40                   ` Ian Campbell
  2014-06-09 13:56                     ` Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Ian Campbell @ 2014-06-06 16:40 UTC (permalink / raw)
  To: Samuel Thibault; +Cc: Thomas Leonard, Julien Grall, xen-devel

On Fri, 2014-06-06 at 17:10 +0200, Samuel Thibault wrote:
> Ian Campbell, le Fri 06 Jun 2014 15:15:42 +0100, a écrit :
> > On Fri, 2014-06-06 at 05:59 +0100, karim.allah.ahmed@gmail.com wrote:
> > > In any case, by looking at the patch it seems like rmb was required to
> > > make sure that the reply message is visible to the current processor
> > > when this thread wakes up and starts reading it.
> > 
> > Can we assume (or arrange) that schedule() gives us this guarantee? Do
> > we want to?
> 
> I'd tend to think something like that, yes. More precisely, thread
> wait/wake primitives usually provide a barrier: events before the wake
> are supposed to complete before the wait returns. So both should have a
> memory barrier.

Makes sense to me.

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 7/7] mini-os: Moved force_evtchn_callback to header
  2014-06-06 14:17         ` Ian Campbell
@ 2014-06-09 11:54           ` Thomas Leonard
  0 siblings, 0 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-09 11:54 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel

On 6 June 2014 15:17, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-06-04 at 17:06 +0100, Thomas Leonard wrote:
>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>
> Why is this being done?

[ CC += Karim ]

I don't know Karim's exact reason, but it seems that ARM doesn't
define XEN_HAVE_PV_UPCALL_MASK, so the existing code can't work.

I don't know what the correct behaviour should be, though. For Mirage,
we check for pending interrupts when we're about to block, rather than
dealing with them in an interrupt handler, so it doesn't affect us.

>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> [talex5@gmail.com: separated from big ARM commit]
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>> ---
>>  extras/mini-os/hypervisor.c         | 20 +-------------------
>>  extras/mini-os/include/hypervisor.h |  1 -
>>  extras/mini-os/include/x86/os.h     | 17 +++++++++++++++++
>>  3 files changed, 18 insertions(+), 20 deletions(-)
>>
>> diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
>> index b4688a0..9c79d5d 100644
>> --- a/extras/mini-os/hypervisor.c
>> +++ b/extras/mini-os/hypervisor.c
>> @@ -71,23 +71,6 @@ void do_hypervisor_callback(struct pt_regs *regs)
>>      in_callback = 0;
>>  }
>>
>> -void force_evtchn_callback(void)
>> -{
>> -    int save;
>> -    vcpu_info_t *vcpu;
>> -    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
>> -    save = vcpu->evtchn_upcall_mask;
>> -
>> -    while (vcpu->evtchn_upcall_pending) {
>> -        vcpu->evtchn_upcall_mask = 1;
>> -        barrier();
>> -        do_hypervisor_callback(NULL);
>> -        barrier();
>> -        vcpu->evtchn_upcall_mask = save;
>> -        barrier();
>> -    };
>> -}
>> -
>>  inline void mask_evtchn(uint32_t port)
>>  {
>>      shared_info_t *s = HYPERVISOR_shared_info;
>> @@ -110,8 +93,7 @@ inline void unmask_evtchn(uint32_t port)
>>                &vcpu_info->evtchn_pending_sel) )
>>      {
>>          vcpu_info->evtchn_upcall_pending = 1;
>> -        if ( !vcpu_info->evtchn_upcall_mask )
>> -            force_evtchn_callback();
>> +        force_evtchn_callback();
>
> If this is something to do with the code motion then I'm not sure what,
> it certainly needs to be explained somewhere.
>
>>      }
>>  }
>>
>> diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
>> index a62cb78..9e9cac8 100644
>> --- a/extras/mini-os/include/hypervisor.h
>> +++ b/extras/mini-os/include/hypervisor.h
>> @@ -35,7 +35,6 @@ extern union start_info_union start_info_union;
>>  #define start_info (start_info_union.start_info)
>>
>>  /* hypervisor.c */
>> -void force_evtchn_callback(void);
>>  void do_hypervisor_callback(struct pt_regs *regs);
>>  void mask_evtchn(uint32_t port);
>>  void unmask_evtchn(uint32_t port);
>> diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
>> index 73b8297..8eea1be 100644
>> --- a/extras/mini-os/include/x86/os.h
>> +++ b/extras/mini-os/include/x86/os.h
>> @@ -160,6 +160,23 @@ do {                                                                     \
>>   */
>>  typedef struct { volatile int counter; } atomic_t;
>>
>> +static inline void force_evtchn_callback(void)
>> +{
>> +    int save;
>> +    vcpu_info_t *vcpu;
>> +    vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
>> +    save = vcpu->evtchn_upcall_mask;
>> +
>> +    while (vcpu->evtchn_upcall_pending) {
>> +        vcpu->evtchn_upcall_mask = 1;
>> +        barrier();
>> +        do_hypervisor_callback(NULL);
>> +        barrier();
>> +        vcpu->evtchn_upcall_mask = save;
>> +        barrier();
>> +    };
>> +}
>> +
>>
>>  /************************** i386 *******************************/
>>  #ifdef __INSIDE_MINIOS__
>
>



-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-06 16:40                   ` Ian Campbell
@ 2014-06-09 13:56                     ` Thomas Leonard
  2014-06-09 14:04                       ` Thomas Leonard
  0 siblings, 1 reply; 44+ messages in thread
From: Thomas Leonard @ 2014-06-09 13:56 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Samuel Thibault, Julien Grall, xen-devel

On 6 June 2014 17:40, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Fri, 2014-06-06 at 17:10 +0200, Samuel Thibault wrote:
>> Ian Campbell, le Fri 06 Jun 2014 15:15:42 +0100, a écrit :
>> > On Fri, 2014-06-06 at 05:59 +0100, karim.allah.ahmed@gmail.com wrote:
>> > > In any case, by looking at the patch it seems like rmb was required to
>> > > make sure that the reply message is visible to the current processor
>> > > when this thread wakes up and starts reading it.
>> >
>> > Can we assume (or arrange) that schedule() gives us this guarantee? Do
>> > we want to?
>>
>> I'd tend to think something like that, yes. More precisely, thread
>> wait/wake primitives usually provide a barrier: events before the wake
>> are supposed to complete before the wait returns. So both should have a
>> memory barrier.
>
> Makes sense to me.

I'm not sure I understand this. Looking again at the code:

if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
    break;
rmb();
memcpy_from_ring(xenstore_buf->rsp,
    &msg,
    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
    sizeof(msg));

I think we are:

1) Checking that the producer response index shows at least one full
unread response is available.

2) Reading the response.

Without the rmb(), we might use stale cached data from before the
response was written, right?

If so, I don't think this has anything to do with Mini-OS's scheduling
(with is always on the same CPU anyway), but with messages between
domains.


-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 6/7] mini-os: Added rmb to xenbus code
  2014-06-09 13:56                     ` Thomas Leonard
@ 2014-06-09 14:04                       ` Thomas Leonard
  0 siblings, 0 replies; 44+ messages in thread
From: Thomas Leonard @ 2014-06-09 14:04 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Samuel Thibault, Julien Grall, xen-devel

On 9 June 2014 14:56, Thomas Leonard <talex5@gmail.com> wrote:
> On 6 June 2014 17:40, Ian Campbell <Ian.Campbell@citrix.com> wrote:
>> On Fri, 2014-06-06 at 17:10 +0200, Samuel Thibault wrote:
>>> Ian Campbell, le Fri 06 Jun 2014 15:15:42 +0100, a écrit :
>>> > On Fri, 2014-06-06 at 05:59 +0100, karim.allah.ahmed@gmail.com wrote:
>>> > > In any case, by looking at the patch it seems like rmb was required to
>>> > > make sure that the reply message is visible to the current processor
>>> > > when this thread wakes up and starts reading it.
>>> >
>>> > Can we assume (or arrange) that schedule() gives us this guarantee? Do
>>> > we want to?
>>>
>>> I'd tend to think something like that, yes. More precisely, thread
>>> wait/wake primitives usually provide a barrier: events before the wake
>>> are supposed to complete before the wait returns. So both should have a
>>> memory barrier.
>>
>> Makes sense to me.
>
> I'm not sure I understand this. Looking again at the code:

Sorry. I was looking at the wrong rmb.


-- 
Dr Thomas Leonard        http://0install.net/
GPG: 9242 9807 C985 3C07 44A6  8B9A AE07 8280 59A5 3CC1
GPG: DA98 25AE CAD0 8975 7CDA  BD8E 0713 3F96 CA74 D8BA

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2014-06-09 14:04 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-02 17:49 [PATCH 0/4] mini-os: initial ARM support Thomas Leonard
2014-06-02 17:49 ` [PATCH 1/4] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-03  0:51   ` Samuel Thibault
2014-06-03  9:01   ` Andrew Cooper
2014-06-02 17:49 ` [PATCH 2/4] mini-os: Tidied up code Thomas Leonard
2014-06-03  0:57   ` Samuel Thibault
2014-06-02 17:49 ` [PATCH 3/4] mini-os: Initial commit to port minios to ARM Thomas Leonard
2014-06-03  9:12   ` Julien Grall
2014-06-04 16:06     ` [PATCH 0/7] mini-os: Preparing for ARM support Thomas Leonard
2014-06-04 16:06       ` [PATCH 1/7] mini-os: Fixed shutdown thread Thomas Leonard
2014-06-04 16:06       ` [PATCH 2/7] mini-os: Tidied up code Thomas Leonard
2014-06-04 16:22         ` Andrew Cooper
2014-06-05 10:24           ` Anil Madhavapeddy
2014-06-04 16:06       ` [PATCH 3/7] mini-os: Moved events code under arch Thomas Leonard
2014-06-04 16:23         ` Julien Grall
2014-06-06 13:54           ` Ian Campbell
2014-06-06 13:57         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 4/7] mini-os: Switched initial C entry point to arch_init Thomas Leonard
2014-06-06 14:05         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 5/7] mini-os: Moved arch-specific xenbus code under arch Thomas Leonard
2014-06-05 14:00         ` Julien Grall
2014-06-06 14:07         ` Ian Campbell
2014-06-04 16:06       ` [PATCH 6/7] mini-os: Added rmb to xenbus code Thomas Leonard
2014-06-05 13:55         ` Julien Grall
2014-06-05 17:45           ` Thomas Leonard
2014-06-06  4:59             ` karim.allah.ahmed
2014-06-06 14:15               ` Ian Campbell
2014-06-06 15:10                 ` Samuel Thibault
2014-06-06 16:40                   ` Ian Campbell
2014-06-09 13:56                     ` Thomas Leonard
2014-06-09 14:04                       ` Thomas Leonard
2014-06-04 16:06       ` [PATCH 7/7] mini-os: Moved force_evtchn_callback to header Thomas Leonard
2014-06-06 14:17         ` Ian Campbell
2014-06-09 11:54           ` Thomas Leonard
2014-06-04 16:12       ` [PATCH 0/7] mini-os: Preparing for ARM support Andrew Cooper
2014-06-02 17:49 ` [PATCH 4/4] mini-os: Added FDT support on ARM Thomas Leonard
2014-06-06 13:51   ` Ian Campbell
2014-06-05 14:36 ` [PATCH 0/4] mini-os: initial ARM support Oleksandr Tyshchenko
2014-06-05 14:57   ` Samuel Thibault
2014-06-05 17:20     ` Oleksandr Tyshchenko
2014-06-05 17:31   ` Thomas Leonard
2014-06-05 18:07     ` Oleksandr Tyshchenko
2014-06-05 18:12       ` Thomas Leonard
2014-06-05 18:21         ` Oleksandr Tyshchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.