All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH ARM v5 00/20] mini-os: initial ARM support
@ 2014-06-26 11:28 Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 01/20] mini-os: build fixes Thomas Leonard
                   ` (20 more replies)
  0 siblings, 21 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

This series is based on Karim's ARM support commits, further broken up into
smaller patches.

The comments from last time should be addressed now, plus a few other things:

- The biggest change in this roll is that it can now cope with being loaded at
  different addresses, and so works on Xen 4.4 and Xen/unstable. It does this
  by configuring the MMU to map virtual address x to physical address (x +
  physical_address_offset), where physical_address_offset is calculated to make
  everything appear where the linker is expecting it.
- The GIC code has moved into the arm directory.
- To make review easier (as requested), libfdt support is now added before the
  main ARM commit, which now uses the FDT immediately rather than adding
  support in later commits.
- I also re-enabled test_xenbus. The old code said "Xenbus tests disabled,
  because of a Xend bug". Since xend doesn't exist any longer, we can enable
  these again.

This patch roll is also available here:

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

Please include Karim in any reply as I am not the author of much of this code.


Karim Raslan (4):
  mini-os: switched initial C entry point to arch_init
  mini-os: added arch_init_gnttab
  mini-os: headers for ARM
  mini-os: import libfdt

Thomas Leonard (16):
  mini-os: build fixes
  mini-os: fixed shutdown thread
  mini-os: fixed format string error in unbind_evtchn
  mini-os: use unbind_evtchn in unbind_all_ports
  mini-os: made off_t type signed
  mini-os: whitespace
  mini-os: don't require XEN_HAVE_PV_UPCALL_MASK
  mini-os: add missing casts to MM printk
  mini-os: added HYPERVISOR_xsm_op
  mini-os: added arch_unbind_ports
  mini-os: moved __pte to x86
  mini-os: moved unlikely/likely macros to new compiler.h
  mini-os: enable test_xenbus again
  mini-os: use irqs_disabled() helper in schedule
  mini-os: initial ARM support
  mini-os: arm: show registers, stack and exception vector on fault

 extras/mini-os/ARM-TODO.txt                        |    5 +
 extras/mini-os/COPYING                             |   27 +
 extras/mini-os/Config.mk                           |    2 +
 extras/mini-os/Makefile                            |   45 +-
 extras/mini-os/arch/arm/Makefile                   |   32 +
 extras/mini-os/arch/arm/arch.mk                    |    7 +
 extras/mini-os/arch/arm/arm32.S                    |  332 +++++
 extras/mini-os/arch/arm/events.c                   |   30 +
 extras/mini-os/arch/arm/gic.c                      |  222 +++
 extras/mini-os/arch/arm/hypercalls32.S             |   75 +
 extras/mini-os/arch/arm/minios-arm32.lds           |   75 +
 extras/mini-os/arch/arm/mm.c                       |  134 ++
 extras/mini-os/arch/arm/panic.c                    |   99 ++
 extras/mini-os/arch/arm/sched.c                    |   37 +
 extras/mini-os/arch/arm/setup.c                    |  116 ++
 extras/mini-os/arch/arm/time.c                     |  202 +++
 extras/mini-os/arch/x86/events.c                   |    4 +
 extras/mini-os/arch/x86/mm.c                       |   13 +
 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/events.c                            |   39 +-
 extras/mini-os/gnttab.c                            |   11 +-
 extras/mini-os/hypervisor.c                        |   12 +-
 extras/mini-os/include/arm/arch_endian.h           |    7 +
 extras/mini-os/include/arm/arch_limits.h           |    9 +
 extras/mini-os/include/arm/arch_mm.h               |   35 +
 extras/mini-os/include/arm/arch_sched.h            |   19 +
 extras/mini-os/include/arm/arch_spinlock.h         |   36 +
 extras/mini-os/include/arm/arm32/arch_wordsize.h   |    1 +
 extras/mini-os/include/arm/gic.h                   |    1 +
 extras/mini-os/include/arm/hypercall-arm.h         |   98 ++
 extras/mini-os/include/arm/os.h                    |  215 +++
 extras/mini-os/include/arm/traps.h                 |   20 +
 extras/mini-os/include/compiler.h                  |    5 +
 extras/mini-os/include/events.h                    |    4 +
 extras/mini-os/include/fdt.h                       |   60 +
 extras/mini-os/include/gnttab.h                    |    1 +
 extras/mini-os/include/hypervisor.h                |    2 +
 extras/mini-os/include/kernel.h                    |    6 +-
 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                     |   24 +-
 extras/mini-os/include/x86/os.h                    |   16 +-
 .../mini-os/include/x86/x86_32/hypercall-x86_32.h  |    5 +
 .../mini-os/include/x86/x86_64/hypercall-x86_64.h  |    4 +
 extras/mini-os/kernel.c                            |   49 +-
 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                                |    4 +-
 extras/mini-os/sched.c                             |   36 +-
 extras/mini-os/test.c                              |    3 +-
 63 files changed, 5606 insertions(+), 138 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/events.c
 create mode 100644 extras/mini-os/arch/arm/gic.c
 create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
 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/panic.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/include/arm/arch_endian.h
 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/arm32/arch_wordsize.h
 create mode 100644 extras/mini-os/include/arm/gic.h
 create mode 100644 extras/mini-os/include/arm/hypercall-arm.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/compiler.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

-- 
2.0.0

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

* [PATCH ARM v5 01/20] mini-os: build fixes
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 02/20] mini-os: fixed shutdown thread Thomas Leonard
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Make .o rules depend on the includes. Before, only the final link step
depended on setting up the includes directory, making parallel builds
unreliable.

Make symlinks use explicit make rules instead of using a phony target.
Avoids unnecessary rebuilds.

[talex5@gmail.com: bring back "make links", for stubdom]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 extras/mini-os/Makefile | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 50d038b..6d6537e 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -50,6 +50,11 @@ flags-$(CONFIG_XENBUS) += -DCONFIG_XENBUS
 
 DEF_CFLAGS += $(flags-y)
 
+# Symlinks and headers that must be created before building the C files
+GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/xen include/$(TARGET_ARCH_FAM)/mini-os
+
+EXTRA_DEPS += $(GENERATED_HEADERS)
+
 # Include common mini-os makerules.
 include minios.mk
 
@@ -124,11 +129,18 @@ include/list.h: $(XEN_ROOT)/tools/include/xen-external/bsd-sys-queue-h-seddery $
 	perl $^ --prefix=minios  >$@.new
 	$(call move-if-changed,$@.new,$@)
 
+# Used by stubdom's Makefile
 .PHONY: links
-links: include/list.h $(ARCH_LINKS)
-	[ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
-	[ -e include/mini-os ] || ln -sf . include/mini-os
-	[ -e include/$(TARGET_ARCH_FAM)/mini-os ] || ln -sf . include/$(TARGET_ARCH_FAM)/mini-os
+links: $(GENERATED_HEADERS)
+
+include/xen:
+	ln -sf ../../../xen/include/public $@
+
+include/mini-os:
+	ln -sf . $@
+
+include/$(TARGET_ARCH_FAM)/mini-os:
+	ln -sf . $@
 
 .PHONY: arch_lib
 arch_lib:
@@ -174,7 +186,7 @@ ifneq ($(APP_OBJS),)
 APP_O=$(OBJ_DIR)/$(TARGET)_app.o 
 endif
 
-$(OBJ_DIR)/$(TARGET): links include/list.h $(OBJS) $(APP_O) arch_lib
+$(OBJ_DIR)/$(TARGET): $(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 $@
@@ -212,4 +224,3 @@ tags:
 .PHONY: TAGS
 TAGS:
 	$(all_sources) | xargs etags
-
-- 
2.0.0

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

* [PATCH ARM v5 02/20] mini-os: fixed shutdown thread
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 01/20] mini-os: build fixes Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 03/20] mini-os: fixed format string error in unbind_evtchn Thomas Leonard
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

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

Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
[talex5@gmail.com: avoid declaration-after-statement in kernel.c]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 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..c7410db 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -68,7 +68,9 @@ void setup_xen_features(void)
 /* This should be overridden by the application we are linked against. */
 __attribute__((weak)) void app_shutdown(unsigned reason)
 {
+    struct sched_shutdown sched_shutdown = { .reason = reason };
     printk("Shutdown requested: %d\n", 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] 54+ messages in thread

* [PATCH ARM v5 03/20] mini-os: fixed format string error in unbind_evtchn
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 01/20] mini-os: build fixes Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 02/20] mini-os: fixed shutdown thread Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 04/20] mini-os: use unbind_evtchn in unbind_all_ports Thomas Leonard
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Would crash if HYPERVISOR_event_channel_op returned an error code.
The other changes in this commit are just fixing indentation.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
Acked-by: Ian Campbell <ian.cammpbell@citrix.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 extras/mini-os/events.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index d60630b..f708cb4 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -109,24 +109,23 @@ evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
 
 void unbind_evtchn(evtchn_port_t port )
 {
-	struct evtchn_close close;
+    struct evtchn_close close;
     int rc;
 
-	if ( ev_actions[port].handler == default_handler )
-		printk("WARN: No handler for port %d when unbinding\n", port);
-	mask_evtchn(port);
-	clear_evtchn(port);
+    if ( ev_actions[port].handler == default_handler )
+        printk("WARN: No handler for port %d when unbinding\n", port);
+    mask_evtchn(port);
+    clear_evtchn(port);
 
-	ev_actions[port].handler = default_handler;
-	wmb();
-	ev_actions[port].data = NULL;
-	clear_bit(port, bound_ports);
+    ev_actions[port].handler = default_handler;
+    wmb();
+    ev_actions[port].data = NULL;
+    clear_bit(port, bound_ports);
 
-	close.port = port;
-	rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+    close.port = port;
+    rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
     if ( rc )
-        printk("WARN: close_port %s failed rc=%d. ignored\n", port, rc);
-        
+        printk("WARN: close_port %d failed rc=%d. ignored\n", port, rc);
 }
 
 evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
-- 
2.0.0

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

* [PATCH ARM v5 04/20] mini-os: use unbind_evtchn in unbind_all_ports
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (2 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 03/20] mini-os: fixed format string error in unbind_evtchn Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 05/20] mini-os: made off_t type signed Thomas Leonard
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

This marks the channel as closed, in case someone tries to use it again.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 extras/mini-os/events.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index f708cb4..3c92d82 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -43,7 +43,6 @@ void unbind_all_ports(void)
     int cpu = 0;
     shared_info_t *s = HYPERVISOR_shared_info;
     vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
-    int rc;
 
     for ( i = 0; i < NR_EVS; i++ )
     {
@@ -53,14 +52,8 @@ void unbind_all_ports(void)
 
         if ( test_and_clear_bit(i, bound_ports) )
         {
-            struct evtchn_close close;
             printk("port %d still bound!\n", i);
-            mask_evtchn(i);
-            close.port = i;
-            rc = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
-            if ( rc )
-                printk("WARN: close_port %s failed rc=%d. ignored\n", i, rc);
-            clear_evtchn(i);
+	    unbind_evtchn(i);
         }
     }
     vcpu_info->evtchn_upcall_pending = 0;
-- 
2.0.0

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

* [PATCH ARM v5 05/20] mini-os: made off_t type signed
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (3 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 04/20] mini-os: use unbind_evtchn in unbind_all_ports Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 06/20] mini-os: switched initial C entry point to arch_init Thomas Leonard
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

POSIX requires this.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 extras/mini-os/include/types.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
index 6640ede..de356e8 100644
--- a/extras/mini-os/include/types.h
+++ b/extras/mini-os/include/types.h
@@ -73,7 +73,7 @@ typedef unsigned long uint64_t;
 #endif
 typedef uint64_t uintmax_t;
 typedef  int64_t intmax_t;
-typedef uint64_t off_t;
+typedef  int64_t off_t;
 #endif
 
 typedef intptr_t            ptrdiff_t;
-- 
2.0.0

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

* [PATCH ARM v5 06/20] mini-os: switched initial C entry point to arch_init
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (4 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 05/20] mini-os: made off_t type signed Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:28 ` [PATCH ARM v5 07/20] mini-os: whitespace Thomas Leonard
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

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]
[talex5@gmail.com: restored comment, moved prototypes to headers]
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
[talex5@gmail.com: restored stack address printk on x86]
[talex5@gmail.com: moved first printk's after start_info setup on x86]
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/kernel.h  |  6 ++++--
 extras/mini-os/include/x86/os.h  |  2 --
 extras/mini-os/kernel.c          | 37 ++++-----------------------------
 6 files changed, 46 insertions(+), 47 deletions(-)

diff --git a/extras/mini-os/arch/x86/setup.c b/extras/mini-os/arch/x86/setup.c
index 54046d3..5e87dd1 100644
--- a/extras/mini-os/arch/x86/setup.c
+++ b/extras/mini-os/arch/x86/setup.c
@@ -28,6 +28,8 @@
 
 #include <mini-os/os.h>
 #include <mini-os/lib.h> /* for printk, memcpy */
+#include <mini-os/kernel.h>
+#include <xen/xen.h>
 
 /*
  * Shared page for communicating with the hypervisor.
@@ -87,20 +89,45 @@ static inline void sse_init(void) {
 #define sse_init()
 #endif
 
+
+/*
+ * 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();
+
 	/*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
 	   shared_info. Use xprintk instead. */
 	memcpy(&start_info, si, sizeof(*si));
 
+	/* 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");
+	printk("       stack: %p-%p\n", stack, stack + sizeof(stack));
+
 	/* set up minimal memory infos */
 	phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
 
@@ -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/kernel.h b/extras/mini-os/include/kernel.h
index b36f172..13e3274 100644
--- a/extras/mini-os/include/kernel.h
+++ b/extras/mini-os/include/kernel.h
@@ -1,7 +1,9 @@
 #ifndef _KERNEL_H_
 #define _KERNEL_H_
 
-extern void do_exit(void) __attribute__((noreturn));
-extern void stop_kernel(void);
+void start_kernel(void);
+void do_exit(void) __attribute__((noreturn));
+void arch_do_exit(void);
+void stop_kernel(void);
 
 #endif /* _KERNEL_H_ */
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 c7410db..9a30550 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -28,6 +28,7 @@
  */
 
 #include <mini-os/os.h>
+#include <mini-os/kernel.h>
 #include <mini-os/hypervisor.h>
 #include <mini-os/mm.h>
 #include <mini-os/events.h>
@@ -114,41 +115,14 @@ __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();
-
     setup_xen_features();
 
     /* Init memory management. */
@@ -201,9 +175,6 @@ void stop_kernel(void)
     /* Reset events. */
     fini_events();
 
-    /* Reset traps */
-    trap_fini();
-
     /* Reset arch details */
     arch_fini();
 }
@@ -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] 54+ messages in thread

* [PATCH ARM v5 07/20] mini-os: whitespace
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (5 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 06/20] mini-os: switched initial C entry point to arch_init Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:35   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab Thomas Leonard
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/gnttab.c     |  2 +-
 extras/mini-os/hypervisor.c |  2 +-
 extras/mini-os/sched.c      | 26 +++++++++++++-------------
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 2f1b3d7..6f25006 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -164,7 +164,7 @@ gnttabop_error(int16_t status)
 {
     status = -status;
     if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
-	return "bad status";
+        return "bad status";
     else
         return gnttabop_error_msgs[status];
 }
diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index b4688a0..c5de872 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -64,7 +64,7 @@ void do_hypervisor_callback(struct pt_regs *regs)
             l2 &= ~(1UL << l2i);
 
             port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
-			do_event(port, regs);
+            do_event(port, regs);
         }
     }
 
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 174945e..99d87b6 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -165,28 +165,28 @@ struct _reent *__getreent(void)
     struct _reent *_reent;
 
     if (!threads_started)
-	_reent = _impure_ptr;
+        _reent = _impure_ptr;
     else if (in_callback)
-	_reent = &callback_reent;
+        _reent = &callback_reent;
     else
-	_reent = &get_current()->reent;
+        _reent = &get_current()->reent;
 
 #ifndef NDEBUG
 #if defined(__x86_64__) || defined(__x86__)
     {
 #ifdef __x86_64__
-	register unsigned long sp asm ("rsp");
+        register unsigned long sp asm ("rsp");
 #else
-	register unsigned long sp asm ("esp");
+        register unsigned long sp asm ("esp");
 #endif
-	if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
-	    static int overflowing;
-	    if (!overflowing) {
-		overflowing = 1;
-		printk("stack overflow\n");
-		BUG();
-	    }
-	}
+        if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+            static int overflowing;
+            if (!overflowing) {
+                overflowing = 1;
+                printk("stack overflow\n");
+                BUG();
+            }
+        }
     }
 #endif
 #else
-- 
2.0.0

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

* [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (6 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 07/20] mini-os: whitespace Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:36   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK Thomas Leonard
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

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

Moves some x86-specific code into arch/x86.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: split into multiple patches]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/x86/mm.c    | 13 +++++++++++++
 extras/mini-os/gnttab.c         |  9 +--------
 extras/mini-os/include/gnttab.h |  1 +
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 35df15b..9c6d1b8 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -942,3 +942,16 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
     *start_pfn_p = start_pfn;
     *max_pfn_p = max_pfn;
 }
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+    struct gnttab_setup_table setup;
+    unsigned long frames[nr_grant_frames];
+
+    setup.dom = DOMID_SELF;
+    setup.nr_frames = nr_grant_frames;
+    set_xen_guest_handle(setup.frame_list, frames);
+
+    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+    return map_frames(frames, nr_grant_frames);
+}
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 6f25006..f395d12 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -172,8 +172,6 @@ gnttabop_error(int16_t status)
 void
 init_gnttab(void)
 {
-    struct gnttab_setup_table setup;
-    unsigned long frames[NR_GRANT_FRAMES];
     int i;
 
 #ifdef GNT_DEBUG
@@ -182,12 +180,7 @@ init_gnttab(void)
     for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
         put_free_entry(i);
 
-    setup.dom = DOMID_SELF;
-    setup.nr_frames = NR_GRANT_FRAMES;
-    set_xen_guest_handle(setup.frame_list, frames);
-
-    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
-    gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
+    gnttab_table = arch_init_gnttab(NR_GRANT_FRAMES);
     printk("gnttab_table mapped at %p.\n", gnttab_table);
 }
 
diff --git a/extras/mini-os/include/gnttab.h b/extras/mini-os/include/gnttab.h
index acd6c39..c43ad42 100644
--- a/extras/mini-os/include/gnttab.h
+++ b/extras/mini-os/include/gnttab.h
@@ -12,5 +12,6 @@ unsigned long gnttab_end_transfer(grant_ref_t gref);
 int gnttab_end_access(grant_ref_t ref);
 const char *gnttabop_error(int16_t status);
 void fini_gnttab(void);
+grant_entry_t *arch_init_gnttab(int nr_grant_frames);
 
 #endif /* !__GNTTAB_H__ */
-- 
2.0.0

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

* [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (7 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:37   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk Thomas Leonard
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

This isn't available on ARM.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/hypervisor.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index c5de872..1b61d9b 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -73,18 +73,26 @@ void do_hypervisor_callback(struct pt_regs *regs)
 
 void force_evtchn_callback(void)
 {
+#ifdef XEN_HAVE_PV_UPCALL_MASK
     int save;
+#endif
     vcpu_info_t *vcpu;
     vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
+#ifdef XEN_HAVE_PV_UPCALL_MASK
     save = vcpu->evtchn_upcall_mask;
+#endif
 
     while (vcpu->evtchn_upcall_pending) {
+#ifdef XEN_HAVE_PV_UPCALL_MASK
         vcpu->evtchn_upcall_mask = 1;
+#endif
         barrier();
         do_hypervisor_callback(NULL);
         barrier();
+#ifdef XEN_HAVE_PV_UPCALL_MASK
         vcpu->evtchn_upcall_mask = save;
         barrier();
+#endif
     };
 }
 
@@ -110,7 +118,9 @@ inline void unmask_evtchn(uint32_t port)
               &vcpu_info->evtchn_pending_sel) )
     {
         vcpu_info->evtchn_upcall_pending = 1;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
         if ( !vcpu_info->evtchn_upcall_mask )
+#endif
             force_evtchn_callback();
     }
 }
-- 
2.0.0

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

* [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (8 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:37   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

The code previously assumed that a long was 64-bits.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/mm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index d2d5264..d31ef97 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -409,8 +409,8 @@ void init_mm(void)
      * now we can initialise the page allocator
      */
     printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
-           (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn), 
-           (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
+           (u_long)to_virt(PFN_PHYS(start_pfn)), (u_long)PFN_PHYS(start_pfn), 
+           (u_long)to_virt(PFN_PHYS(max_pfn)), (u_long)PFN_PHYS(max_pfn));
     init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
     printk("MM: done\n");
 
-- 
2.0.0

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

* [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (9 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:38   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports Thomas Leonard
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Avoids using _hypercall1 in events.c.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/events.c         | 4 ++--
 extras/mini-os/include/x86/os.h | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 3c92d82..d07dbfb 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -244,7 +244,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
     op.cmd = FLASK_GET_PEER_SID;
     op.interface_version = XEN_FLASK_INTERFACE_VERSION;
     op.u.peersid.evtchn = local_port;
-    rc = _hypercall1(int, xsm_op, &op);
+    rc = HYPERVISOR_xsm_op(&op);
     if (rc)
         return rc;
     sid = op.u.peersid.sid;
@@ -252,7 +252,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
     op.u.sid_context.sid = sid;
     op.u.sid_context.size = size;
     set_xen_guest_handle(op.u.sid_context.context, ctx);
-    rc = _hypercall1(int, xsm_op, &op);
+    rc = HYPERVISOR_xsm_op(&op);
     return rc;
 }
 
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 73b8297..9e3f9bf 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -20,6 +20,7 @@
 #include <mini-os/types.h>
 #include <mini-os/hypervisor.h>
 #include <mini-os/kernel.h>
+#include <xen/xsm/flask_op.h>
 
 #define USED    __attribute__ ((used))
 
@@ -563,6 +564,12 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
  synch_const_test_bit((nr),(addr)) : \
  synch_var_test_bit((nr),(addr)))
 
+static inline int
+HYPERVISOR_xsm_op(
+	struct xen_flask_op *op)
+{
+	return _hypercall1(int, xsm_op, op);
+}
 
 #undef ADDR
 
-- 
2.0.0

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

* [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (10 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:38   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 13/20] mini-os: moved __pte to x86 Thomas Leonard
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

This allows closing any ports opened by the arch-specific code.
ARM will use it for the debug port.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/x86/events.c | 4 ++++
 extras/mini-os/events.c          | 1 +
 extras/mini-os/include/events.h  | 4 ++++
 3 files changed, 9 insertions(+)

diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
index e420a98..5198cf3 100644
--- a/extras/mini-os/arch/x86/events.c
+++ b/extras/mini-os/arch/x86/events.c
@@ -23,6 +23,10 @@ void arch_init_events(void)
 #endif
 }
 
+void arch_unbind_ports(void)
+{
+}
+
 void arch_fini_events(void)
 {
 #if defined(__x86_64__)
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index d07dbfb..2a23042 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -179,6 +179,7 @@ void init_events(void)
 void fini_events(void)
 {
     /* Dealloc all events */
+    arch_unbind_ports();
     unbind_all_ports();
     arch_fini_events();
 }
diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
index 0452d21..89b5997 100644
--- a/extras/mini-os/include/events.h
+++ b/extras/mini-os/include/events.h
@@ -26,6 +26,10 @@ typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
 
 /* prototypes */
 void arch_init_events(void);
+
+/* Called by fini_events to close any ports opened by arch-specific code. */
+void arch_unbind_ports(void);
+
 void arch_fini_events(void);
 
 int do_event(evtchn_port_t port, struct pt_regs *regs);
-- 
2.0.0

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

* [PATCH ARM v5 13/20] mini-os: moved __pte to x86
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (11 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:39   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h Thomas Leonard
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

We don't need to define this on ARM. Suggested by Julien Grall.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/include/types.h                       | 12 ------------
 extras/mini-os/include/x86/x86_32/hypercall-x86_32.h |  5 +++++
 extras/mini-os/include/x86/x86_64/hypercall-x86_64.h |  4 ++++
 3 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
index de356e8..93356fe 100644
--- a/extras/mini-os/include/types.h
+++ b/extras/mini-os/include/types.h
@@ -30,23 +30,11 @@ typedef unsigned long       u_long;
 #ifdef __i386__
 typedef long long           quad_t;
 typedef unsigned long long  u_quad_t;
-
-typedef struct { unsigned long pte_low, pte_high; } pte_t;
-
 #elif defined(__x86_64__)
 typedef long                quad_t;
 typedef unsigned long       u_quad_t;
-
-typedef struct { unsigned long pte; } pte_t;
 #endif /* __i386__ || __x86_64__ */
 
-#ifdef __x86_64__
-#define __pte(x) ((pte_t) { (x) } )
-#else
-#define __pte(x) ({ unsigned long long _x = (x);        \
-    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
-#endif
-
 #ifdef HAVE_LIBC
 #include <limits.h>
 #include <stdint.h>
diff --git a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
index dcfbe41..99a4ee3 100644
--- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
+++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
@@ -35,6 +35,11 @@
 #include <xen/nmi.h>
 #include <mini-os/mm.h>
 
+typedef struct { unsigned long pte_low, pte_high; } pte_t;
+
+#define __pte(x) ({ unsigned long long _x = (x);        \
+    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
+
 #define __STR(x) #x
 #define STR(x) __STR(x)
 
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..e00b3bd 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
@@ -38,6 +38,10 @@
 #include <xen/sched.h>
 #include <mini-os/mm.h>
 
+typedef struct { unsigned long pte; } pte_t;
+
+#define __pte(x) ((pte_t) { (x) } )
+
 #define __STR(x) #x
 #define STR(x) __STR(x)
 
-- 
2.0.0

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

* [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (12 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 13/20] mini-os: moved __pte to x86 Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:40   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 15/20] mini-os: enable test_xenbus again Thomas Leonard
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Requested by Julien Grall.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/include/compiler.h | 5 +++++
 extras/mini-os/include/x86/os.h   | 7 +------
 2 files changed, 6 insertions(+), 6 deletions(-)
 create mode 100644 extras/mini-os/include/compiler.h

diff --git a/extras/mini-os/include/compiler.h b/extras/mini-os/include/compiler.h
new file mode 100644
index 0000000..e35c9d5
--- /dev/null
+++ b/extras/mini-os/include/compiler.h
@@ -0,0 +1,5 @@
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+#define unlikely(x)  __builtin_expect((x),0)
+#define likely(x)  __builtin_expect((x),1)
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 9e3f9bf..7a1bdc5 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -7,16 +7,11 @@
 #ifndef _OS_H_
 #define _OS_H_
 
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
-#define unlikely(x)  __builtin_expect((x),0)
-#define likely(x)  __builtin_expect((x),1)
-
 #define smp_processor_id() 0
 
 
 #ifndef __ASSEMBLY__
+#include <mini-os/compiler.h>
 #include <mini-os/types.h>
 #include <mini-os/hypervisor.h>
 #include <mini-os/kernel.h>
-- 
2.0.0

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

* [PATCH ARM v5 15/20] mini-os: enable test_xenbus again
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (13 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:40   ` Samuel Thibault
  2014-06-27 11:05   ` Ian Campbell
  2014-06-26 11:28 ` [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule Thomas Leonard
                   ` (5 subsequent siblings)
  20 siblings, 2 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

The old code said "Xenbus tests disabled, because of a Xend bug".
Since xend doesn't exist any longer, we can enable these again.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/test.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
index bbfc613..20d372b 100644
--- a/extras/mini-os/test.c
+++ b/extras/mini-os/test.c
@@ -56,8 +56,7 @@ void test_xenbus(void);
 
 static void xenbus_tester(void *p)
 {
-    printk("Xenbus tests disabled, because of a Xend bug.\n");
-    /* test_xenbus(); */
+    test_xenbus();
 }
 #endif
 
-- 
2.0.0

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

* [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (14 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 15/20] mini-os: enable test_xenbus again Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 11:42   ` Samuel Thibault
  2014-06-26 11:28 ` [PATCH ARM v5 17/20] mini-os: headers for ARM Thomas Leonard
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Testing whether the result of local_irq_save is zero doesn't work on
ARM.

Suggested by Julien Grall.
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/sched.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 99d87b6..d0c607e 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -78,6 +78,11 @@ void schedule(void)
     struct thread *prev, *next, *thread, *tmp;
     unsigned long flags;
 
+    if (irqs_disabled()) {
+        printk("Must not call schedule() with IRQs disabled\n");
+        BUG();
+    }
+
     prev = current;
     local_irq_save(flags); 
 
@@ -86,11 +91,6 @@ void schedule(void)
         BUG();
     }
 
-    if (flags) {
-        printk("Must not call schedule() with IRQs disabled\n");
-        BUG();
-    }
-
     do {
         /* Examine all threads.
            Find a runnable thread, but also wake up expired ones and find the
-- 
2.0.0

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

* [PATCH ARM v5 17/20] mini-os: headers for ARM
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (15 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-26 16:26   ` Julien Grall
  2014-06-26 11:28 ` [PATCH ARM v5 18/20] mini-os: import libfdt Thomas Leonard
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

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

Adds header files for future ARM support.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
[talex5@gmail.com: split into multiple patches]
[talex5@gmail.com: include hypervisor.h from os.h, as on x86]
[talex5@gmail.com: implemented bitops for ARM]
[talex5@gmail.com: added arch_endian.h for ARM]
[talex5@gmail.com: removed unused hypercalls and inlines]
[talex5@gmail.com: renamed hypercall-arm32 to just hypercall-arm]
[talex5@gmail.com: moved GIC driver to arm directory]
[talex5@gmail.com: added HYPERVISOR_xsm_op]
[talex5@gmail.com: fixes suggested by Julien Grall:
- Removed old x86 comment from arm/arch_spinlock.h.
- Removed unimplemented _raw_spin_lock_flags.
- Renamed __cli/__sti to local_irq_disable/local_irq_enable.
- Cleaned up interrupt macros.
- Avoid disabling the Asynchronous Abort exception.
- Added memory clobber to barriers.
- Enable barriers on __aarch64__ too.
- Use compiler.h for likely/unlikely macros.
- Replaced dmb with slower but safer dsb for now.]
[talex5@gmail.com: made image relocatable]
[talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn]

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/include/arm/arch_endian.h         |   7 +
 extras/mini-os/include/arm/arch_limits.h         |   9 +
 extras/mini-os/include/arm/arch_mm.h             |  35 ++++
 extras/mini-os/include/arm/arch_sched.h          |  19 ++
 extras/mini-os/include/arm/arch_spinlock.h       |  36 ++++
 extras/mini-os/include/arm/arm32/arch_wordsize.h |   1 +
 extras/mini-os/include/arm/gic.h                 |   1 +
 extras/mini-os/include/arm/hypercall-arm.h       |  98 +++++++++++
 extras/mini-os/include/arm/os.h                  | 215 +++++++++++++++++++++++
 extras/mini-os/include/arm/traps.h               |  20 +++
 extras/mini-os/include/hypervisor.h              |   2 +
 extras/mini-os/include/mm.h                      |   2 +
 extras/mini-os/include/types.h                   |  10 +-
 13 files changed, 450 insertions(+), 5 deletions(-)
 create mode 100644 extras/mini-os/include/arm/arch_endian.h
 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/arm32/arch_wordsize.h
 create mode 100644 extras/mini-os/include/arm/gic.h
 create mode 100644 extras/mini-os/include/arm/hypercall-arm.h
 create mode 100644 extras/mini-os/include/arm/os.h
 create mode 100644 extras/mini-os/include/arm/traps.h

diff --git a/extras/mini-os/include/arm/arch_endian.h b/extras/mini-os/include/arm/arch_endian.h
new file mode 100644
index 0000000..0771683
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_endian.h
@@ -0,0 +1,7 @@
+#ifndef	ARCH_ENDIAN_H
+#error "Do not include arch_endian by itself, include endian.h"
+#else
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif
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..a19cb39
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_mm.h
@@ -0,0 +1,35 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern int stack[];
+extern int physical_address_offset;	/* Add this to a virtual address to get the physical address (wraps) */
+
+#define PAGE_SHIFT        12
+#define PAGE_SIZE        (1 << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#define L1_PAGETABLE_SHIFT      12
+
+#define to_phys(x)                 ((unsigned long)(x)+physical_address_offset)
+#define to_virt(x)                 ((void *)((unsigned long)(x)-physical_address_offset))
+
+#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)         (PFN_DOWN(to_phys(_virt)))
+#define mfn_to_virt(_mfn)          (to_virt(PFN_PHYS(_mfn)))
+#define pfn_to_virt(_pfn)          (to_virt(PFN_PHYS(_pfn)))
+
+#define mfn_to_pfn(x) (x)
+#define pfn_to_mfn(x) (x)
+
+#define virtual_to_mfn(_virt)	   virt_to_mfn(_virt)
+
+// 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..de3ac02
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_sched.h
@@ -0,0 +1,19 @@
+#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;
+}
+
+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..dccb9fc
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_spinlock.h
@@ -0,0 +1,36 @@
+#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))
+
+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);
+}
+
+#endif
diff --git a/extras/mini-os/include/arm/arm32/arch_wordsize.h b/extras/mini-os/include/arm/arm32/arch_wordsize.h
new file mode 100644
index 0000000..b47eee9
--- /dev/null
+++ b/extras/mini-os/include/arm/arm32/arch_wordsize.h
@@ -0,0 +1 @@
+#define __WORDSIZE 32
diff --git a/extras/mini-os/include/arm/gic.h b/extras/mini-os/include/arm/gic.h
new file mode 100644
index 0000000..cead2e5
--- /dev/null
+++ b/extras/mini-os/include/arm/gic.h
@@ -0,0 +1 @@
+void gic_init(void);
diff --git a/extras/mini-os/include/arm/hypercall-arm.h b/extras/mini-os/include/arm/hypercall-arm.h
new file mode 100644
index 0000000..6d862ff
--- /dev/null
+++ b/extras/mini-os/include/arm/hypercall-arm.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * hypercall-arm.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 <xen/xsm/flask_op.h>
+#include <mini-os/mm.h>
+
+int
+HYPERVISOR_sched_op(
+    int cmd, void *arg);
+
+static inline int
+HYPERVISOR_shutdown(
+    unsigned int reason)
+{
+    struct sched_shutdown shutdown = { .reason = reason };
+    HYPERVISOR_sched_op(SCHEDOP_shutdown, &shutdown);
+}
+
+int
+HYPERVISOR_memory_op(
+    unsigned int cmd, void *arg);
+
+int
+HYPERVISOR_event_channel_op(
+    int cmd, void *op);
+
+int
+HYPERVISOR_xen_version(
+    int cmd, void *arg);
+
+int
+HYPERVISOR_console_io(
+    int cmd, int count, char *str);
+
+int
+HYPERVISOR_physdev_op(
+    void *physdev_op);
+
+int
+HYPERVISOR_grant_table_op(
+    unsigned int cmd, void *uop, unsigned int count);
+
+int
+HYPERVISOR_vcpu_op(
+    int cmd, int vcpuid, void *extra_args);
+
+int
+HYPERVISOR_sysctl(
+    unsigned long op);
+
+int
+HYPERVISOR_domctl(
+    unsigned long op);
+
+int
+HYPERVISOR_hvm_op(
+    unsigned long op, void *arg);
+
+int
+HYPERVISOR_xsm_op(
+    struct xen_flask_op *);
+
+#endif  /* __HYPERCALL_ARM_H__ */
diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
new file mode 100644
index 0000000..bde8796
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,215 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/hypervisor.h>
+#include <mini-os/types.h>
+#include <mini-os/compiler.h>
+#include <xen/xen.h>
+
+void arch_fini(void);
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
+
+extern void *device_tree;
+
+#define BUG() while(1){}
+
+#define smp_processor_id() 0
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+// disable interrupts
+static inline void local_irq_disable(void) {
+    __asm__ __volatile__("cpsid i":::"memory");
+}
+
+// enable interrupts
+static inline void local_irq_enable(void) {
+    __asm__ __volatile__("cpsie i":::"memory");
+}
+
+#define local_irq_save(x) { \
+    __asm__ __volatile__("mrs %0, cpsr;cpsid i":"=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":"=r"(x)::"memory");    \
+}
+
+static inline int irqs_disabled(void) {
+    int x;
+    local_save_flags(x);
+    return x & 0x80;
+}
+
+/* We probably only need "dmb" here, but we'll start by being paranoid. */
+#define mb() __asm__("dsb":::"memory");
+#define rmb() __asm__("dsb":::"memory");
+#define wmb() __asm__("dsb":::"memory");
+
+/************************** arm *******************************/
+#ifdef __INSIDE_MINIOS__
+#if defined (__arm__)
+#define xchg(ptr,v) __atomic_exchange_n(ptr, v, __ATOMIC_SEQ_CST)
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ *
+ * This operation is atomic.
+ * If you need a memory barrier, use synch_test_and_clear_bit instead.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+    uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+    uint8_t bit = 1 << (nr & 7);
+    uint8_t orig;
+
+    orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_RELAXED);
+
+    return (orig & bit) != 0;
+}
+
+/**
+ * Atomically set a bit and return the old value.
+ * Similar to test_and_clear_bit.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void *base)
+{
+    uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+    uint8_t bit = 1 << (nr & 7);
+    uint8_t orig;
+
+    orig = __atomic_fetch_or(byte, bit, __ATOMIC_RELAXED);
+
+    return (orig & bit) != 0;
+}
+
+/**
+ * Test whether a bit is set. */
+static __inline__ int test_bit(int nr, const volatile unsigned long *addr)
+{
+    const uint8_t *ptr = (const uint8_t *) addr;
+    return ((1 << (nr & 7)) & (ptr[nr >> 3])) != 0;
+}
+
+/**
+ * Atomically set a bit in memory (like test_and_set_bit but discards result).
+ */
+static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+{
+    test_and_set_bit(nr, addr);
+}
+
+/**
+ * Atomically clear a bit in memory (like test_and_clear_bit but discards result).
+ */
+static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+{
+    test_and_clear_bit(nr, addr);
+}
+
+/**
+ * __ffs - find first (lowest) set 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)
+{
+    int clz;
+
+    /* xxxxx10000 = word
+     * xxxxx01111 = word - 1
+     * 0000011111 = word ^ (word - 1)
+     *      4     = 31 - clz(word ^ (word - 1))
+     */
+
+    __asm__ (
+        "sub r0, %[word], #1\n"
+        "eor r0, r0, %[word]\n"
+        "clz %[clz], r0\n":
+        /* Outputs: */
+        [clz] "=r"(clz):
+        /* Inputs: */
+        [word] "r"(word):
+        /* Clobbers: */
+        "r0");
+
+    return 31 - clz;
+}
+
+#else /* ifdef __arm__ */
+#error "Unsupported architecture"
+#endif
+#endif /* ifdef __INSIDE_MINIOS */
+
+/********************* common arm32 and arm64  ****************************/
+
+/* If *ptr == old, then store new there (and return new).
+ * Otherwise, return the old value.
+ * Atomic. */
+#define synch_cmpxchg(ptr, old, new) \
+({ __typeof__(*ptr) stored = old; \
+   __atomic_compare_exchange_n(ptr, &stored, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? new : old; \
+})
+
+/* As test_and_clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void *addr)
+{
+    uint8_t *byte = ((uint8_t *)addr) + (nr >> 3);
+    uint8_t bit = 1 << (nr & 7);
+    uint8_t orig;
+
+    orig = __atomic_fetch_and(byte, ~bit, __ATOMIC_SEQ_CST);
+
+    return (orig & bit) != 0;
+}
+
+/* As test_and_set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ int synch_test_and_set_bit(int nr, volatile void *base)
+{
+    uint8_t *byte = ((uint8_t *)base) + (nr >> 3);
+    uint8_t bit = 1 << (nr & 7);
+    uint8_t orig;
+
+    orig = __atomic_fetch_or(byte, bit, __ATOMIC_SEQ_CST);
+
+    return (orig & bit) != 0;
+}
+
+/* As set_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_set_bit(int nr, volatile void *addr)
+{
+    synch_test_and_set_bit(nr, addr);
+}
+
+/* As clear_bit, but using __ATOMIC_SEQ_CST */
+static __inline__ void synch_clear_bit(int nr, volatile void *addr)
+{
+    synch_test_and_clear_bit(nr, addr);
+}
+
+/* As test_bit, but with a following memory barrier. */
+static __inline__ int synch_test_bit(int nr, volatile void *addr)
+{
+    int result;
+    result = test_bit(nr, addr);
+    barrier();
+    return result;
+}
+
+#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..704df22
--- /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/hypervisor.h b/extras/mini-os/include/hypervisor.h
index a62cb78..21b3566 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -18,6 +18,8 @@
 #include <hypercall-x86_32.h>
 #elif defined(__x86_64__)
 #include <hypercall-x86_64.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#include <hypercall-arm.h>
 #else
 #error "Unsupported architecture"
 #endif
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 93356fe..be9f1d3 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;
 #elif defined(__x86_64__)
@@ -39,10 +39,10 @@ typedef unsigned long       u_quad_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__ */
@@ -52,10 +52,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
-- 
2.0.0

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

* [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (16 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 17/20] mini-os: headers for ARM Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-28 12:01   ` Julien Grall
  2014-06-26 11:28 ` [PATCH ARM v5 19/20] mini-os: initial ARM support Thomas Leonard
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

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

Looks like this is revision v1.3.0-47-gbe60268 from
http://git.jdl.com/gitweb/?p=dtc.git

The memmove implementation is from FreeBSD's
contrib/ldns/compat/memmove.c

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: fixed "make clean" for FDT]
[talex5@gmail.com: replaced GPL memmove with BSD one]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/COPYING                   |   27 +
 extras/mini-os/Makefile                  |   13 +
 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, 3612 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 6d6537e..931cd05 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -77,6 +77,18 @@ TARGET := mini-os
 # Subdirectories common to mini-os
 SUBDIRS := lib xenbus console
 
+ifeq ($(XEN_TARGET_ARCH),arm32)
+# 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
 src-$(CONFIG_TPMFRONT) += tpmfront.c
 src-$(CONFIG_TPM_TIS) += tpm_tis.c
@@ -101,6 +113,7 @@ src-y += lib/math.c
 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 670c14f..171f2df 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..c96ca41 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
-- 
2.0.0

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

* [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (17 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 18/20] mini-os: import libfdt Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-28 18:31   ` Julien Grall
  2014-06-26 11:28 ` [PATCH ARM v5 20/20] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
  2014-06-27 13:34 ` [PATCH ARM v5 00/20] mini-os: initial ARM support Ian Campbell
  20 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

On ARM, Mini-OS will boot and display some output on the console.
Tested with:

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

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]
[talex5@gmail.com: re-enabled force_evtchn_callback]
[talex5@gmail.com: enable regular console]
[talex5@gmail.com: fixed initialisation code:
- Configure write-back caching in page table. This is needed for
  reliable hypercalls to Xen (thanks to Julien Grall).
- Use "client mode" for access control (domains are deprecated,
  according to ARM Cortex-A Series Programmer’s Guide version 4.0,
  section 9.6.4).
- Enable more SCTLR features (icache, branch prediction)]
[talex5@gmail.com: use Virtual Count register for monotonic time]
[talex5@gmail.com: fixed HYPERVISOR_shutdown]
[talex5@gmail.com: get xenstore details from hypervisor]
[talex5@gmail.com: use GCC implementation of division]
[talex5@gmail.com: cleaned up interrupt handlers and threading]
[talex5@gmail.com: call exit_thread when a thread returns]
[talex5@gmail.com: implemented block_domain for ARM]
[talex5@gmail.com: fixed hang when enabling interrupts]
[talex5@gmail.com: added -march=armv7-a to flags]
[talex5@gmail.com: CLREX after handling IRQs]
[talex5@gmail.com: unbind debug port at shutdown]
[talex5@gmail.com: allow unaligned accesses]
[talex5@gmail.com: fix zImage header for XSA-95]
[talex5@gmail.com: get RAM base and size from the FDT]
[talex5@gmail.com: get GIC addresses from FDT]
[talex5@gmail.com: added ARM grant table initialisation]
[talex5@gmail.com: added missing copyright header to hypercalls32.S]
[talex5@gmail.com: moved GIC driver to arm directory]
[talex5@gmail.com: fixes suggested by Julien Grall:
- Removed unnecessary isb.
- Renamed GICD_PRIORITY to GICD_IPRIORITYR.
- Change IRQ number type from unsigned char to int.
- Added volatile to {set,clear}_bit_non_atomic.
- Fixed some comments.
- Check compatible properties in DTB.]
[talex5@gmail.com: made image relocatable]
[talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn]
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/ARM-TODO.txt              |   6 +
 extras/mini-os/Config.mk                 |   2 +
 extras/mini-os/Makefile                  |   9 ++
 extras/mini-os/arch/arm/Makefile         |  32 ++++
 extras/mini-os/arch/arm/arch.mk          |   7 +
 extras/mini-os/arch/arm/arm32.S          | 266 +++++++++++++++++++++++++++++++
 extras/mini-os/arch/arm/events.c         |  30 ++++
 extras/mini-os/arch/arm/gic.c            | 222 ++++++++++++++++++++++++++
 extras/mini-os/arch/arm/hypercalls32.S   |  75 +++++++++
 extras/mini-os/arch/arm/minios-arm32.lds |  75 +++++++++
 extras/mini-os/arch/arm/mm.c             | 134 ++++++++++++++++
 extras/mini-os/arch/arm/sched.c          |  37 +++++
 extras/mini-os/arch/arm/setup.c          | 116 ++++++++++++++
 extras/mini-os/arch/arm/time.c           | 202 +++++++++++++++++++++++
 extras/mini-os/kernel.c                  |   2 +-
 15 files changed, 1214 insertions(+), 1 deletion(-)
 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/events.c
 create mode 100644 extras/mini-os/arch/arm/gic.c
 create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
 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/sched.c
 create mode 100644 extras/mini-os/arch/arm/setup.c
 create mode 100644 extras/mini-os/arch/arm/time.c

diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
new file mode 100644
index 0000000..c85ee5b
--- /dev/null
+++ b/extras/mini-os/ARM-TODO.txt
@@ -0,0 +1,6 @@
+* support abort exception handling ( and others )
+* gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler.
+* bind_*
+* add multiple cpu support (?)
+* map_frames
+* make sure that wallclock is functioning properly
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 931cd05..01d8af0 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -78,6 +78,9 @@ TARGET := mini-os
 SUBDIRS := lib xenbus console
 
 ifeq ($(XEN_TARGET_ARCH),arm32)
+# Need libgcc.a for division helpers
+LDLIBS += `$(CC) -print-libgcc-file-name`
+
 # Device tree support
 SUBDIRS += lib/fdt
 src-y += lib/fdt/fdt.c
@@ -109,7 +112,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
@@ -203,7 +208,11 @@ $(OBJ_DIR)/$(TARGET): $(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..8b78651
--- /dev/null
+++ b/extras/mini-os/arch/arm/Makefile
@@ -0,0 +1,32 @@
+#
+# ARM architecture specific makefiles.
+#
+
+XEN_ROOT = $(CURDIR)/../../../..
+include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
+
+# include arch.mk has to be before minios.mk!
+
+include arch.mk
+include ../../minios.mk
+
+# Sources here are all *.c (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
+
+all: $(OBJ_DIR)/$(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only built 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..ab20d99
--- /dev/null
+++ b/extras/mini-os/arch/arm/arch.mk
@@ -0,0 +1,7 @@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+DEF_ASFLAGS += -march=armv7-a
+ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__ -DXEN_HAVE_PV_GUEST_ENTRY #-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..de74ed9
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,266 @@
+@ Virtual address of the start of RAM (any value will do, but it must be
+@ section-aligned). Update the lds script if changed.
+#define VIRT_BASE 0x400000
+
+@ Offset of the kernel within the RAM. This is a zImage convention which we
+@ rely on.
+#define ZIMAGE_KERNEL_OFFSET 0x8000
+
+@ Desired virtual address of _start. Must match value in .lds file.
+#define VIRT_START (VIRT_BASE + ZIMAGE_KERNEL_OFFSET)
+
+.section .text
+
+.globl _start
+_start:
+	@ zImage header
+.rept   8
+        mov     r0, r0
+.endr
+        b       reset
+        .word   0x016f2818      @ Magic numbers to help the loader
+        .word   0		@ zImage start address (0 = relocatable)
+        .word   _edata - _start @ zImage end address (excludes bss section)
+	@ end of zImage header
+
+@ Called at boot time. Sets up MMU, exception vectors and stack, and then calls C arch_init() function.
+@ => r2 -> DTB
+@ <= never returns
+@ Note: this boot code needs to be within the first (1MB - ZIMAGE_KERNEL_OFFSET) of _start.
+reset:
+	@ Problem: the C code wants to be at a known address (VIRT_BASE), but Xen might
+	@ load us anywhere. We initialise the MMU (mapping virtual to physical @ addresses)
+	@ so everything ends up where the code expects it to be.
+	@
+	@ We calculate the offet between where the linker thought _start would be and where
+	@ it actually is and initialise the page tables to have that offset for every page.
+	@
+	@ When we turn on the MMU, we're still executing at the old address. We don't want
+	@ the code to disappear from under us. So we have to do the mapping in stages:
+	@
+	@ 1. set up a mapping to our current page from both its current and desired addresses
+	@ 2. enable the MMU
+	@ 3. jump to the new address
+	@ 4. remap all the other pages with the calculated offset
+
+	adr	r1, _start		@ r1 = physical address of _start
+	ldr	r3, =VIRT_START		@ r3 = (desired) virtual address of _start
+	sub 	r9, r1, r3		@ r9 = (physical - virtual) offset
+
+	ldr	r7, =page_dir		@ r7 = (desired) virtual addr of page_dir
+	add	r1, r7, r9		@ r1 = physical addr of page_dir
+
+	@ Tell the system where our page table is located.
+	mcr	p15, 0, r1, c2, c0, 0	@ set ttbr0 = r1
+
+	@ Set access permission for domains.
+	@ Domains are deprecated, but we have to configure them anyway.
+	@ We mark every page as being domain 0 and set domain 0 to "client mode"
+	@ (client mode = use access flags in page table).
+	mov	r0, #1			@ 1 = client
+	mcr	p15, 0, r0, c3, c0, 0	@ DACR
+
+	@ Template (flags) for a 1 MB page-table entry.
+	@ TEX[2:0] C B = 001 1 1 (outer and inner write-back, write-allocate)
+	ldr	r8, =(0x2 +  		/* Section entry */ \
+		      0xc +  		/* C B */ \
+		      (3 << 10) + 	/* Read/write */ \
+		      (1 << 12) +	/* TEX */ \
+		      (1 << 16) +	/* Sharable */ \
+		      (1<<19))		/* Non-secure */
+	@ r8 = template page table entry
+
+	@ Add two entries for the current physical section, at the old and new
+	@ addresses.
+	@ It's OK if they're the same. It's even OK if the new section overlaps
+	@ the physical address of the page table, since the MMU is still turned off.
+	mov	r0, pc, lsr#20
+	mov	r0, r0, lsl#20		@ r0 = physical address of this code's section start
+	orr	r3, r0, r8		@ r3 = table entry for this section
+	str	r3, [r1, #VIRT_BASE >> 18] @ map desired virtual section to this code
+	str	r3, [r1, r0, lsr#18]	@ map current section to this code too
+
+	@ Map the section containing the page table to its desired address, if possible.
+	@ We need to make sure the desired virtual section doesn't match the old address of the
+	@ code, since that needs to remain valid briefly after the MMU is turned on.
+	mov	r3, r1, lsr#20		@ r3 = physical section number containing page table
+	rsb	r4, r9, r3, lsl#20	@ r4 = desired virtual address of page table's section
+	orr	r3, r8, r3, lsl#20	@ r3 = table entry for page table
+	cmp	r4, r0			@ is r4 where we're executing from?
+	movne	r5, r4			@ use it if not
+	addeq	r5, r4, #1<<20		@ else use next section instead
+	str	r3, [r1, r5, lsr#18]	@ add section entry for page table itself
+	@ r5 = temporary virtual address of page table section
+
+	@ Invalidate TLB
+	mcr	p15, 0, r1, c8, c7, 0	@ TLBIALL
+
+	@ Enable MMU / SCTLR
+	@ We leave caches off for now because we're going to be changing the
+	@ TLB a lot and this avoids having to flush the caches each time.
+	mrc	p15, 0, r1, c1, c0, 0	@ SCTLR
+	orr	r1, r1, #0x1		@ Enable MMU
+	mcr	p15, 0, r1, c1, c0, 0	@ SCTLR
+	isb
+
+	adr	r1, stage2		@ Physical address of stage2
+	sub	r1, r1, r9		@ Virtual address of stage2
+	bx	r1
+
+@ Called once the MMU is enabled. The boot code and the page table are mapped,
+@ but nothing else is yet.
+@
+@ => r2 -> dtb (physical)
+@    r3 = page table entry for page table itself
+@    r4 = desired virtual address of page table's section
+@    r5 = temporary virtual address of page table's section
+@    r7 = desired virtual address of page table
+@    r8 = section entry template (flags)
+@    r9 = desired physical - virtual offset
+@    pc -> somewhere in newly-mapped virtual code section
+stage2:
+	@ Remap page table to its final location, now it can't clash with our
+	@ execution address.
+	sub	r5, r5,	r4		@ r5 = difference between desired and actual
+	add	r5, r5, r7		@ r5 = temporary virtual address of page_dir
+	str	r3, [r5, r4, lsr#18]	@ map page table section at desired address
+
+	@ Invalidate TLB
+	mcr	p15, 0, r1, c8, c7, 0	@ TLBIALL
+	isb
+
+	@ The new mapping has now taken effect:
+	@ r7 -> page_dir
+
+	@ Fill in the whole top-level translation table (at page_dir).
+	@ Populate the whole pagedir with 1MB section descriptors.
+
+	mov	r1, r7			@ r1 -> first section entry
+	add	r3, r1, #4*4*1024	@ limit (4 GB address space, 4 byte entries)
+	orr	r0, r8, r9		@ r0 = entry mapping section zero to start of physical RAM
+1:
+	str	r0, [r1],#4		@ write the section entry
+	add	r0, r0, #1 << 20 	@ next physical page (wraps)
+	cmp	r1, r3
+	bne	1b
+
+	@ Invalidate TLB
+	mcr	p15, 0, r1, c8, c7, 0	@ TLBIALL
+	isb
+
+	@ At this point, everything is mapped to its final location.
+	@ It's now safe to turn on caching.
+	ldr	r0, =(3 << 11) + 4	@ icache, branch prediction, dcache
+	mrc	p15, 0, r1, c1, c0, 0	@ SCTLR
+	orr	r1, r1, r0
+	mcr	p15, 0, r1, c1, c0, 0	@ SCTLR
+
+	@ Set VBAR -> exception_vector_table
+	@ SCTLR.V = 0
+	adr	r0, exception_vector_table
+	mcr	p15, 0, r0, c12, c0, 0
+
+	@ Initialise 16 KB stack
+	ldr	sp, =stack_end
+
+	@ Store virtual -> physical offset for C code
+	ldr	r0, =physical_address_offset
+	str	r9, [r0]
+
+	sub	r0, r2, r9		@ r0 -> device tree (virtual address)
+
+	b	arch_init
+
+.pushsection .data
+_data:
+.align	14
+.globl page_dir
+@ Each word maps one 1MB virtual section to a physical section
+page_dir:
+	.fill (4*1024), 4, 0x0
+
+.align 12
+.globl shared_info_page
+shared_info_page:
+	.fill (1024), 4, 0x0
+
+.align 3
+.globl stack
+stack:
+	.fill (4*1024), 4, 0x0
+stack_end:
+
+.align 3
+irqstack:
+	.fill (1024), 4, 0x0
+irqstack_end:
+
+.globl physical_address_offset
+physical_address_offset:
+	.long 	0
+
+.popsection
+
+@ exception base address
+.align 5
+.globl exception_vector_table
+@ Note: remember to call CLREX if returning from an exception:
+@ "The architecture enables the local monitor to treat any exclusive store as
+@  matching a previous LDREX address. For this reason, use of the CLREX
+@  instruction to clear an existing tag is required on context switches."
+@ -- ARM Cortex-A Series Programmer’s Guide (Version: 4.0)
+exception_vector_table:
+	b	. @ reset
+	b	. @ undefined instruction
+	b	. @ supervisor call
+	b	. @ prefetch call
+	b	. @ prefetch abort
+	b	. @ data abort
+	b	irq_handler @ irq
+	.word 0xe7f000f0    @ abort on FIQ
+
+irq_handler:
+	ldr	sp, =irqstack_end
+	push	{r0 - r12, r14}
+
+	ldr	r0, IRQ_handler
+	cmp	r0, #0
+	.word	0x07f000f0    	@ undeq - panic if no handler
+	blx	r0		@ call handler
+
+	@ Return from IRQ
+	pop	{r0 - r12, r14}
+	clrex
+	subs	pc, lr, #4
+
+.globl IRQ_handler
+IRQ_handler:
+	.long	0x0
+
+
+.globl __arch_switch_threads
+@ => r0 = &prev->sp
+@    r1 = &next->sp
+@ <= returns to next thread's saved return address
+__arch_switch_threads:
+	stmia	r0, {sp, lr}	@ Store current sp and ip to prev's struct thread
+	str	fp, [sp, #-4]	@ Store fp on the old stack
+
+	ldmia	r1, {sp, lr}	@ Load new sp, ip from next's struct thread
+	ldr	fp, [sp, #-4]	@ Restore fp from the stack
+
+	mov	pc, lr
+
+@ This is called if you try to divide by zero. For now, we make a supervisor call,
+@ which will make us halt.
+.globl raise
+raise:
+	svc	0
+
+.globl arm_start_thread
+arm_start_thread:
+	pop	{r0, r1}
+	@ r0 = user data
+	@ r1 -> thread's main function
+	ldr	lr, =exit_thread
+	bx	r1
diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..517e763
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,30 @@
+#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_unbind_ports(void)
+{
+    if(debug_port != -1)
+    {
+        mask_evtchn(debug_port);
+        unbind_evtchn(debug_port);
+    }
+}
+
+void arch_fini_events(void)
+{
+}
diff --git a/extras/mini-os/arch/arm/gic.c b/extras/mini-os/arch/arm/gic.c
new file mode 100644
index 0000000..5641eb0
--- /dev/null
+++ b/extras/mini-os/arch/arm/gic.c
@@ -0,0 +1,222 @@
+// ARM GIC implementation
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.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 void (*IRQ_handler)(void);
+
+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_IPRIORITYR   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, int irq_number, unsigned char priority)
+{
+    uint32_t value;
+    uint32_t *addr = REG(gicd(gic, GICD_IPRIORITYR)) + (irq_number >> 2);
+    value = REG_READ32(addr);
+    value &= ~(0xff << (8 * (irq_number & 0x3))); // clear old priority
+    value |= priority << (8 * (irq_number & 0x3)); // set new priority
+    REG_WRITE32(addr, value);
+}
+
+static void gic_route_interrupt(struct gic *gic, int irq_number, unsigned char cpu_set)
+{
+    uint32_t value;
+    uint32_t *addr = REG(gicd(gic, GICD_ITARGETSR)) + (irq_number >> 2);
+    value = REG_READ32(addr);
+    value &= ~(0xff << (8 * (irq_number & 0x3))); // clear old target
+    value |= cpu_set << (8 * (irq_number & 0x3)); // set new target
+    REG_WRITE32(addr, value);
+}
+
+/* When accessing the GIC registers, we can't use LDREX/STREX because it's not regular memory. */
+static __inline__ void clear_bit_non_atomic(int nr, volatile void *base)
+{
+    volatile uint32_t *tmp = base;
+    tmp[nr >> 5] &= (unsigned long)~(1 << (nr & 0x1f));
+}
+
+static __inline__ void set_bit_non_atomic(int nr, volatile void *base)
+{
+    volatile uint32_t *tmp = base;
+    tmp[nr >> 5] |= (1 << (nr & 0x1f));
+}
+
+/* Note: not thread safe (but we only support one CPU for now anyway) */
+static void gic_enable_interrupt(struct gic *gic, int 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_non_atomic((irq_number * 2) + 1, cfg_reg) : set_bit_non_atomic((irq_number * 2) + 1, cfg_reg);
+    if(ppi)
+        clear_bit_non_atomic((irq_number * 2), cfg_reg);
+
+    wmb();
+
+    // enable forwarding interrupt from distributor to cpu interface
+    set_enable_reg = (void *)gicd(gic, GICD_ISENABLER);
+    set_bit_non_atomic(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 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
+
+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);
+        break;
+    default:
+        DEBUG("Unhandled irq\n");
+        break;
+    }
+
+    DEBUG("EIRQ\n");
+
+    gic_eoir(&gic, irq);
+}
+
+void gic_init(void) {
+    gic.gicd_base = NULL;
+    int node = 0;
+    int depth = 0;
+    for (;;)
+    {
+        node = fdt_next_node(device_tree, node, &depth);
+        if (node <= 0 || depth < 0)
+            break;
+
+        if (fdt_getprop(device_tree, node, "interrupt-controller", NULL)) {
+            int len = 0;
+
+            if (fdt_node_check_compatible(device_tree, node, "arm,cortex-a15-gic") &&
+                fdt_node_check_compatible(device_tree, node, "arm,cortex-a9-gic") &&
+                fdt_node_check_compatible(device_tree, node, "arm,cortex-a7-gic")) {
+                printk("Skipping incompatible interrupt-controller node\n");
+                continue;
+            }
+
+            const uint64_t *reg = fdt_getprop(device_tree, node, "reg", &len);
+            if (reg == NULL || len != 32) {
+                /* TODO: support other formats */
+                printk("Bad 'reg' property: %p %d\n", reg, len);
+                continue;
+            }
+            gic.gicd_base = to_virt((long) fdt64_to_cpu(reg[0]));
+            gic.gicc_base = to_virt((long) fdt64_to_cpu(reg[2]));
+            printk("Found GIC: gicd_base = %p, gicc_base = %p\n", gic.gicd_base, gic.gicc_base);
+            break;
+        }
+    }
+    if (!gic.gicd_base) {
+        printk("GIC not found!\n");
+        BUG();
+    }
+    wmb();
+
+    IRQ_handler = gic_handler;
+
+    gic_disable_interrupts(&gic);
+    gic_cpu_set_priority(&gic, 0xff);
+
+    /* Must call gic_enable_interrupts before enabling individual interrupts, otherwise our IRQ handler
+     * gets called endlessly with spurious interrupts. */
+    gic_enable_interrupts(&gic);
+
+    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 */);
+}
diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
new file mode 100644
index 0000000..0d7662d
--- /dev/null
+++ b/extras/mini-os/arch/arm/hypercalls32.S
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when 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.
+ */
+
+#define __HYPERVISOR_memory_op            12
+#define __HYPERVISOR_xen_version          17
+#define __HYPERVISOR_console_io           18
+#define __HYPERVISOR_grant_table_op       20
+#define __HYPERVISOR_vcpu_op              24
+#define __HYPERVISOR_xsm_op               27
+#define __HYPERVISOR_sched_op             29
+#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 __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
+
+_hypercall2(sched_op);
+_hypercall2(memory_op);
+_hypercall2(event_channel_op);
+_hypercall2(xen_version);
+_hypercall3(console_io);
+_hypercall1(physdev_op);
+_hypercall3(grant_table_op);
+_hypercall3(vcpu_op);
+_hypercall1(sysctl);
+_hypercall1(domctl);
+_hypercall2(hvm_op);
+_hypercall1(xsm_op);
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..b18ca55
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,75 @@
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x408000;
+  _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 */
+
+  /* Nothing after here is included in the zImage's size */
+
+  __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..5e38a88
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,134 @@
+#include <console.h>
+#include <xen/memory.h>
+#include <arch_mm.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.h>
+#include <lib.h>
+
+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)
+{
+    int memory;
+    int prop_len = 0;
+    const uint64_t *regs;
+
+    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);
+
+    if (fdt_num_mem_rsv(device_tree) != 0)
+        printk("WARNING: reserved memory not supported!\n");
+
+    memory = fdt_node_offset_by_prop_value(device_tree, -1, "device_type", "memory", sizeof("memory"));
+    if (memory < 0) {
+        printk("No memory found in FDT!\n");
+        BUG();
+    }
+
+    /* Xen will always provide us at least one bank of memory.
+     * Mini-OS will use the first bank for the time-being. */
+    regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
+    if (regs == NULL || prop_len != 16) {
+        /* TODO: support other formats */
+        printk("Bad 'reg' property: %p %d\n", regs, prop_len);
+        BUG();
+    }
+
+    unsigned int end = (unsigned int) &_end;
+    unsigned int mem_base = fdt64_to_cpu(regs[0]);
+    unsigned int mem_size = fdt64_to_cpu(regs[1]);
+    printk("Found memory at %p (len 0x%x)\n", mem_base, mem_size);
+
+    BUG_ON(to_virt(mem_base) > (void *) &_text);          /* Our image isn't in our RAM! */
+    *start_pfn_p = PFN_UP(to_phys(end));
+    int heap_len = mem_size - (PFN_PHYS(*start_pfn_p) - mem_base);
+    *max_pfn_p = *start_pfn_p + PFN_DOWN(heap_len);
+
+    printk("Using pages %d to %d as free space for heap.\n", *start_pfn_p, *max_pfn_p);
+
+    /* The device tree is probably in memory that we're about to hand over to the page
+     * allocator, so move it to the end and reserve that space.
+     */
+    int fdt_size = fdt_totalsize(device_tree);
+    void *new_device_tree = to_virt(((*max_pfn_p << PAGE_SHIFT) - fdt_size) & PAGE_MASK);
+    if (new_device_tree != device_tree) {
+        memmove(new_device_tree, device_tree, fdt_size);
+    }
+    device_tree = new_device_tree;
+    *max_pfn_p = to_phys(new_device_tree) >> PAGE_SHIFT;
+}
+
+void arch_init_p2m(unsigned long max_pfn)
+{
+}
+
+void arch_init_demand_mapping_area(unsigned long cur_pfn)
+{
+}
+
+/* Get Xen's suggested physical page assignments for the grant table. */
+static unsigned long get_gnttab_base(void)
+{
+    int hypervisor;
+    int len = 0;
+    const uint64_t *regs;
+    unsigned int gnttab_base;
+
+    hypervisor = fdt_node_offset_by_compatible(device_tree, -1, "xen,xen");
+    BUG_ON(hypervisor < 0);
+
+    regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
+    if (regs == NULL || len != 16) {
+        /* TODO: support other formats */
+        printk("Bad 'reg' property: %p %d\n", regs, len);
+        BUG();
+    }
+
+    gnttab_base = fdt64_to_cpu(regs[0]);
+
+    printk("FDT suggests grant table base %lx\n", gnttab_base);
+
+    return gnttab_base;
+}
+
+grant_entry_t *arch_init_gnttab(int nr_grant_frames)
+{
+    struct xen_add_to_physmap xatp;
+    struct gnttab_setup_table setup;
+    xen_pfn_t frames[nr_grant_frames];
+    unsigned long gnttab_table;
+    int i, rc;
+
+    gnttab_table = get_gnttab_base();
+
+    for (i = 0; i < nr_grant_frames; i++)
+    {
+        xatp.domid = DOMID_SELF;
+        xatp.size = 0;      /* Seems to be unused */
+        xatp.space = XENMAPSPACE_grant_table;
+        xatp.idx = i;
+        xatp.gpfn = (gnttab_table >> PAGE_SHIFT) + i;
+        rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+        BUG_ON(rc != 0);
+    }
+
+    setup.dom = DOMID_SELF;
+    setup.nr_frames = nr_grant_frames;
+    set_xen_guest_handle(setup.frame_list, frames);
+    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+    if (setup.status != 0)
+    {
+        printk("GNTTABOP_setup_table failed; status = %d\n", setup.status);
+        BUG();
+    }
+
+    return to_virt(gnttab_table);
+}
diff --git a/extras/mini-os/arch/arm/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..1306c1b
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,37 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+
+void arm_start_thread(void);
+
+/* 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);
+
+    /* Save pointer to the thread on the stack, used by current macro */
+    *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+    /* Push the details to pass to arm_start_thread onto the stack */
+    int *sp = (int *) (thread->stack + STACK_SIZE);
+    *(--sp) = (int) function;
+    *(--sp) = (int) data;
+    thread->sp = (unsigned long) sp;
+
+    thread->ip = (unsigned long) arm_start_thread;
+
+    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..721e59f
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,116 @@
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/gic.h>
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/hvm/params.h>
+#include <arch_mm.h>
+#include <libfdt.h>
+
+/*
+ * This structure contains start-of-day info, such as pagetable base pointer,
+ * address of the shared_info structure, and things like that.
+ * On x86, the hypervisor passes it to us. On ARM, we fill it in ourselves.
+ */
+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 *device_tree;
+
+static 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;
+}
+
+static void get_console(void)
+{
+    uint64_t v = -1;
+
+    hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+    start_info.console.domU.evtchn = v;
+
+    hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
+    start_info.console.domU.mfn = v;
+
+    printk("Console is on port %d\n", start_info.console.domU.evtchn);
+    printk("Console ring is at mfn %x\n", start_info.console.domU.mfn);
+}
+
+void get_xenbus(void)
+{
+    uint64_t value;
+
+    if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &value))
+        BUG();
+
+    start_info.store_evtchn = (int)value;
+
+    if(hvm_get_parameter(HVM_PARAM_STORE_PFN, &value))
+        BUG();
+    start_info.store_mfn = (unsigned long)value;
+}
+
+/*
+ * INITIAL C ENTRY POINT.
+ */
+void arch_init(void *dtb_pointer)
+{
+    struct xen_add_to_physmap xatp;
+    int r;
+
+    memset(&__bss_start, 0, &_end - &__bss_start);
+
+    xprintk("Virtual -> physical offset = %x\n", physical_address_offset);
+
+    xprintk("Checking DTB at %x...\n", dtb_pointer);
+
+    if ((r = fdt_check_header(dtb_pointer))) {
+        xprintk("Invalid DTB from Xen: %s\n", fdt_strerror(r));
+        BUG();
+    }
+    device_tree = 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;
+
+    /* Fill in start_info */
+    get_console();
+    get_xenbus();
+
+    gic_init();
+
+    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..a522aa9
--- /dev/null
+++ b/extras/mini-os/arch/arm/time.c
@@ -0,0 +1,202 @@
+#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
+ *************************************************************************/
+
+static uint64_t cntvct_at_init;
+static uint32_t counter_freq;
+
+/* Compute with 96 bit intermediate result: (a*b)/c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+    union {
+        uint64_t ll;
+        struct {
+            uint32_t low, high;
+        } l;
+    } u, res;
+    uint64_t rl, rh;
+
+    u.ll = a;
+    rl = (uint64_t)u.l.low * (uint64_t)b;
+    rh = (uint64_t)u.l.high * (uint64_t)b;
+    rh += (rl >> 32);
+    res.l.high = rh / c;
+    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+    return res.ll;
+}
+
+static inline s_time_t ticks_to_ns(uint64_t ticks)
+{
+    return muldiv64(ticks, SECONDS(1), counter_freq);
+}
+
+static inline uint64_t ns_to_ticks(s_time_t ns)
+{
+    return muldiv64(ns, counter_freq, SECONDS(1));
+}
+
+/* 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;
+
+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;
+}
+
+static inline uint64_t read_virtual_count(void)
+{
+    uint32_t c_lo, c_hi;
+    __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));
+    return (((uint64_t) c_hi) << 32) + c_lo;
+}
+
+/* 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)
+{
+    s_time_t time = ticks_to_ns(read_virtual_count() - cntvct_at_init);
+    //printk("monotonic_clock: %llu (%llu)\n", time, NSEC_TO_SEC(time));
+    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 set_vtimer_compare(uint64_t value) {
+    uint32_t x, y;
+
+    DEBUG("New CompareValue : %llx\n", value);
+    x = 0xFFFFFFFFULL & value;
+    y = (value >> 32) & 0xFFFFFFFF;
+
+    __asm__ __volatile__("mcrr p15, 3, %0, %1, c14"
+            ::"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));
+}
+
+void unset_vtimer_compare(void) {
+    uint32_t x;
+
+    __asm__ __volatile__("mov %0, #0x2\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Disable timer and mask the output signal */
+            "isb":"=r"(x));
+}
+
+void block_domain(s_time_t until)
+{
+    uint64_t until_count = ns_to_ticks(until) + cntvct_at_init;
+    ASSERT(irqs_disabled());
+    if (read_virtual_count() < until_count)
+    {
+        set_vtimer_compare(until_count);
+        //char buf[] = "sleep\n"; (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);
+        __asm__ __volatile__("wfi");
+        //char wake[] = "wake\n"; (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(wake), wake);
+        unset_vtimer_compare();
+
+        /* Give the IRQ handler a chance to handle whatever woke us up. */
+        local_irq_enable();
+        local_irq_disable();
+    }
+}
+
+void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign)
+{
+    DEBUG("Timer kick\n");
+    get_time_values_from_xen();
+    update_wallclock();
+}
+
+evtchn_port_t timer_port = -1;
+
+void init_time(void)
+{
+    printk("Initialising timer interface\n");
+
+    __asm__ __volatile__("mrc p15, 0, %0, c14, c0, 0":"=r"(counter_freq));
+    cntvct_at_init = read_virtual_count();
+    printk("Virtual Count register is %llx, freq = %d Hz\n", cntvct_at_init, counter_freq);
+
+    timer_port = bind_virq(VIRQ_TIMER, (evtchn_handler_t)timer_handler, 0);
+    if (timer_port == -1)
+        BUG();
+    unmask_evtchn(timer_port);
+}
+
+void fini_time(void)
+{
+    if (timer_port != -1)
+    {
+        mask_evtchn(timer_port);
+        unbind_evtchn(timer_port);
+    }
+}
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 9a30550..437e5b4 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -121,7 +121,7 @@ void start_kernel(void)
     init_events();
 
     /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
-    __sti();
+    local_irq_enable();
 
     setup_xen_features();
 
-- 
2.0.0


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

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

* [PATCH ARM v5 20/20] mini-os: arm: show registers, stack and exception vector on fault
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (18 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 19/20] mini-os: initial ARM support Thomas Leonard
@ 2014-06-26 11:28 ` Thomas Leonard
  2014-06-27 13:34 ` [PATCH ARM v5 00/20] mini-os: initial ARM support Ian Campbell
  20 siblings, 0 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-26 11:28 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/ARM-TODO.txt     |  1 -
 extras/mini-os/arch/arm/arm32.S | 80 ++++++++++++++++++++++++++++++---
 extras/mini-os/arch/arm/panic.c | 99 +++++++++++++++++++++++++++++++++++++++++
 extras/mini-os/include/arm/os.h |  2 +-
 4 files changed, 173 insertions(+), 9 deletions(-)
 create mode 100644 extras/mini-os/arch/arm/panic.c

diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt
index c85ee5b..27507cd 100644
--- a/extras/mini-os/ARM-TODO.txt
+++ b/extras/mini-os/ARM-TODO.txt
@@ -1,4 +1,3 @@
-* support abort exception handling ( and others )
 * gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler.
 * bind_*
 * add multiple cpu support (?)
diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
index de74ed9..1733936 100644
--- a/extras/mini-os/arch/arm/arm32.S
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -186,11 +186,14 @@ shared_info_page:
 
 .align 3
 .globl stack
+.globl stack_end
 stack:
 	.fill (4*1024), 4, 0x0
 stack_end:
 
 .align 3
+.globl irqstack
+.globl irqstack_end
 irqstack:
 	.fill (1024), 4, 0x0
 irqstack_end:
@@ -199,8 +202,71 @@ irqstack_end:
 physical_address_offset:
 	.long 	0
 
+fault_dump:
+	.fill 18, 4, 0x0		@ On fault, we save the registers + CPSR + handler address
+
 .popsection
 
+fault:
+	cpsid	aif			@ Disable interrupts
+
+	ldr	r13, =fault_dump
+	stmia	r13, {r0-r12}		@ Dump the non-banked registers directly (well, unless from FIQ mode)
+	str	r14, [r13, #15 << 2]	@ Our r14 is the faulting r15
+	mov	r0, r13
+
+	@ Save the caller's CPSR (our SPSR) too.
+	mrs	r1, SPSR
+	str	r1, [r13, #16 << 2]
+
+	@ Switch to the mode we came from to get r13 and r14.
+	@ If coming from user mode, use System mode instead so we're still
+	@ privileged.
+	and	r1, r1, #0x1f		@ r1 = SPSR mode
+	cmp	r1, #0x10		@ If from User mode
+	moveq	r1, #0x1f		@ Then use System mode instead
+
+	mrs	r3, CPSR		@ r3 = our CPSR
+	bic	r2, r3, #0x1f
+	orr	r2, r2, r1
+	msr	CPSR, r2		@ Change to mode r1
+
+	@ Save old mode's r13, r14
+	str	r13, [r0, #13 << 2]
+	str	r14, [r0, #14 << 2]
+
+	msr	CPSR, r3		@ Back to fault mode
+
+	ldr	r1, [r0, #17 << 2]
+	sub	r1, r1, #12		@ Fix to point at start of handler
+	str	r1, [r0, #17 << 2]
+
+	@ Call C code to format the register dump.
+	@ Clobbers the stack, but we're not going to return anyway.
+	ldr	r13, =stack_end
+	bl	dump_registers
+1:
+	wfi
+	b	1b
+
+@ We want to store a unique value to identify this handler, without corrupting
+@ any of the registers. So, we store r15 (which will point just after the branch).
+@ Later, we subtract 12 so the user gets pointed at the start of the exception
+@ handler.
+#define FAULT(name)			\
+.globl fault_##name;			\
+fault_##name:				\
+	ldr	r13, =fault_dump;	\
+	str	r15, [r13, #17 << 2];	\
+	b	fault
+
+FAULT(reset)
+FAULT(undefined_instruction)
+FAULT(svc)
+FAULT(prefetch_call)
+FAULT(prefetch_abort)
+FAULT(data_abort)
+
 @ exception base address
 .align 5
 .globl exception_vector_table
@@ -210,13 +276,13 @@ physical_address_offset:
 @  instruction to clear an existing tag is required on context switches."
 @ -- ARM Cortex-A Series Programmer’s Guide (Version: 4.0)
 exception_vector_table:
-	b	. @ reset
-	b	. @ undefined instruction
-	b	. @ supervisor call
-	b	. @ prefetch call
-	b	. @ prefetch abort
-	b	. @ data abort
-	b	irq_handler @ irq
+	b	fault_reset
+	b	fault_undefined_instruction
+	b	fault_svc
+	b	fault_prefetch_call
+	b	fault_prefetch_abort
+	b	fault_data_abort
+	b	irq_handler @ IRQ
 	.word 0xe7f000f0    @ abort on FIQ
 
 irq_handler:
diff --git a/extras/mini-os/arch/arm/panic.c b/extras/mini-os/arch/arm/panic.c
new file mode 100644
index 0000000..12735d6
--- /dev/null
+++ b/extras/mini-os/arch/arm/panic.c
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * panic.c
+ *
+ * Displays a register dump and stack trace for debugging.
+ *
+ * Copyright (c) 2014, Thomas Leonard
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (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.
+ */
+
+#include <mini-os/os.h>
+#include <arch_mm.h>
+
+extern int stack[];
+extern int stack_end[];
+extern int irqstack[];
+extern int irqstack_end[];
+
+typedef void handler(void);
+
+extern handler fault_reset;
+extern handler fault_undefined_instruction;
+extern handler fault_svc;
+extern handler fault_prefetch_call;
+extern handler fault_prefetch_abort;
+extern handler fault_data_abort;
+
+void dump_registers(int *saved_registers) {
+    static int in_dump = 0;
+    int *sp, *stack_top, *x;
+    char *fault_name;
+    void *fault_handler;
+    int i;
+
+    if (in_dump)
+    {
+        printk("Crash while in dump_registers! Not generating a second report.\n");
+        return;
+    }
+
+    in_dump = 1;
+
+    fault_handler = (handler *) saved_registers[17];
+    if (fault_handler == fault_reset)
+        fault_name = "reset";
+    else if (fault_handler == fault_undefined_instruction)
+        fault_name = "undefined_instruction";
+    else if (fault_handler == fault_svc)
+        fault_name = "svc";
+    else if (fault_handler == fault_prefetch_call)
+        fault_name = "prefetch_call";
+    else if (fault_handler == fault_prefetch_abort)
+        fault_name = "prefetch_abort";
+    else if (fault_handler == fault_data_abort)
+        fault_name = "data_abort";
+    else
+        fault_name = "unknown fault type!";
+
+    printk("Fault handler at %x called (%s)\n", fault_handler, fault_name);
+
+    for (i = 0; i < 16; i++) {
+        printk("r%d = %x\n", i, saved_registers[i]);
+    }
+    printk("CPSR = %x\n", saved_registers[16]);
+
+    printk("Stack dump (innermost last)\n");
+    sp = (int *) saved_registers[13];
+
+    if (sp >= stack && sp <= stack_end)
+        stack_top = stack_end;                          /* The small boot stack */
+    else if (sp >= irqstack && sp <= irqstack_end)
+        stack_top = irqstack_end;                       /* The small IRQ stack */
+    else
+        stack_top = (int *) ((((unsigned long) sp) | (__STACK_SIZE-1)) + 1);        /* A normal thread stack */
+
+    for (x = stack_top - 1; x >= sp; x--)
+    {
+        printk("  [%8p] %8x\n", x, *x);
+    }
+    printk("End of stack\n");
+
+    in_dump = 0;
+}
diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
index bde8796..f750236 100644
--- a/extras/mini-os/include/arm/os.h
+++ b/extras/mini-os/include/arm/os.h
@@ -13,7 +13,7 @@ void timer_handler(evtchn_port_t port, struct pt_regs *regs, void *ign);
 
 extern void *device_tree;
 
-#define BUG() while(1){}
+#define BUG() while(1){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */
 
 #define smp_processor_id() 0
 
-- 
2.0.0


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

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

* Re: [PATCH ARM v5 07/20] mini-os: whitespace
  2014-06-26 11:28 ` [PATCH ARM v5 07/20] mini-os: whitespace Thomas Leonard
@ 2014-06-26 11:35   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:35 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:24 +0100, a écrit :
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/gnttab.c     |  2 +-
>  extras/mini-os/hypervisor.c |  2 +-
>  extras/mini-os/sched.c      | 26 +++++++++++++-------------
>  3 files changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
> index 2f1b3d7..6f25006 100644
> --- a/extras/mini-os/gnttab.c
> +++ b/extras/mini-os/gnttab.c
> @@ -164,7 +164,7 @@ gnttabop_error(int16_t status)
>  {
>      status = -status;
>      if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
> -	return "bad status";
> +        return "bad status";
>      else
>          return gnttabop_error_msgs[status];
>  }
> diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
> index b4688a0..c5de872 100644
> --- a/extras/mini-os/hypervisor.c
> +++ b/extras/mini-os/hypervisor.c
> @@ -64,7 +64,7 @@ void do_hypervisor_callback(struct pt_regs *regs)
>              l2 &= ~(1UL << l2i);
>  
>              port = (l1i * (sizeof(unsigned long) * 8)) + l2i;
> -			do_event(port, regs);
> +            do_event(port, regs);
>          }
>      }
>  
> diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
> index 174945e..99d87b6 100644
> --- a/extras/mini-os/sched.c
> +++ b/extras/mini-os/sched.c
> @@ -165,28 +165,28 @@ struct _reent *__getreent(void)
>      struct _reent *_reent;
>  
>      if (!threads_started)
> -	_reent = _impure_ptr;
> +        _reent = _impure_ptr;
>      else if (in_callback)
> -	_reent = &callback_reent;
> +        _reent = &callback_reent;
>      else
> -	_reent = &get_current()->reent;
> +        _reent = &get_current()->reent;
>  
>  #ifndef NDEBUG
>  #if defined(__x86_64__) || defined(__x86__)
>      {
>  #ifdef __x86_64__
> -	register unsigned long sp asm ("rsp");
> +        register unsigned long sp asm ("rsp");
>  #else
> -	register unsigned long sp asm ("esp");
> +        register unsigned long sp asm ("esp");
>  #endif
> -	if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
> -	    static int overflowing;
> -	    if (!overflowing) {
> -		overflowing = 1;
> -		printk("stack overflow\n");
> -		BUG();
> -	    }
> -	}
> +        if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
> +            static int overflowing;
> +            if (!overflowing) {
> +                overflowing = 1;
> +                printk("stack overflow\n");
> +                BUG();
> +            }
> +        }
>      }
>  #endif
>  #else
> -- 
> 2.0.0
> 

-- 
Samuel
I am the "ILOVEGNU" signature virus. Just copy me to your signature.
This email was infected under the terms of the GNU General Public License.

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

* Re: [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab
  2014-06-26 11:28 ` [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab Thomas Leonard
@ 2014-06-26 11:36   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:36 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:25 +0100, a écrit :
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> 
> Moves some x86-specific code into arch/x86.
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> [talex5@gmail.com: split into multiple patches]
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/arch/x86/mm.c    | 13 +++++++++++++
>  extras/mini-os/gnttab.c         |  9 +--------
>  extras/mini-os/include/gnttab.h |  1 +
>  3 files changed, 15 insertions(+), 8 deletions(-)
> 
> diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
> index 35df15b..9c6d1b8 100644
> --- a/extras/mini-os/arch/x86/mm.c
> +++ b/extras/mini-os/arch/x86/mm.c
> @@ -942,3 +942,16 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
>      *start_pfn_p = start_pfn;
>      *max_pfn_p = max_pfn;
>  }
> +
> +grant_entry_t *arch_init_gnttab(int nr_grant_frames)
> +{
> +    struct gnttab_setup_table setup;
> +    unsigned long frames[nr_grant_frames];
> +
> +    setup.dom = DOMID_SELF;
> +    setup.nr_frames = nr_grant_frames;
> +    set_xen_guest_handle(setup.frame_list, frames);
> +
> +    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
> +    return map_frames(frames, nr_grant_frames);
> +}
> diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
> index 6f25006..f395d12 100644
> --- a/extras/mini-os/gnttab.c
> +++ b/extras/mini-os/gnttab.c
> @@ -172,8 +172,6 @@ gnttabop_error(int16_t status)
>  void
>  init_gnttab(void)
>  {
> -    struct gnttab_setup_table setup;
> -    unsigned long frames[NR_GRANT_FRAMES];
>      int i;
>  
>  #ifdef GNT_DEBUG
> @@ -182,12 +180,7 @@ init_gnttab(void)
>      for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
>          put_free_entry(i);
>  
> -    setup.dom = DOMID_SELF;
> -    setup.nr_frames = NR_GRANT_FRAMES;
> -    set_xen_guest_handle(setup.frame_list, frames);
> -
> -    HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
> -    gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
> +    gnttab_table = arch_init_gnttab(NR_GRANT_FRAMES);
>      printk("gnttab_table mapped at %p.\n", gnttab_table);
>  }
>  
> diff --git a/extras/mini-os/include/gnttab.h b/extras/mini-os/include/gnttab.h
> index acd6c39..c43ad42 100644
> --- a/extras/mini-os/include/gnttab.h
> +++ b/extras/mini-os/include/gnttab.h
> @@ -12,5 +12,6 @@ unsigned long gnttab_end_transfer(grant_ref_t gref);
>  int gnttab_end_access(grant_ref_t ref);
>  const char *gnttabop_error(int16_t status);
>  void fini_gnttab(void);
> +grant_entry_t *arch_init_gnttab(int nr_grant_frames);
>  
>  #endif /* !__GNTTAB_H__ */
> -- 
> 2.0.0
> 

-- 
Samuel
"And the next time you consider complaining that running Lucid Emacs
19.05 via NFS from a remote Linux machine in Paraguay doesn't seem to
get the background colors right, you'll know who to thank."
(By Matt Welsh)

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

* Re: [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK
  2014-06-26 11:28 ` [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK Thomas Leonard
@ 2014-06-26 11:37   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:37 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:26 +0100, a écrit :
> This isn't available on ARM.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/hypervisor.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
> index c5de872..1b61d9b 100644
> --- a/extras/mini-os/hypervisor.c
> +++ b/extras/mini-os/hypervisor.c
> @@ -73,18 +73,26 @@ void do_hypervisor_callback(struct pt_regs *regs)
>  
>  void force_evtchn_callback(void)
>  {
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
>      int save;
> +#endif
>      vcpu_info_t *vcpu;
>      vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
>      save = vcpu->evtchn_upcall_mask;
> +#endif
>  
>      while (vcpu->evtchn_upcall_pending) {
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
>          vcpu->evtchn_upcall_mask = 1;
> +#endif
>          barrier();
>          do_hypervisor_callback(NULL);
>          barrier();
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
>          vcpu->evtchn_upcall_mask = save;
>          barrier();
> +#endif
>      };
>  }
>  
> @@ -110,7 +118,9 @@ inline void unmask_evtchn(uint32_t port)
>                &vcpu_info->evtchn_pending_sel) )
>      {
>          vcpu_info->evtchn_upcall_pending = 1;
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
>          if ( !vcpu_info->evtchn_upcall_mask )
> +#endif
>              force_evtchn_callback();
>      }
>  }
> -- 
> 2.0.0
> 

-- 
Samuel
 Créer une hiérarchie supplementaire pour remedier à un problème (?) de
 dispersion est d'une logique digne des Shadocks.
 * BT in: Guide du Cabaliste Usenet - La Cabale vote oui (les Shadocks aussi) *

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

* Re: [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk
  2014-06-26 11:28 ` [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk Thomas Leonard
@ 2014-06-26 11:37   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:37 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:27 +0100, a écrit :
> The code previously assumed that a long was 64-bits.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/mm.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
> index d2d5264..d31ef97 100644
> --- a/extras/mini-os/mm.c
> +++ b/extras/mini-os/mm.c
> @@ -409,8 +409,8 @@ void init_mm(void)
>       * now we can initialise the page allocator
>       */
>      printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n",
> -           (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn), 
> -           (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
> +           (u_long)to_virt(PFN_PHYS(start_pfn)), (u_long)PFN_PHYS(start_pfn), 
> +           (u_long)to_virt(PFN_PHYS(max_pfn)), (u_long)PFN_PHYS(max_pfn));
>      init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
>      printk("MM: done\n");
>  
> -- 
> 2.0.0
> 

-- 
Samuel
 Moralité : le modem et le cablerouteur font comme les filles, ils
 papotent toute la journée.
 -+- RB in NPC : Et en plus, ils ne parlent que de bits -+-

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

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-26 11:28 ` [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
@ 2014-06-26 11:38   ` Samuel Thibault
  2014-06-27 13:13     ` Ian Campbell
  0 siblings, 1 reply; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:38 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:28 +0100, a écrit :
> Avoids using _hypercall1 in events.c.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/events.c         | 4 ++--
>  extras/mini-os/include/x86/os.h | 7 +++++++
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> index 3c92d82..d07dbfb 100644
> --- a/extras/mini-os/events.c
> +++ b/extras/mini-os/events.c
> @@ -244,7 +244,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
>      op.cmd = FLASK_GET_PEER_SID;
>      op.interface_version = XEN_FLASK_INTERFACE_VERSION;
>      op.u.peersid.evtchn = local_port;
> -    rc = _hypercall1(int, xsm_op, &op);
> +    rc = HYPERVISOR_xsm_op(&op);
>      if (rc)
>          return rc;
>      sid = op.u.peersid.sid;
> @@ -252,7 +252,7 @@ int evtchn_get_peercontext(evtchn_port_t local_port, char *ctx, int size)
>      op.u.sid_context.sid = sid;
>      op.u.sid_context.size = size;
>      set_xen_guest_handle(op.u.sid_context.context, ctx);
> -    rc = _hypercall1(int, xsm_op, &op);
> +    rc = HYPERVISOR_xsm_op(&op);
>      return rc;
>  }
>  
> diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
> index 73b8297..9e3f9bf 100644
> --- a/extras/mini-os/include/x86/os.h
> +++ b/extras/mini-os/include/x86/os.h
> @@ -20,6 +20,7 @@
>  #include <mini-os/types.h>
>  #include <mini-os/hypervisor.h>
>  #include <mini-os/kernel.h>
> +#include <xen/xsm/flask_op.h>
>  
>  #define USED    __attribute__ ((used))
>  
> @@ -563,6 +564,12 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
>   synch_const_test_bit((nr),(addr)) : \
>   synch_var_test_bit((nr),(addr)))
>  
> +static inline int
> +HYPERVISOR_xsm_op(
> +	struct xen_flask_op *op)
> +{
> +	return _hypercall1(int, xsm_op, op);
> +}
>  
>  #undef ADDR
>  
> -- 
> 2.0.0
> 

-- 
Samuel
<s> T'as pas de portable ?
<m> J'ai un nokia, dans le bassin d'arcachon

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

* Re: [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports
  2014-06-26 11:28 ` [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports Thomas Leonard
@ 2014-06-26 11:38   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:38 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:29 +0100, a écrit :
> This allows closing any ports opened by the arch-specific code.
> ARM will use it for the debug port.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/arch/x86/events.c | 4 ++++
>  extras/mini-os/events.c          | 1 +
>  extras/mini-os/include/events.h  | 4 ++++
>  3 files changed, 9 insertions(+)
> 
> diff --git a/extras/mini-os/arch/x86/events.c b/extras/mini-os/arch/x86/events.c
> index e420a98..5198cf3 100644
> --- a/extras/mini-os/arch/x86/events.c
> +++ b/extras/mini-os/arch/x86/events.c
> @@ -23,6 +23,10 @@ void arch_init_events(void)
>  #endif
>  }
>  
> +void arch_unbind_ports(void)
> +{
> +}
> +
>  void arch_fini_events(void)
>  {
>  #if defined(__x86_64__)
> diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
> index d07dbfb..2a23042 100644
> --- a/extras/mini-os/events.c
> +++ b/extras/mini-os/events.c
> @@ -179,6 +179,7 @@ void init_events(void)
>  void fini_events(void)
>  {
>      /* Dealloc all events */
> +    arch_unbind_ports();
>      unbind_all_ports();
>      arch_fini_events();
>  }
> diff --git a/extras/mini-os/include/events.h b/extras/mini-os/include/events.h
> index 0452d21..89b5997 100644
> --- a/extras/mini-os/include/events.h
> +++ b/extras/mini-os/include/events.h
> @@ -26,6 +26,10 @@ typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
>  
>  /* prototypes */
>  void arch_init_events(void);
> +
> +/* Called by fini_events to close any ports opened by arch-specific code. */
> +void arch_unbind_ports(void);
> +
>  void arch_fini_events(void);
>  
>  int do_event(evtchn_port_t port, struct pt_regs *regs);
> -- 
> 2.0.0
> 

-- 
Samuel
 > Quelqu'un aurait-il une solution pour réinitialiser un MBR
 Si tu veux qu'il soit complètement blanc (pas souhaitable, à mon avis) :
 dd if=/dev/zero of=/dev/hda bs=512 count=1 (sous Linux)
 -+- OT in Guide du linuxien (très) pervers - "Pour les K difficiles" -+-

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

* Re: [PATCH ARM v5 13/20] mini-os: moved __pte to x86
  2014-06-26 11:28 ` [PATCH ARM v5 13/20] mini-os: moved __pte to x86 Thomas Leonard
@ 2014-06-26 11:39   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:39 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:30 +0100, a écrit :
> We don't need to define this on ARM. Suggested by Julien Grall.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/include/types.h                       | 12 ------------
>  extras/mini-os/include/x86/x86_32/hypercall-x86_32.h |  5 +++++
>  extras/mini-os/include/x86/x86_64/hypercall-x86_64.h |  4 ++++
>  3 files changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/extras/mini-os/include/types.h b/extras/mini-os/include/types.h
> index de356e8..93356fe 100644
> --- a/extras/mini-os/include/types.h
> +++ b/extras/mini-os/include/types.h
> @@ -30,23 +30,11 @@ typedef unsigned long       u_long;
>  #ifdef __i386__
>  typedef long long           quad_t;
>  typedef unsigned long long  u_quad_t;
> -
> -typedef struct { unsigned long pte_low, pte_high; } pte_t;
> -
>  #elif defined(__x86_64__)
>  typedef long                quad_t;
>  typedef unsigned long       u_quad_t;
> -
> -typedef struct { unsigned long pte; } pte_t;
>  #endif /* __i386__ || __x86_64__ */
>  
> -#ifdef __x86_64__
> -#define __pte(x) ((pte_t) { (x) } )
> -#else
> -#define __pte(x) ({ unsigned long long _x = (x);        \
> -    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
> -#endif
> -
>  #ifdef HAVE_LIBC
>  #include <limits.h>
>  #include <stdint.h>
> diff --git a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
> index dcfbe41..99a4ee3 100644
> --- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
> +++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
> @@ -35,6 +35,11 @@
>  #include <xen/nmi.h>
>  #include <mini-os/mm.h>
>  
> +typedef struct { unsigned long pte_low, pte_high; } pte_t;
> +
> +#define __pte(x) ({ unsigned long long _x = (x);        \
> +    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
> +
>  #define __STR(x) #x
>  #define STR(x) __STR(x)
>  
> 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..e00b3bd 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
> @@ -38,6 +38,10 @@
>  #include <xen/sched.h>
>  #include <mini-os/mm.h>
>  
> +typedef struct { unsigned long pte; } pte_t;
> +
> +#define __pte(x) ((pte_t) { (x) } )
> +
>  #define __STR(x) #x
>  #define STR(x) __STR(x)
>  
> -- 
> 2.0.0
> 

-- 
Samuel
Actually, typing random strings in the Finder does the equivalent of
filename completion.
(Discussion in comp.os.linux.misc on the intuitiveness of commands: file
completion vs. the Mac Finder.)

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

* Re: [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h
  2014-06-26 11:28 ` [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h Thomas Leonard
@ 2014-06-26 11:40   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:40 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:31 +0100, a écrit :
> Requested by Julien Grall.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/include/compiler.h | 5 +++++
>  extras/mini-os/include/x86/os.h   | 7 +------
>  2 files changed, 6 insertions(+), 6 deletions(-)
>  create mode 100644 extras/mini-os/include/compiler.h
> 
> diff --git a/extras/mini-os/include/compiler.h b/extras/mini-os/include/compiler.h
> new file mode 100644
> index 0000000..e35c9d5
> --- /dev/null
> +++ b/extras/mini-os/include/compiler.h
> @@ -0,0 +1,5 @@
> +#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
> +#define __builtin_expect(x, expected_value) (x)
> +#endif
> +#define unlikely(x)  __builtin_expect((x),0)
> +#define likely(x)  __builtin_expect((x),1)
> diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
> index 9e3f9bf..7a1bdc5 100644
> --- a/extras/mini-os/include/x86/os.h
> +++ b/extras/mini-os/include/x86/os.h
> @@ -7,16 +7,11 @@
>  #ifndef _OS_H_
>  #define _OS_H_
>  
> -#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
> -#define __builtin_expect(x, expected_value) (x)
> -#endif
> -#define unlikely(x)  __builtin_expect((x),0)
> -#define likely(x)  __builtin_expect((x),1)
> -
>  #define smp_processor_id() 0
>  
>  
>  #ifndef __ASSEMBLY__
> +#include <mini-os/compiler.h>
>  #include <mini-os/types.h>
>  #include <mini-os/hypervisor.h>
>  #include <mini-os/kernel.h>
> -- 
> 2.0.0
> 

-- 
Samuel
 jr> J'ai fait.
 Ne bougez pas, l'aide soignante va venir nettoyer.
 -+- FF in GNU - Le vieil homme et la merde -+-

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

* Re: [PATCH ARM v5 15/20] mini-os: enable test_xenbus again
  2014-06-26 11:28 ` [PATCH ARM v5 15/20] mini-os: enable test_xenbus again Thomas Leonard
@ 2014-06-26 11:40   ` Samuel Thibault
  2014-06-27 11:05   ` Ian Campbell
  1 sibling, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:40 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:32 +0100, a écrit :
> The old code said "Xenbus tests disabled, because of a Xend bug".
> Since xend doesn't exist any longer, we can enable these again.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/test.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
> index bbfc613..20d372b 100644
> --- a/extras/mini-os/test.c
> +++ b/extras/mini-os/test.c
> @@ -56,8 +56,7 @@ void test_xenbus(void);
>  
>  static void xenbus_tester(void *p)
>  {
> -    printk("Xenbus tests disabled, because of a Xend bug.\n");
> -    /* test_xenbus(); */
> +    test_xenbus();
>  }
>  #endif
>  
> -- 
> 2.0.0
> 

-- 
Samuel
<D> N: j'aime bien Cut d'un truc enorme... ca montre de quel cote de l'ecran sont les couilles :)))
 -+- #ens-mim et la peufeupeu -+-

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

* Re: [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule
  2014-06-26 11:28 ` [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule Thomas Leonard
@ 2014-06-26 11:42   ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-26 11:42 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Thu 26 Jun 2014 12:28:33 +0100, a écrit :
> Testing whether the result of local_irq_save is zero doesn't work on
> ARM.
> 
> Suggested by Julien Grall.
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/sched.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
> index 99d87b6..d0c607e 100644
> --- a/extras/mini-os/sched.c
> +++ b/extras/mini-os/sched.c
> @@ -78,6 +78,11 @@ void schedule(void)
>      struct thread *prev, *next, *thread, *tmp;
>      unsigned long flags;
>  
> +    if (irqs_disabled()) {
> +        printk("Must not call schedule() with IRQs disabled\n");
> +        BUG();
> +    }
> +
>      prev = current;
>      local_irq_save(flags); 
>  
> @@ -86,11 +91,6 @@ void schedule(void)
>          BUG();
>      }
>  
> -    if (flags) {
> -        printk("Must not call schedule() with IRQs disabled\n");
> -        BUG();
> -    }
> -
>      do {
>          /* Examine all threads.
>             Find a runnable thread, but also wake up expired ones and find the
> -- 
> 2.0.0
> 

-- 
Samuel
    if (argc > 1 && strcmp(argv[1], "-advice") == 0) {
	printf("Don't Panic!\n");
	exit(42);
    }
	-- Arnold Robbins in the LJ of February '95, describing RCS

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

* Re: [PATCH ARM v5 17/20] mini-os: headers for ARM
  2014-06-26 11:28 ` [PATCH ARM v5 17/20] mini-os: headers for ARM Thomas Leonard
@ 2014-06-26 16:26   ` Julien Grall
  2014-06-27 13:02     ` Thomas Leonard
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2014-06-26 16:26 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 06/26/2014 12:28 PM, Thomas Leonard wrote:
> diff --git a/extras/mini-os/include/arm/hypercall-arm.h b/extras/mini-os/include/arm/hypercall-arm.h
> new file mode 100644
> index 0000000..6d862ff
> --- /dev/null
> +++ b/extras/mini-os/include/arm/hypercall-arm.h
> +#ifndef __HYPERCALL_ARM_H__
> +#define __HYPERCALL_ARM_H__
> +
> +#include <xen/xen.h>
> +#include <xen/sched.h>
> +#include <xen/xsm/flask_op.h>
> +#include <mini-os/mm.h>

Does all those includes relevant for hypercall-arm?

> diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
> new file mode 100644
> index 0000000..bde8796
> --- /dev/null
> +++ b/extras/mini-os/include/arm/os.h

[..]

> +#define BUG() while(1){}

It looks odd to use onely while (1). Shouldn't you call do_exit as x86 does?

-- 
Julien Grall

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

* Re: [PATCH ARM v5 15/20] mini-os: enable test_xenbus again
  2014-06-26 11:28 ` [PATCH ARM v5 15/20] mini-os: enable test_xenbus again Thomas Leonard
  2014-06-26 11:40   ` Samuel Thibault
@ 2014-06-27 11:05   ` Ian Campbell
  2014-06-27 12:48     ` Thomas Leonard
  1 sibling, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 11:05 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Thu, 2014-06-26 at 12:28 +0100, Thomas Leonard wrote:
> The old code said "Xenbus tests disabled, because of a Xend bug".
> Since xend doesn't exist any longer, we can enable these again.

Out of curiosity, do you know if they work now? (I don't think the
answer should block this patch either way).

> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/test.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
> index bbfc613..20d372b 100644
> --- a/extras/mini-os/test.c
> +++ b/extras/mini-os/test.c
> @@ -56,8 +56,7 @@ void test_xenbus(void);
>  
>  static void xenbus_tester(void *p)
>  {
> -    printk("Xenbus tests disabled, because of a Xend bug.\n");
> -    /* test_xenbus(); */
> +    test_xenbus();
>  }
>  #endif
>  

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

* Re: [PATCH ARM v5 15/20] mini-os: enable test_xenbus again
  2014-06-27 11:05   ` Ian Campbell
@ 2014-06-27 12:48     ` Thomas Leonard
  2014-06-27 12:54       ` Ian Campbell
  0 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-27 12:48 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 27 June 2014 12:05, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Thu, 2014-06-26 at 12:28 +0100, Thomas Leonard wrote:
>> The old code said "Xenbus tests disabled, because of a Xend bug".
>> Since xend doesn't exist any longer, we can enable these again.
>
> Out of curiosity, do you know if they work now? (I don't think the
> answer should block this patch either way).

On ARM, with all the patches I sent applied, the output is:

[...]
Doing xenbus test.
Periodic thread started.
T(s=0 us=1253)
Got a reply, type 16, id 1, len 7.
Doing ls test.
ls device...
ls device[0] -> suspend
ls device[1] -> vbd
ls device[2] -> vif
ls device/vif...
ls device/vif[0] -> 0
ls device/vif/0...
ls device/vif/0[0] -> backend
ls device/vif/0[1] -> backend-id
ls device/vif/0[2] -> state
ls device/vif/0[3] -> handle
ls device/vif/0[4] -> mac
Doing read test.
Read device/vif/0/mac...
Read device/vif/0/mac -> 00:16:3e:7d:69:0d.
Read device/vif/0/backend...
Read device/vif/0/backend -> /local/domain/0/backend/vif/1/0.
Doing write test.
Write flobble to device/vif/0/flibble...
Success.
Read device/vif/0/flibble...
Read device/vif/0/flibble -> flobble.
Write widget to device/vif/0/flibble...
Success.
Read device/vif/0/flibble...
Read device/vif/0/flibble -> widget.
Doing rm test.
rm device/vif/0/flibble...
Success.
Read device/vif/0/flibble...
Error in xenbus read: ENOENT
(Should have said ENOENT)
Thread "xenbus_tester" exited.
T(s=1 us=1543)
[...]

>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>> ---
>>  extras/mini-os/test.c | 3 +--
>>  1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
>> index bbfc613..20d372b 100644
>> --- a/extras/mini-os/test.c
>> +++ b/extras/mini-os/test.c
>> @@ -56,8 +56,7 @@ void test_xenbus(void);
>>
>>  static void xenbus_tester(void *p)
>>  {
>> -    printk("Xenbus tests disabled, because of a Xend bug.\n");
>> -    /* test_xenbus(); */
>> +    test_xenbus();
>>  }
>>  #endif
>>
>
>



-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 15/20] mini-os: enable test_xenbus again
  2014-06-27 12:48     ` Thomas Leonard
@ 2014-06-27 12:54       ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 12:54 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Fri, 2014-06-27 at 13:48 +0100, Thomas Leonard wrote:
> On 27 June 2014 12:05, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Thu, 2014-06-26 at 12:28 +0100, Thomas Leonard wrote:
> >> The old code said "Xenbus tests disabled, because of a Xend bug".
> >> Since xend doesn't exist any longer, we can enable these again.
> >
> > Out of curiosity, do you know if they work now? (I don't think the
> > answer should block this patch either way).
> 
> On ARM, with all the patches I sent applied, the output is:

Which I suppose looks like success despite the messages towards the end.
Anywya, thanks.

> 
> [...]
> Doing xenbus test.
> Periodic thread started.
> T(s=0 us=1253)
> Got a reply, type 16, id 1, len 7.
> Doing ls test.
> ls device...
> ls device[0] -> suspend
> ls device[1] -> vbd
> ls device[2] -> vif
> ls device/vif...
> ls device/vif[0] -> 0
> ls device/vif/0...
> ls device/vif/0[0] -> backend
> ls device/vif/0[1] -> backend-id
> ls device/vif/0[2] -> state
> ls device/vif/0[3] -> handle
> ls device/vif/0[4] -> mac
> Doing read test.
> Read device/vif/0/mac...
> Read device/vif/0/mac -> 00:16:3e:7d:69:0d.
> Read device/vif/0/backend...
> Read device/vif/0/backend -> /local/domain/0/backend/vif/1/0.
> Doing write test.
> Write flobble to device/vif/0/flibble...
> Success.
> Read device/vif/0/flibble...
> Read device/vif/0/flibble -> flobble.
> Write widget to device/vif/0/flibble...
> Success.
> Read device/vif/0/flibble...
> Read device/vif/0/flibble -> widget.
> Doing rm test.
> rm device/vif/0/flibble...
> Success.
> Read device/vif/0/flibble...
> Error in xenbus read: ENOENT
> (Should have said ENOENT)
> Thread "xenbus_tester" exited.
> T(s=1 us=1543)
> [...]
> 
> >> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> >> ---
> >>  extras/mini-os/test.c | 3 +--
> >>  1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >> diff --git a/extras/mini-os/test.c b/extras/mini-os/test.c
> >> index bbfc613..20d372b 100644
> >> --- a/extras/mini-os/test.c
> >> +++ b/extras/mini-os/test.c
> >> @@ -56,8 +56,7 @@ void test_xenbus(void);
> >>
> >>  static void xenbus_tester(void *p)
> >>  {
> >> -    printk("Xenbus tests disabled, because of a Xend bug.\n");
> >> -    /* test_xenbus(); */
> >> +    test_xenbus();
> >>  }
> >>  #endif
> >>
> >
> >
> 
> 
> 

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

* Re: [PATCH ARM v5 17/20] mini-os: headers for ARM
  2014-06-26 16:26   ` Julien Grall
@ 2014-06-27 13:02     ` Thomas Leonard
  2014-06-27 13:11       ` Ian Campbell
  0 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-27 13:02 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 26 June 2014 17:26, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
> On 06/26/2014 12:28 PM, Thomas Leonard wrote:
>> diff --git a/extras/mini-os/include/arm/hypercall-arm.h b/extras/mini-os/include/arm/hypercall-arm.h
>> new file mode 100644
>> index 0000000..6d862ff
>> --- /dev/null
>> +++ b/extras/mini-os/include/arm/hypercall-arm.h
>> +#ifndef __HYPERCALL_ARM_H__
>> +#define __HYPERCALL_ARM_H__
>> +
>> +#include <xen/xen.h>
>> +#include <xen/sched.h>
>> +#include <xen/xsm/flask_op.h>
>> +#include <mini-os/mm.h>
>
> Does all those includes relevant for hypercall-arm?

Removing any line except xen.h makes Mini-OS not compile.

hypercall-arm.h is normally included via hypervisor.h, which includes
xen.h itself, so that's perhaps not necessary, but it doesn't do any
harm.

Note that the x86 versions have the same include. There are a couple
of places where I've included other files in the ARM version of an
include just because the corresponding x86 file had it. Otherwise,
code that compiles on x86 may fail on ARM.

>> diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
>> new file mode 100644
>> index 0000000..bde8796
>> --- /dev/null
>> +++ b/extras/mini-os/include/arm/os.h
>
> [..]
>
>> +#define BUG() while(1){}
>
> It looks odd to use onely while (1). Shouldn't you call do_exit as x86 does?

Note that patch #20 changes this to dump the registers and stack.

[ also, exiting on BUG is annoying because you may lose the console
output if the VM dies before xl attaches to it. ]


-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 17/20] mini-os: headers for ARM
  2014-06-27 13:02     ` Thomas Leonard
@ 2014-06-27 13:11       ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 13:11 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On Fri, 2014-06-27 at 14:02 +0100, Thomas Leonard wrote:

> >> +#define BUG() while(1){}
> >
> > It looks odd to use onely while (1). Shouldn't you call do_exit as x86 does?
> 
> Note that patch #20 changes this to dump the registers and stack.
> 
> [ also, exiting on BUG is annoying because you may lose the console
> output if the VM dies before xl attaches to it. ]

That's what on_crash=preserve and xenconsoled's logging capabilities are
for. I expect SCHEDOP_crash is probably better than exiting though.

Ian.

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

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-26 11:38   ` Samuel Thibault
@ 2014-06-27 13:13     ` Ian Campbell
  2014-06-27 13:56       ` Thomas Leonard
  0 siblings, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 13:13 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: xen-devel, Thomas Leonard, stefano.stabellini, Dave.Scott, anil

On Thu, 2014-06-26 at 13:38 +0200, Samuel Thibault wrote:
> Thomas Leonard, le Thu 26 Jun 2014 12:28:28 +0100, a écrit :
> > Avoids using _hypercall1 in events.c.
> > 
> > Signed-off-by: Thomas Leonard <talex5@gmail.com>
> 
> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

On x86 this results in 

In file included from stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
                 from stubdom/../extras/mini-os/include/mini-os/lib.h:55,
                 from stubdom/../extras/mini-os/include/mini-os/mm.h:36,
                 from stubdom/../extras/mini-os/include/x86/x86_64/hypercall-x86_64.h:39,
                 from stubdom/../extras/mini-os/include/hypervisor.h:20,
                 from mini-os.c:13:
stubdom/../extras/mini-os/include/x86/os.h: In function ‘HYPERVISOR_xsm_op’:
stubdom/../extras/mini-os/include/x86/os.h:566:21: error: expected expression before ‘int’

I'm not sure why.

Ian.


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

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

* Re: [PATCH ARM v5 00/20] mini-os: initial ARM support
  2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
                   ` (19 preceding siblings ...)
  2014-06-26 11:28 ` [PATCH ARM v5 20/20] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
@ 2014-06-27 13:34 ` Ian Campbell
  20 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 13:34 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil


On Thu, 2014-06-26 at 12:28 +0100, Thomas Leonard wrote:
> Karim Raslan (4):
>   mini-os: switched initial C entry point to arch_init
>   mini-os: added arch_init_gnttab

> Thomas Leonard (16):
>   mini-os: build fixes
>   mini-os: fixed shutdown thread
>   mini-os: fixed format string error in unbind_evtchn
>   mini-os: use unbind_evtchn in unbind_all_ports
>   mini-os: made off_t type signed
>   mini-os: whitespace
>   mini-os: don't require XEN_HAVE_PV_UPCALL_MASK
>   mini-os: add missing casts to MM printk
>   mini-os: added arch_unbind_ports
>   mini-os: moved __pte to x86
>   mini-os: moved unlikely/likely macros to new compiler.h
>   mini-os: enable test_xenbus again
>   mini-os: use irqs_disabled() helper in schedule

I've applied all these. Skipping:

>   mini-os: added HYPERVISOR_xsm_op

(compile failure, YHM)

>  mini-os: headers for ARM

This had a comment or two. So I stopped at that point.

>   mini-os: import libfdt
> 
>   mini-os: initial ARM support
>   mini-os: arm: show registers, stack and exception vector on fault

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

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-27 13:13     ` Ian Campbell
@ 2014-06-27 13:56       ` Thomas Leonard
  2014-06-27 15:43         ` Thomas Leonard
  2014-06-27 16:47         ` Ian Campbell
  0 siblings, 2 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-27 13:56 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Samuel Thibault, Anil Madhavapeddy, David Scott,
	Stefano Stabellini, xen-devel

On 27 June 2014 14:13, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Thu, 2014-06-26 at 13:38 +0200, Samuel Thibault wrote:
>> Thomas Leonard, le Thu 26 Jun 2014 12:28:28 +0100, a écrit :
>> > Avoids using _hypercall1 in events.c.
>> >
>> > Signed-off-by: Thomas Leonard <talex5@gmail.com>
>>
>> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
>
> On x86 this results in
>
> In file included from stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
>                  from stubdom/../extras/mini-os/include/mini-os/lib.h:55,
>                  from stubdom/../extras/mini-os/include/mini-os/mm.h:36,
>                  from stubdom/../extras/mini-os/include/x86/x86_64/hypercall-x86_64.h:39,
>                  from stubdom/../extras/mini-os/include/hypervisor.h:20,
>                  from mini-os.c:13:
> stubdom/../extras/mini-os/include/x86/os.h: In function ‘HYPERVISOR_xsm_op’:
> stubdom/../extras/mini-os/include/x86/os.h:566:21: error: expected expression before ‘int’
>
> I'm not sure why.

That's strange. It compiles for me on x86_64 (running "make" in the
mini-os directory and also running "make" in "stubdom").

If you tell me the compiler/OS/arch you're on I can try to reproduce it.


-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-27 13:56       ` Thomas Leonard
@ 2014-06-27 15:43         ` Thomas Leonard
  2014-06-27 15:50           ` Samuel Thibault
  2014-06-27 16:47         ` Ian Campbell
  1 sibling, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-27 15:43 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Samuel Thibault, Anil Madhavapeddy, David Scott,
	Stefano Stabellini, xen-devel

On 27 June 2014 14:56, Thomas Leonard <talex5@gmail.com> wrote:
> On 27 June 2014 14:13, Ian Campbell <Ian.Campbell@citrix.com> wrote:
>> On Thu, 2014-06-26 at 13:38 +0200, Samuel Thibault wrote:
>>> Thomas Leonard, le Thu 26 Jun 2014 12:28:28 +0100, a écrit :
>>> > Avoids using _hypercall1 in events.c.
>>> >
>>> > Signed-off-by: Thomas Leonard <talex5@gmail.com>
>>>
>>> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
>>
>> On x86 this results in
>>
>> In file included from stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
>>                  from stubdom/../extras/mini-os/include/mini-os/lib.h:55,
>>                  from stubdom/../extras/mini-os/include/mini-os/mm.h:36,
>>                  from stubdom/../extras/mini-os/include/x86/x86_64/hypercall-x86_64.h:39,
>>                  from stubdom/../extras/mini-os/include/hypervisor.h:20,
>>                  from mini-os.c:13:
>> stubdom/../extras/mini-os/include/x86/os.h: In function ‘HYPERVISOR_xsm_op’:
>> stubdom/../extras/mini-os/include/x86/os.h:566:21: error: expected expression before ‘int’
>>
>> I'm not sure why.
>
> That's strange. It compiles for me on x86_64 (running "make" in the
> mini-os directory and also running "make" in "stubdom").
>
> If you tell me the compiler/OS/arch you're on I can try to reproduce it.

OK, I see this on x86_32. There's a (pre-existing) cycle in the includes:

hypervisor.h -> hypercall-x86_32.h -> mm.h -> lib.h -> gntmap.h ->
os.h -> hypervisor.h

I could break it at the mm.h -> lib.h link. I can't see why the
low-level MM code needs libc, and it seems to compile without it
(adding some lib.h includes in various C files instead). Any
objections?


-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-27 15:43         ` Thomas Leonard
@ 2014-06-27 15:50           ` Samuel Thibault
  0 siblings, 0 replies; 54+ messages in thread
From: Samuel Thibault @ 2014-06-27 15:50 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Ian Campbell,
	Anil Madhavapeddy

Hello,

Thomas Leonard, le Fri 27 Jun 2014 16:43:51 +0100, a écrit :
> I could break it at the mm.h -> lib.h link. I can't see why the
> low-level MM code needs libc,

I guess the reason has disappeared now

> and it seems to compile without it (adding some lib.h includes in
> various C files instead). Any objections?

It looks good to me.

Samuel

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

* Re: [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op
  2014-06-27 13:56       ` Thomas Leonard
  2014-06-27 15:43         ` Thomas Leonard
@ 2014-06-27 16:47         ` Ian Campbell
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-06-27 16:47 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: Samuel Thibault, Stefano Stabellini, xen-devel, David Scott,
	Anil Madhavapeddy

On Fri, 2014-06-27 at 14:56 +0100, Thomas Leonard wrote:
> On 27 June 2014 14:13, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Thu, 2014-06-26 at 13:38 +0200, Samuel Thibault wrote:
> >> Thomas Leonard, le Thu 26 Jun 2014 12:28:28 +0100, a écrit :
> >> > Avoids using _hypercall1 in events.c.
> >> >
> >> > Signed-off-by: Thomas Leonard <talex5@gmail.com>
> >>
> >> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> >
> > On x86 this results in
> >
> > In file included from stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
> >                  from stubdom/../extras/mini-os/include/mini-os/lib.h:55,
> >                  from stubdom/../extras/mini-os/include/mini-os/mm.h:36,
> >                  from stubdom/../extras/mini-os/include/x86/x86_64/hypercall-x86_64.h:39,
> >                  from stubdom/../extras/mini-os/include/hypervisor.h:20,
> >                  from mini-os.c:13:
> > stubdom/../extras/mini-os/include/x86/os.h: In function ‘HYPERVISOR_xsm_op’:
> > stubdom/../extras/mini-os/include/x86/os.h:566:21: error: expected expression before ‘int’
> >
> > I'm not sure why.
> 
> That's strange. It compiles for me on x86_64 (running "make" in the
> mini-os directory and also running "make" in "stubdom").
> 
> If you tell me the compiler/OS/arch you're on I can try to reproduce it.

Debian Wheezy. I run pre-commit build tests for both 32- and 64-bit but
I'm afraid I don't recall which one had this issue (I should have been
more specific with "x86" above, sorry).

Oh wait, does the fact that it is including hypercall-x86_64.h give us a
clue? I'm not sure if we cross compile stubdoms or not...

Ian.


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

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

* Re: [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-26 11:28 ` [PATCH ARM v5 18/20] mini-os: import libfdt Thomas Leonard
@ 2014-06-28 12:01   ` Julien Grall
  2014-06-28 12:27     ` Thomas Leonard
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2014-06-28 12:01 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 26/06/14 12:28, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>
> Looks like this is revision v1.3.0-47-gbe60268 from
> http://git.jdl.com/gitweb/?p=dtc.git

Unfortunately I can find this commit in the git tree. Do you have the 
full sha1?

AFAIU, you are using the version 1.3.0, right? If so, why didn't you get 
the latest version (i.e 1.4.0)?

> The memmove implementation is from FreeBSD's
> contrib/ldns/compat/memmove.c

Can you add a commit number just for tracking purpose?

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-28 12:01   ` Julien Grall
@ 2014-06-28 12:27     ` Thomas Leonard
  2014-06-28 15:14       ` Julien Grall
  0 siblings, 1 reply; 54+ messages in thread
From: Thomas Leonard @ 2014-06-28 12:27 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 28 June 2014 13:01, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
>
> On 26/06/14 12:28, Thomas Leonard wrote:
>>
>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>
>> Looks like this is revision v1.3.0-47-gbe60268 from
>> http://git.jdl.com/gitweb/?p=dtc.git
>
>
> Unfortunately I can find this commit in the git tree. Do you have the full
> sha1?

It works for me:

$ git clone git://git.jdl.com/software/dtc.git
$ cd dtc
$ git show be60268
commit be6026838e45b67800ac803f4ad8cca3cde57d6d
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Jun 1 14:12:38 2012 +1000

    libfdt: Add helper function to create a trivial, empty tree

> AFAIU, you are using the version 1.3.0, right? If so, why didn't you get the
> latest version (i.e 1.4.0)?

I don't know why this particular version was chosen. I could upgrade
it if you want. I don't think there are any functional changes
(uint32_t has been replaced by fdt32_t all over the place, and there
are a couple of extra functions, which we don't need).

>> The memmove implementation is from FreeBSD's
>> contrib/ldns/compat/memmove.c
>
>
> Can you add a commit number just for tracking purpose?

OK.


-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-28 12:27     ` Thomas Leonard
@ 2014-06-28 15:14       ` Julien Grall
  2014-06-28 16:35         ` Anil Madhavapeddy
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2014-06-28 15:14 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy



On 28/06/14 13:27, Thomas Leonard wrote:
> On 28 June 2014 13:01, Julien Grall <julien.grall@linaro.org> wrote:
>> Hi Thomas,
>>
>>
>> On 26/06/14 12:28, Thomas Leonard wrote:
>>>
>>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>>
>>> Looks like this is revision v1.3.0-47-gbe60268 from
>>> http://git.jdl.com/gitweb/?p=dtc.git
>>
>>
>> Unfortunately I can find this commit in the git tree. Do you have the full
>> sha1?
>
> It works for me:

Hmmm right, sorry for the noise. Even though, you shell command below 
show a tag but a commit ;).

> $ git clone git://git.jdl.com/software/dtc.git
> $ cd dtc
> $ git show be60268
> commit be6026838e45b67800ac803f4ad8cca3cde57d6d
> Author: David Gibson <david@gibson.dropbear.id.au>
> Date:   Fri Jun 1 14:12:38 2012 +1000
>
>      libfdt: Add helper function to create a trivial, empty tree
>
>> AFAIU, you are using the version 1.3.0, right? If so, why didn't you get the
>> latest version (i.e 1.4.0)?
>
> I don't know why this particular version was chosen. I could upgrade
> it if you want. I don't think there are any functional changes
> (uint32_t has been replaced by fdt32_t all over the place, and there
> are a couple of extra functions, which we don't need).

Just looking to the libfdt already embedded in xen (xen/common/libfdt) 
and it looks like we are using the same version.

I'm wondering if you could share the same code and avoid to have the 
libfdt imported twice in Xen. Any thoughts?

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-28 15:14       ` Julien Grall
@ 2014-06-28 16:35         ` Anil Madhavapeddy
  2014-06-28 16:45           ` Julien Grall
  0 siblings, 1 reply; 54+ messages in thread
From: Anil Madhavapeddy @ 2014-06-28 16:35 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Thomas Leonard, David Scott, Samuel Thibault,
	Stefano Stabellini

> On 28 Jun 2014, at 16:14, Julien Grall <julien.grall@linaro.org> wrote:
> 
> 
> 
>> On 28/06/14 13:27, Thomas Leonard wrote:
>>> On 28 June 2014 13:01, Julien Grall <julien.grall@linaro.org> wrote:
>>> Hi Thomas,
>>> 
>>> 
>>>> On 26/06/14 12:28, Thomas Leonard wrote:
>>>> 
>>>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>>> 
>>>> Looks like this is revision v1.3.0-47-gbe60268 from
>>>> http://git.jdl.com/gitweb/?p=dtc.git
>>> 
>>> 
>>> Unfortunately I can find this commit in the git tree. Do you have the full
>>> sha1?
>> 
>> It works for me:
> 
> Hmmm right, sorry for the noise. Even though, you shell command below show a tag but a commit ;).
> 
>> $ git clone git://git.jdl.com/software/dtc.git
>> $ cd dtc
>> $ git show be60268
>> commit be6026838e45b67800ac803f4ad8cca3cde57d6d
>> Author: David Gibson <david@gibson.dropbear.id.au>
>> Date:   Fri Jun 1 14:12:38 2012 +1000
>> 
>>     libfdt: Add helper function to create a trivial, empty tree
>> 
>>> AFAIU, you are using the version 1.3.0, right? If so, why didn't you get the
>>> latest version (i.e 1.4.0)?
>> 
>> I don't know why this particular version was chosen. I could upgrade
>> it if you want. I don't think there are any functional changes
>> (uint32_t has been replaced by fdt32_t all over the place, and there
>> are a couple of extra functions, which we don't need).
> 
> Just looking to the libfdt already embedded in xen (xen/common/libfdt) and it looks like we are using the same version.
> 
> I'm wondering if you could share the same code and avoid to have the libfdt imported twice in Xen. Any thoughts?

MiniOS really needs to be able to compile as a standalone repository and not depend on Xen's source code if at all possible. This also came up at the recent hackathon in the context of splitting it out of the main repository in the future.

-Anil

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

* Re: [PATCH ARM v5 18/20] mini-os: import libfdt
  2014-06-28 16:35         ` Anil Madhavapeddy
@ 2014-06-28 16:45           ` Julien Grall
  0 siblings, 0 replies; 54+ messages in thread
From: Julien Grall @ 2014-06-28 16:45 UTC (permalink / raw)
  To: Anil Madhavapeddy
  Cc: xen-devel, Thomas Leonard, David Scott, Samuel Thibault,
	Stefano Stabellini

Hi Anil,

On 28/06/14 17:35, Anil Madhavapeddy wrote:
>> On 28 Jun 2014, at 16:14, Julien Grall <julien.grall@linaro.org> wrote:
>>> On 28/06/14 13:27, Thomas Leonard wrote:
>>>> On 28 June 2014 13:01, Julien Grall <julien.grall@linaro.org> wrote:
>>> I don't know why this particular version was chosen. I could upgrade
>>> it if you want. I don't think there are any functional changes
>>> (uint32_t has been replaced by fdt32_t all over the place, and there
>>> are a couple of extra functions, which we don't need).
>>
>> Just looking to the libfdt already embedded in xen (xen/common/libfdt) and it looks like we are using the same version.
>>
>> I'm wondering if you could share the same code and avoid to have the libfdt imported twice in Xen. Any thoughts?
>
> MiniOS really needs to be able to compile as a standalone repository and not depend on Xen's source code if at all possible. This also came up at the recent hackathon in the context of splitting it out of the main repository in the future.

Thanks for the answer, I didn't follow this session at the Hackthon so I 
wasn't not aware about this plan.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-26 11:28 ` [PATCH ARM v5 19/20] mini-os: initial ARM support Thomas Leonard
@ 2014-06-28 18:31   ` Julien Grall
  2014-06-30 19:12     ` Thomas Leonard
  0 siblings, 1 reply; 54+ messages in thread
From: Julien Grall @ 2014-06-28 18:31 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil



On 26/06/14 12:28, Thomas Leonard wrote:
> On ARM, Mini-OS will boot and display some output on the console.
> Tested with:
>
> make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
> 	CONFIG_TEST=y CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
> 	CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
> 	CONFIG_CONSFRONT=n CONFIG_XC=n -j4
>
> 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]
> [talex5@gmail.com: re-enabled force_evtchn_callback]
> [talex5@gmail.com: enable regular console]
> [talex5@gmail.com: fixed initialisation code:
> - Configure write-back caching in page table. This is needed for
>    reliable hypercalls to Xen (thanks to Julien Grall).
> - Use "client mode" for access control (domains are deprecated,
>    according to ARM Cortex-A Series Programmer’s Guide version 4.0,
>    section 9.6.4).
> - Enable more SCTLR features (icache, branch prediction)]
> [talex5@gmail.com: use Virtual Count register for monotonic time]
> [talex5@gmail.com: fixed HYPERVISOR_shutdown]
> [talex5@gmail.com: get xenstore details from hypervisor]
> [talex5@gmail.com: use GCC implementation of division]
> [talex5@gmail.com: cleaned up interrupt handlers and threading]
> [talex5@gmail.com: call exit_thread when a thread returns]
> [talex5@gmail.com: implemented block_domain for ARM]
> [talex5@gmail.com: fixed hang when enabling interrupts]
> [talex5@gmail.com: added -march=armv7-a to flags]
> [talex5@gmail.com: CLREX after handling IRQs]
> [talex5@gmail.com: unbind debug port at shutdown]
> [talex5@gmail.com: allow unaligned accesses]
> [talex5@gmail.com: fix zImage header for XSA-95]
> [talex5@gmail.com: get RAM base and size from the FDT]
> [talex5@gmail.com: get GIC addresses from FDT]
> [talex5@gmail.com: added ARM grant table initialisation]
> [talex5@gmail.com: added missing copyright header to hypercalls32.S]
> [talex5@gmail.com: moved GIC driver to arm directory]
> [talex5@gmail.com: fixes suggested by Julien Grall:
> - Removed unnecessary isb.
> - Renamed GICD_PRIORITY to GICD_IPRIORITYR.
> - Change IRQ number type from unsigned char to int.
> - Added volatile to {set,clear}_bit_non_atomic.
> - Fixed some comments.
> - Check compatible properties in DTB.]
> [talex5@gmail.com: made image relocatable]
> [talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn]

IHMO all these changes doesn't belong to the commit message, i.e should 
not appear in the commit message when Ian will apply your commit message.

I would move them in a changelog. You can separate the commit message 
and the changelog by --- and a newline. Everything after the --- will be 
removed by git am.

> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>   extras/mini-os/ARM-TODO.txt              |   6 +
>   extras/mini-os/Config.mk                 |   2 +
>   extras/mini-os/Makefile                  |   9 ++
>   extras/mini-os/arch/arm/Makefile         |  32 ++++
>   extras/mini-os/arch/arm/arch.mk          |   7 +
>   extras/mini-os/arch/arm/arm32.S          | 266 +++++++++++++++++++++++++++++++
>   extras/mini-os/arch/arm/events.c         |  30 ++++
>   extras/mini-os/arch/arm/gic.c            | 222 ++++++++++++++++++++++++++
>   extras/mini-os/arch/arm/hypercalls32.S   |  75 +++++++++
>   extras/mini-os/arch/arm/minios-arm32.lds |  75 +++++++++
>   extras/mini-os/arch/arm/mm.c             | 134 ++++++++++++++++
>   extras/mini-os/arch/arm/sched.c          |  37 +++++
>   extras/mini-os/arch/arm/setup.c          | 116 ++++++++++++++
>   extras/mini-os/arch/arm/time.c           | 202 +++++++++++++++++++++++
>   extras/mini-os/kernel.c                  |   2 +-
>   15 files changed, 1214 insertions(+), 1 deletion(-)
>   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/events.c
>   create mode 100644 extras/mini-os/arch/arm/gic.c
>   create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>   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/sched.c
>   create mode 100644 extras/mini-os/arch/arm/setup.c
>   create mode 100644 extras/mini-os/arch/arm/time.c
>
> 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 931cd05..01d8af0 100644
> --- a/extras/mini-os/Makefile
> +++ b/extras/mini-os/Makefile
> @@ -78,6 +78,9 @@ TARGET := mini-os
>   SUBDIRS := lib xenbus console
>
>   ifeq ($(XEN_TARGET_ARCH),arm32)
> +# Need libgcc.a for division helpers
> +LDLIBS += `$(CC) -print-libgcc-file-name`

OOI, how much code does add libgcc for the division helpers?

> diff --git a/extras/mini-os/arch/arm/Makefile b/extras/mini-os/arch/arm/Makefile
> new file mode 100755
> index 0000000..8b78651
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/Makefile
> @@ -0,0 +1,32 @@
> +#
> +# ARM architecture specific makefiles.
> +#
> +
> +XEN_ROOT = $(CURDIR)/../../../..
> +include $(XEN_ROOT)/Config.mk
> +include ../../Config.mk
> +
> +# include arch.mk has to be before minios.mk!
> +
> +include arch.mk
> +include ../../minios.mk
> +
> +# Sources here are all *.c (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
> +
> +all: $(OBJ_DIR)/$(ARCH_LIB)
> +
> +# $(HEAD_ARCH_OBJ) is only built 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..ab20d99
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/arch.mk
> @@ -0,0 +1,7 @@
> +ifeq ($(XEN_TARGET_ARCH),arm32)
> +DEF_ASFLAGS += -march=armv7-a
> +ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__ -DXEN_HAVE_PV_GUEST_ENTRY #-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..de74ed9
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/arm32.S
> @@ -0,0 +1,266 @@
> +@ Virtual address of the start of RAM (any value will do, but it must be
> +@ section-aligned). Update the lds script if changed.
> +#define VIRT_BASE 0x400000
> +
> +@ Offset of the kernel within the RAM. This is a zImage convention which we
> +@ rely on.
> +#define ZIMAGE_KERNEL_OFFSET 0x8000

Hmmm... this is not a zImage convention... IIRC Linux is using this 
offset to have enough space to create startup page table during boot.

The Linux zImage is able to relocate itself in the memory to respect 
this convention. But the zImage itself can be loaded anywhere in the memory.

By looking to your code below your are relying that the kernel will be 
loaded at 0xXXXX8000 which is incorrect. This offset is odd and make 
other kernel (such as FreeBSD) requiring the same trick which is not 
part of the Linux boot protocol.

I plan to send a patch to require the start address to be 2MB aligned, 
so kernels will be able to use 2MB (for LPAE) and 1MB section for there 
early page table.

If the kernel wants another alignment, then you will have to relocate 
yourself. Even though in your case, you don't need this odd 0xXXXX8000.

[..]

> +	@ Fill in the whole top-level translation table (at page_dir).
> +	@ Populate the whole pagedir with 1MB section descriptors.
> +
> +	mov	r1, r7			@ r1 -> first section entry
> +	add	r3, r1, #4*4*1024	@ limit (4 GB address space, 4 byte entries)
> +	orr	r0, r8, r9		@ r0 = entry mapping section zero to start of physical RAM
> +1:
> +	str	r0, [r1],#4		@ write the section entry
> +	add	r0, r0, #1 << 20 	@ next physical page (wraps)
> +	cmp	r1, r3
> +	bne	1b

I would document a bit more this part. It took me a bit of time to 
understand that you mapping the whole address space in an odd manner.

While it's fine for a first version of Mini-OS support for ARM. It think 
at long term you want to map only necessary bank rank. It will be easier 
to catch programming error and avoid to trap in the hypervisor because 
the physical address doesn't exist.

Futhermore, the data abort sent by the hypervisor is odd (debug smth).

> +.pushsection .data
> +_data:
> +.align	14
> +.globl page_dir
> +@ Each word maps one 1MB virtual section to a physical section
> +page_dir:
> +	.fill (4*1024), 4, 0x0
> +
> +.align 12
> +.globl shared_info_page
> +shared_info_page:
> +	.fill (1024), 4, 0x0
> +
> +.align 3
> +.globl stack
> +stack:
> +	.fill (4*1024), 4, 0x0
> +stack_end:
> +
> +.align 3
> +irqstack:
> +	.fill (1024), 4, 0x0
> +irqstack_end:
> +
> +.globl physical_address_offset
> +physical_address_offset:
> +	.long 	0
> +
> +.popsection

Any reason to define theses variables in ASM rather than C?

> diff --git a/extras/mini-os/arch/arm/gic.c b/extras/mini-os/arch/arm/gic.c
> new file mode 100644
> index 0000000..5641eb0
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/gic.c
> @@ -0,0 +1,222 @@
> +// ARM GIC implementation
> +
> +#include <mini-os/os.h>
> +#include <mini-os/hypervisor.h>
> +#include <libfdt.h>
> +
> +//#define VGIC_DEBUG
> +#ifdef VGIC_DEBUG
> +#define DEBUG(_f, _a...) \
> +    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)

Did you intend to use printk here?

[..]

> +void gic_init(void) {
> +    gic.gicd_base = NULL;
> +    int node = 0;
> +    int depth = 0;
> +    for (;;)
> +    {
> +        node = fdt_next_node(device_tree, node, &depth);
> +        if (node <= 0 || depth < 0)
> +            break;
> +
> +        if (fdt_getprop(device_tree, node, "interrupt-controller", NULL)) {
> +            int len = 0;
> +
> +            if (fdt_node_check_compatible(device_tree, node, "arm,cortex-a15-gic") &&
> +                fdt_node_check_compatible(device_tree, node, "arm,cortex-a9-gic") &&

I don't think this compatible is necessary. Cortex A9 doesn't support 
virtualisation.

> +                fdt_node_check_compatible(device_tree, node, "arm,cortex-a7-gic")) {
> +                printk("Skipping incompatible interrupt-controller node\n");
> +                continue;
> +            }
> +
> +            const uint64_t *reg = fdt_getprop(device_tree, node, "reg", &len);
> +            if (reg == NULL || len != 32) {

As asked on the previous version, if you plan to assume specific range 
size for the time-being, please explain the 32.

> +                /* TODO: support other formats */
> +                printk("Bad 'reg' property: %p %d\n", reg, len);
> +                continue;
> +            }
> +            gic.gicd_base = to_virt((long) fdt64_to_cpu(reg[0]));
> +            gic.gicc_base = to_virt((long) fdt64_to_cpu(reg[2]));

AFAIU, your are mapping the GIC region with normal attribute. With this 
attribute, the processor may reorder the write in the device memory, 
preload memory, caching.... Which is completely wrong in this case. I'm 
sa bit surprised that it works correctly. You have to map thoses regions 
as device memory.

[..]

> diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
> new file mode 100644
> index 0000000..0d7662d
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/hypercalls32.S

[..]

> +#define __HYPERVISOR_memory_op            12
> +#define __HYPERVISOR_xen_version          17
> +#define __HYPERVISOR_console_io           18
> +#define __HYPERVISOR_grant_table_op       20
> +#define __HYPERVISOR_vcpu_op              24
> +#define __HYPERVISOR_xsm_op               27
> +#define __HYPERVISOR_sched_op             29
> +#define __HYPERVISOR_event_channel_op     32
> +#define __HYPERVISOR_physdev_op           33
> +#define __HYPERVISOR_hvm_op               34
> +#define __HYPERVISOR_sysctl               35
> +#define __HYPERVISOR_domctl               36

Hmmm... why do you hardcode those numbers here? Can't you include the 
correct header?

[..]

> 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..b18ca55
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/minios-arm32.lds
> @@ -0,0 +1,75 @@
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> +  . = 0x408000;

I would use the preprocessor to avoid hardcoding address here. It will 
help later if someone wants to change the virtual address of the kernel.

[..]

> diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c


[..]

> +void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)

[..]

> +
> +    /* Xen will always provide us at least one bank of memory.
> +     * Mini-OS will use the first bank for the time-being. */
> +    regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
> +    if (regs == NULL || prop_len != 16) {

Same remark as in gic_init. Please explain where does come from the 16.

[..]

> +        /* TODO: support other formats */
> +        printk("Bad 'reg' property: %p %d\n", regs, prop_len);
> +        BUG();
> +    }
> +
> +    unsigned int end = (unsigned int) &_end;
> +    unsigned int mem_base = fdt64_to_cpu(regs[0]);
> +    unsigned int mem_size = fdt64_to_cpu(regs[1]);

In general if you have to cast/create a variable to contain a physical 
address. Please make create a type paddr_t and use it.

When someone will implement arm64 support it will have less trouble 
because we cast correctly cast the value.

IIRC, there is few other place where it's the same problem.

> +/* Get Xen's suggested physical page assignments for the grant table. */
> +static unsigned long get_gnttab_base(void)
> +{
> +    int hypervisor;
> +    int len = 0;
> +    const uint64_t *regs;
> +    unsigned int gnttab_base;
> +
> +    hypervisor = fdt_node_offset_by_compatible(device_tree, -1, "xen,xen");
> +    BUG_ON(hypervisor < 0);
> +
> +    regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
> +    if (regs == NULL || len != 16) {
> +        /* TODO: support other formats */

Please explain why the 16.

> +        printk("Bad 'reg' property: %p %d\n", regs, len);
> +        BUG();
> +    }
> +
> +    gnttab_base = fdt64_to_cpu(regs[0]);

This look odd... you are using unsigned int for the variable but the 
function is return unsigned long.

> +    printk("FDT suggests grant table base %lx\n", gnttab_base);
> +
> +    return gnttab_base;
> +}

[..]

Regards,

-- 
Julien Grall

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

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

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-28 18:31   ` Julien Grall
@ 2014-06-30 19:12     ` Thomas Leonard
  2014-06-30 21:08       ` Julien Grall
  2014-07-02  8:23       ` Ian Campbell
  0 siblings, 2 replies; 54+ messages in thread
From: Thomas Leonard @ 2014-06-30 19:12 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 28 June 2014 19:31, Julien Grall <julien.grall@linaro.org> wrote:
>
>
> On 26/06/14 12:28, Thomas Leonard wrote:
>>
>> On ARM, Mini-OS will boot and display some output on the console.
>> Tested with:
>>
>> make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
>>         CONFIG_TEST=y CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
>>         CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
>>         CONFIG_CONSFRONT=n CONFIG_XC=n -j4
>>
>> 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]
>> [talex5@gmail.com: re-enabled force_evtchn_callback]
>> [talex5@gmail.com: enable regular console]
>> [talex5@gmail.com: fixed initialisation code:
>> - Configure write-back caching in page table. This is needed for
>>    reliable hypercalls to Xen (thanks to Julien Grall).
>> - Use "client mode" for access control (domains are deprecated,
>>    according to ARM Cortex-A Series Programmer’s Guide version 4.0,
>>    section 9.6.4).
>> - Enable more SCTLR features (icache, branch prediction)]
>> [talex5@gmail.com: use Virtual Count register for monotonic time]
>> [talex5@gmail.com: fixed HYPERVISOR_shutdown]
>> [talex5@gmail.com: get xenstore details from hypervisor]
>> [talex5@gmail.com: use GCC implementation of division]
>> [talex5@gmail.com: cleaned up interrupt handlers and threading]
>> [talex5@gmail.com: call exit_thread when a thread returns]
>> [talex5@gmail.com: implemented block_domain for ARM]
>> [talex5@gmail.com: fixed hang when enabling interrupts]
>> [talex5@gmail.com: added -march=armv7-a to flags]
>> [talex5@gmail.com: CLREX after handling IRQs]
>> [talex5@gmail.com: unbind debug port at shutdown]
>> [talex5@gmail.com: allow unaligned accesses]
>> [talex5@gmail.com: fix zImage header for XSA-95]
>> [talex5@gmail.com: get RAM base and size from the FDT]
>> [talex5@gmail.com: get GIC addresses from FDT]
>> [talex5@gmail.com: added ARM grant table initialisation]
>> [talex5@gmail.com: added missing copyright header to hypercalls32.S]
>> [talex5@gmail.com: moved GIC driver to arm directory]
>> [talex5@gmail.com: fixes suggested by Julien Grall:
>> - Removed unnecessary isb.
>> - Renamed GICD_PRIORITY to GICD_IPRIORITYR.
>> - Change IRQ number type from unsigned char to int.
>> - Added volatile to {set,clear}_bit_non_atomic.
>> - Fixed some comments.
>> - Check compatible properties in DTB.]
>> [talex5@gmail.com: made image relocatable]
>> [talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn]
>
>
> IHMO all these changes doesn't belong to the commit message, i.e should not
> appear in the commit message when Ian will apply your commit message.

As I understand it, as I'm not the author of the patch, it's polite to
indicate how I have modified it. I'm trying to follow the guidelines
here:

"Rule (b) allows you to adjust the code, but then it is very impolite
to change one submitter's code and make him endorse your bugs. To
solve this problem, it is recommended that you add a line between the
last Signed-off-by header and yours, indicating the nature of your
changes."

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/SubmittingPatches?id=4e8a2372f9255a1464ef488ed925455f53fbdaa1#n338

> I would move them in a changelog. You can separate the commit message and
> the changelog by --- and a newline. Everything after the --- will be removed
> by git am.
>
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>> ---
>>   extras/mini-os/ARM-TODO.txt              |   6 +
>>   extras/mini-os/Config.mk                 |   2 +
>>   extras/mini-os/Makefile                  |   9 ++
>>   extras/mini-os/arch/arm/Makefile         |  32 ++++
>>   extras/mini-os/arch/arm/arch.mk          |   7 +
>>   extras/mini-os/arch/arm/arm32.S          | 266
>> +++++++++++++++++++++++++++++++
>>   extras/mini-os/arch/arm/events.c         |  30 ++++
>>   extras/mini-os/arch/arm/gic.c            | 222
>> ++++++++++++++++++++++++++
>>   extras/mini-os/arch/arm/hypercalls32.S   |  75 +++++++++
>>   extras/mini-os/arch/arm/minios-arm32.lds |  75 +++++++++
>>   extras/mini-os/arch/arm/mm.c             | 134 ++++++++++++++++
>>   extras/mini-os/arch/arm/sched.c          |  37 +++++
>>   extras/mini-os/arch/arm/setup.c          | 116 ++++++++++++++
>>   extras/mini-os/arch/arm/time.c           | 202 +++++++++++++++++++++++
>>   extras/mini-os/kernel.c                  |   2 +-
>>   15 files changed, 1214 insertions(+), 1 deletion(-)
>>   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/events.c
>>   create mode 100644 extras/mini-os/arch/arm/gic.c
>>   create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>>   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/sched.c
>>   create mode 100644 extras/mini-os/arch/arm/setup.c
>>   create mode 100644 extras/mini-os/arch/arm/time.c
>>
>> 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 931cd05..01d8af0 100644
>> --- a/extras/mini-os/Makefile
>> +++ b/extras/mini-os/Makefile
>> @@ -78,6 +78,9 @@ TARGET := mini-os
>>   SUBDIRS := lib xenbus console
>>
>>   ifeq ($(XEN_TARGET_ARCH),arm32)
>> +# Need libgcc.a for division helpers
>> +LDLIBS += `$(CC) -print-libgcc-file-name`
>
>
> OOI, how much code does add libgcc for the division helpers?

Hard to say. libgcc.a contains many files, but the ones with "div" in
the name come to about 67K, so probably less than that.

>> diff --git a/extras/mini-os/arch/arm/Makefile
>> b/extras/mini-os/arch/arm/Makefile
>> new file mode 100755
>> index 0000000..8b78651
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/Makefile
>> @@ -0,0 +1,32 @@
>> +#
>> +# ARM architecture specific makefiles.
>> +#
>> +
>> +XEN_ROOT = $(CURDIR)/../../../..
>> +include $(XEN_ROOT)/Config.mk
>> +include ../../Config.mk
>> +
>> +# include arch.mk has to be before minios.mk!
>> +
>> +include arch.mk
>> +include ../../minios.mk
>> +
>> +# Sources here are all *.c (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
>> +
>> +all: $(OBJ_DIR)/$(ARCH_LIB)
>> +
>> +# $(HEAD_ARCH_OBJ) is only built 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..ab20d99
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/arch.mk
>> @@ -0,0 +1,7 @@
>> +ifeq ($(XEN_TARGET_ARCH),arm32)
>> +DEF_ASFLAGS += -march=armv7-a
>> +ARCH_CFLAGS  := -march=armv7-a -marm -fms-extensions -D__arm__
>> -DXEN_HAVE_PV_GUEST_ENTRY #-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..de74ed9
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/arm32.S
>> @@ -0,0 +1,266 @@
>> +@ Virtual address of the start of RAM (any value will do, but it must be
>> +@ section-aligned). Update the lds script if changed.
>> +#define VIRT_BASE 0x400000
>> +
>> +@ Offset of the kernel within the RAM. This is a zImage convention which
>> we
>> +@ rely on.
>> +#define ZIMAGE_KERNEL_OFFSET 0x8000
>
>
> Hmmm... this is not a zImage convention... IIRC Linux is using this offset
> to have enough space to create startup page table during boot.

OK, so this is a convention of Linux only? I found this reference:

http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html

"Despite the ability to place zImage anywhere within memory,
convention has it that it is loaded at the base of physical RAM plus
an offset of 0x8000 (32K). This leaves space for the parameter block
usually placed at offset 0x100, zero page exception vectors and page
tables. This convention is *very* common."

> The Linux zImage is able to relocate itself in the memory to respect this
> convention. But the zImage itself can be loaded anywhere in the memory.
>
> By looking to your code below your are relying that the kernel will be
> loaded at 0xXXXX8000 which is incorrect. This offset is odd and make other
> kernel (such as FreeBSD) requiring the same trick which is not part of the
> Linux boot protocol.

Sorry, I don't understand this. You're saying that Xen's choice of
0x8000 forces FreeBSD to support this offset too? But that isn't
caused by anything in Mini-OS.

> I plan to send a patch to require the start address to be 2MB aligned, so
> kernels will be able to use 2MB (for LPAE) and 1MB section for there early
> page table.
>
> If the kernel wants another alignment, then you will have to relocate
> yourself. Even though in your case, you don't need this odd 0xXXXX8000.

It's very convenient to know at least the offset where we will be
loaded. Otherwise, we have to move the image around in memory with
loads and stores. I think there is some work going on to share images
between VMs (for running large numbers of VMs on one machine). I don't
know the details, but presumably it would be easier to support that if
the image's text section can be mapped read-only.

> [..]
>
>
>> +       @ Fill in the whole top-level translation table (at page_dir).
>> +       @ Populate the whole pagedir with 1MB section descriptors.
>> +
>> +       mov     r1, r7                  @ r1 -> first section entry
>> +       add     r3, r1, #4*4*1024       @ limit (4 GB address space, 4
>> byte entries)
>> +       orr     r0, r8, r9              @ r0 = entry mapping section zero
>> to start of physical RAM
>> +1:
>> +       str     r0, [r1],#4             @ write the section entry
>> +       add     r0, r0, #1 << 20        @ next physical page (wraps)
>> +       cmp     r1, r3
>> +       bne     1b
>
>
> I would document a bit more this part. It took me a bit of time to
> understand that you mapping the whole address space in an odd manner.

Could you suggest something? It's hard to know what other people will
find confusing. For reference, here's the existing comment in the code
where I tried to explain the scheme:

    @ Problem: the C code wants to be at a known address (VIRT_BASE),
but Xen might
    @ load us anywhere. We initialise the MMU (mapping virtual to
physical @ addresses)
    @ so everything ends up where the code expects it to be.
    @
    @ We calculate the offet between where the linker thought _start
would be and where
    @ it actually is and initialise the page tables to have that
offset for every page.
    @
    @ When we turn on the MMU, we're still executing at the old
address. We don't want
    @ the code to disappear from under us. So we have to do the
mapping in stages:
    @
    @ 1. set up a mapping to our current page from both its current
and desired addresses
    @ 2. enable the MMU
    @ 3. jump to the new address
    @ 4. remap all the other pages with the calculated offset

> While it's fine for a first version of Mini-OS support for ARM. It think at
> long term you want to map only necessary bank rank. It will be easier to
> catch programming error and avoid to trap in the hypervisor because the
> physical address doesn't exist.

Yes, this is just the boot code. Eventually, the C code should make
the .text read-only (and unmap pages that don't exist, although I
don't think there's currently any disadvantage to having the trap
caused by the second stage page tables). I also want to add guard
pages to the thread stacks once these initial patches are in.

> Futhermore, the data abort sent by the hypervisor is odd (debug smth).

Could you explain what you mean by "odd" here?

>> +.pushsection .data
>> +_data:
>> +.align 14
>> +.globl page_dir
>> +@ Each word maps one 1MB virtual section to a physical section
>> +page_dir:
>> +       .fill (4*1024), 4, 0x0
>> +
>> +.align 12
>> +.globl shared_info_page
>> +shared_info_page:
>> +       .fill (1024), 4, 0x0
>> +
>> +.align 3
>> +.globl stack
>> +stack:
>> +       .fill (4*1024), 4, 0x0
>> +stack_end:
>> +
>> +.align 3
>> +irqstack:
>> +       .fill (1024), 4, 0x0
>> +irqstack_end:
>> +
>> +.globl physical_address_offset
>> +physical_address_offset:
>> +       .long   0
>> +
>> +.popsection
>
>
> Any reason to define theses variables in ASM rather than C?

I normally prefer to define variables in the module that sets them,
but it doesn't make much difference to me.

Though perhaps they should be moved to the .bss section (except for
the page table, which could be moved to the start of RAM to simplify
things).

>> diff --git a/extras/mini-os/arch/arm/gic.c b/extras/mini-os/arch/arm/gic.c
>> new file mode 100644
>> index 0000000..5641eb0
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/gic.c
>> @@ -0,0 +1,222 @@
>> +// ARM GIC implementation
>> +
>> +#include <mini-os/os.h>
>> +#include <mini-os/hypervisor.h>
>> +#include <libfdt.h>
>> +
>> +//#define VGIC_DEBUG
>> +#ifdef VGIC_DEBUG
>> +#define DEBUG(_f, _a...) \
>> +    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)
>
>
> Did you intend to use printk here?

It does look odd. I'll take a look.

> [..]
>
>
>> +void gic_init(void) {
>> +    gic.gicd_base = NULL;
>> +    int node = 0;
>> +    int depth = 0;
>> +    for (;;)
>> +    {
>> +        node = fdt_next_node(device_tree, node, &depth);
>> +        if (node <= 0 || depth < 0)
>> +            break;
>> +
>> +        if (fdt_getprop(device_tree, node, "interrupt-controller", NULL))
>> {
>> +            int len = 0;
>> +
>> +            if (fdt_node_check_compatible(device_tree, node,
>> "arm,cortex-a15-gic") &&
>> +                fdt_node_check_compatible(device_tree, node,
>> "arm,cortex-a9-gic") &&
>
>
> I don't think this compatible is necessary. Cortex A9 doesn't support
> virtualisation.

OK. I was just matching on the values that Xen provides. a15-gic
should be fine on its own, though.

>> +                fdt_node_check_compatible(device_tree, node,
>> "arm,cortex-a7-gic")) {
>> +                printk("Skipping incompatible interrupt-controller
>> node\n");
>> +                continue;
>> +            }
>> +
>> +            const uint64_t *reg = fdt_getprop(device_tree, node, "reg",
>> &len);
>> +            if (reg == NULL || len != 32) {
>
>
> As asked on the previous version, if you plan to assume specific range size
> for the time-being, please explain the 32.

OK, so we have two registers (GICC and GICD), each of which contains
two parts (an address and a size), each of which is a 64-bit value (8
bytes). So 2 * 2 * 8 = 32. Should I check this as a minimum, or
require it to match exactly?

>> +                /* TODO: support other formats */
>> +                printk("Bad 'reg' property: %p %d\n", reg, len);
>> +                continue;
>> +            }
>> +            gic.gicd_base = to_virt((long) fdt64_to_cpu(reg[0]));
>> +            gic.gicc_base = to_virt((long) fdt64_to_cpu(reg[2]));
>
>
> AFAIU, your are mapping the GIC region with normal attribute. With this
> attribute, the processor may reorder the write in the device memory, preload
> memory, caching.... Which is completely wrong in this case. I'm sa bit
> surprised that it works correctly. You have to map thoses regions as device
> memory.

I believe that the ARM uses the most restrictive memory type from the
two stages of the translation table, so if Xen maps it as device
memory then it will work. We can set it here as well, though.

(see "Overlaying the memory type attribute" in the Architecture
Reference Manual)

> [..]
>
>
>> diff --git a/extras/mini-os/arch/arm/hypercalls32.S
>> b/extras/mini-os/arch/arm/hypercalls32.S
>> new file mode 100644
>> index 0000000..0d7662d
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/hypercalls32.S
>
>
> [..]
>
>
>> +#define __HYPERVISOR_memory_op            12
>> +#define __HYPERVISOR_xen_version          17
>> +#define __HYPERVISOR_console_io           18
>> +#define __HYPERVISOR_grant_table_op       20
>> +#define __HYPERVISOR_vcpu_op              24
>> +#define __HYPERVISOR_xsm_op               27
>> +#define __HYPERVISOR_sched_op             29
>> +#define __HYPERVISOR_event_channel_op     32
>> +#define __HYPERVISOR_physdev_op           33
>> +#define __HYPERVISOR_hvm_op               34
>> +#define __HYPERVISOR_sysctl               35
>> +#define __HYPERVISOR_domctl               36
>
>
> Hmmm... why do you hardcode those numbers here? Can't you include the
> correct header?

Good idea.

> [..]
>
>
>> 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..b18ca55
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/minios-arm32.lds
>> @@ -0,0 +1,75 @@
>> +OUTPUT_ARCH(arm)
>> +ENTRY(_start)
>> +SECTIONS
>> +{
>> +  . = 0x408000;
>
>
> I would use the preprocessor to avoid hardcoding address here. It will help
> later if someone wants to change the virtual address of the kernel.

OK.

> [..]
>
>> diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
>
>
>
> [..]
>
>
>> +void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)
>
>
> [..]
>
>
>> +
>> +    /* Xen will always provide us at least one bank of memory.
>> +     * Mini-OS will use the first bank for the time-being. */
>> +    regs = fdt_getprop(device_tree, memory, "reg", &prop_len);
>> +    if (regs == NULL || prop_len != 16) {
>
>
> Same remark as in gic_init. Please explain where does come from the 16.

OK.

> [..]
>
>
>> +        /* TODO: support other formats */
>> +        printk("Bad 'reg' property: %p %d\n", regs, prop_len);
>> +        BUG();
>> +    }
>> +
>> +    unsigned int end = (unsigned int) &_end;
>> +    unsigned int mem_base = fdt64_to_cpu(regs[0]);
>> +    unsigned int mem_size = fdt64_to_cpu(regs[1]);
>
>
> In general if you have to cast/create a variable to contain a physical
> address. Please make create a type paddr_t and use it.
>
> When someone will implement arm64 support it will have less trouble because
> we cast correctly cast the value.

Good idea.

> IIRC, there is few other place where it's the same problem.
>
>
>> +/* Get Xen's suggested physical page assignments for the grant table. */
>> +static unsigned long get_gnttab_base(void)
>> +{
>> +    int hypervisor;
>> +    int len = 0;
>> +    const uint64_t *regs;
>> +    unsigned int gnttab_base;
>> +
>> +    hypervisor = fdt_node_offset_by_compatible(device_tree, -1,
>> "xen,xen");
>> +    BUG_ON(hypervisor < 0);
>> +
>> +    regs = fdt_getprop(device_tree, hypervisor, "reg", &len);
>> +    if (regs == NULL || len != 16) {
>> +        /* TODO: support other formats */
>
>
> Please explain why the 16.

OK.

>> +        printk("Bad 'reg' property: %p %d\n", regs, len);
>> +        BUG();
>> +    }
>> +
>> +    gnttab_base = fdt64_to_cpu(regs[0]);
>
>
> This look odd... you are using unsigned int for the variable but the
> function is return unsigned long.

OK.

>> +    printk("FDT suggests grant table base %lx\n", gnttab_base);
>> +
>> +    return gnttab_base;
>> +}
>
>
> [..]
>
> Regards,
>
> --
> Julien Grall

Thanks,


-- 
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] 54+ messages in thread

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-30 19:12     ` Thomas Leonard
@ 2014-06-30 21:08       ` Julien Grall
  2014-07-02  8:41         ` Ian Campbell
  2014-07-02  8:23       ` Ian Campbell
  1 sibling, 1 reply; 54+ messages in thread
From: Julien Grall @ 2014-06-30 21:08 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

Hi Thomas,

On 30/06/14 20:12, Thomas Leonard wrote:
> On 28 June 2014 19:31, Julien Grall <julien.grall@linaro.org> wrote:
>>
>>
>> On 26/06/14 12:28, Thomas Leonard wrote:
>>>
>>> On ARM, Mini-OS will boot and display some output on the console.
>>> Tested with:
>>>
>>> make XEN_TARGET_ARCH=arm32 CROSS_COMPILE=arm-linux-gnueabihf- \
>>>          CONFIG_TEST=y CONFIG_START_NETWORK=n CONFIG_BLKFRONT=n \
>>>          CONFIG_NETFRONT=n CONFIG_FBFRONT=n CONFIG_KBDFRONT=n \
>>>          CONFIG_CONSFRONT=n CONFIG_XC=n -j4
>>>
>>> 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]
>>> [talex5@gmail.com: re-enabled force_evtchn_callback]
>>> [talex5@gmail.com: enable regular console]
>>> [talex5@gmail.com: fixed initialisation code:
>>> - Configure write-back caching in page table. This is needed for
>>>     reliable hypercalls to Xen (thanks to Julien Grall).
>>> - Use "client mode" for access control (domains are deprecated,
>>>     according to ARM Cortex-A Series Programmer’s Guide version 4.0,
>>>     section 9.6.4).
>>> - Enable more SCTLR features (icache, branch prediction)]
>>> [talex5@gmail.com: use Virtual Count register for monotonic time]
>>> [talex5@gmail.com: fixed HYPERVISOR_shutdown]
>>> [talex5@gmail.com: get xenstore details from hypervisor]
>>> [talex5@gmail.com: use GCC implementation of division]
>>> [talex5@gmail.com: cleaned up interrupt handlers and threading]
>>> [talex5@gmail.com: call exit_thread when a thread returns]
>>> [talex5@gmail.com: implemented block_domain for ARM]
>>> [talex5@gmail.com: fixed hang when enabling interrupts]
>>> [talex5@gmail.com: added -march=armv7-a to flags]
>>> [talex5@gmail.com: CLREX after handling IRQs]
>>> [talex5@gmail.com: unbind debug port at shutdown]
>>> [talex5@gmail.com: allow unaligned accesses]
>>> [talex5@gmail.com: fix zImage header for XSA-95]
>>> [talex5@gmail.com: get RAM base and size from the FDT]
>>> [talex5@gmail.com: get GIC addresses from FDT]
>>> [talex5@gmail.com: added ARM grant table initialisation]
>>> [talex5@gmail.com: added missing copyright header to hypercalls32.S]
>>> [talex5@gmail.com: moved GIC driver to arm directory]
>>> [talex5@gmail.com: fixes suggested by Julien Grall:
>>> - Removed unnecessary isb.
>>> - Renamed GICD_PRIORITY to GICD_IPRIORITYR.
>>> - Change IRQ number type from unsigned char to int.
>>> - Added volatile to {set,clear}_bit_non_atomic.
>>> - Fixed some comments.
>>> - Check compatible properties in DTB.]
>>> [talex5@gmail.com: made image relocatable]
>>> [talex5@gmail.com: added mfn_to_pfn and pfn_to_mfn]
>>
>>
>> IHMO all these changes doesn't belong to the commit message, i.e should not
>> appear in the commit message when Ian will apply your commit message.
>
> As I understand it, as I'm not the author of the patch, it's polite to
> indicate how I have modified it. I'm trying to follow the guidelines
> here:
> "Rule (b) allows you to adjust the code, but then it is very impolite
> to change one submitter's code and make him endorse your bugs. To
> solve this problem, it is recommended that you add a line between the
> last Signed-off-by header and yours, indicating the nature of your
> changes."

I agree with it. But you modify so much things in this patch, that I 
think it's not necessary to specify all of them.

Anyway it was only a suggestion.


>>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>>> ---
>>>    extras/mini-os/ARM-TODO.txt              |   6 +
>>>    extras/mini-os/Config.mk                 |   2 +
>>>    extras/mini-os/Makefile                  |   9 ++
>>>    extras/mini-os/arch/arm/Makefile         |  32 ++++
>>>    extras/mini-os/arch/arm/arch.mk          |   7 +
>>>    extras/mini-os/arch/arm/arm32.S          | 266
>>> +++++++++++++++++++++++++++++++
>>>    extras/mini-os/arch/arm/events.c         |  30 ++++
>>>    extras/mini-os/arch/arm/gic.c            | 222
>>> ++++++++++++++++++++++++++
>>>    extras/mini-os/arch/arm/hypercalls32.S   |  75 +++++++++
>>>    extras/mini-os/arch/arm/minios-arm32.lds |  75 +++++++++
>>>    extras/mini-os/arch/arm/mm.c             | 134 ++++++++++++++++
>>>    extras/mini-os/arch/arm/sched.c          |  37 +++++
>>>    extras/mini-os/arch/arm/setup.c          | 116 ++++++++++++++
>>>    extras/mini-os/arch/arm/time.c           | 202 +++++++++++++++++++++++
>>>    extras/mini-os/kernel.c                  |   2 +-
>>>    15 files changed, 1214 insertions(+), 1 deletion(-)
>>>    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/events.c
>>>    create mode 100644 extras/mini-os/arch/arm/gic.c
>>>    create mode 100644 extras/mini-os/arch/arm/hypercalls32.S
>>>    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/sched.c
>>>    create mode 100644 extras/mini-os/arch/arm/setup.c
>>>    create mode 100644 extras/mini-os/arch/arm/time.c
>>>
>>> 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 931cd05..01d8af0 100644
>>> --- a/extras/mini-os/Makefile
>>> +++ b/extras/mini-os/Makefile
>>> @@ -78,6 +78,9 @@ TARGET := mini-os
>>>    SUBDIRS := lib xenbus console
>>>
>>>    ifeq ($(XEN_TARGET_ARCH),arm32)
>>> +# Need libgcc.a for division helpers
>>> +LDLIBS += `$(CC) -print-libgcc-file-name`
>>
>>
>> OOI, how much code does add libgcc for the division helpers?
>
> Hard to say. libgcc.a contains many files, but the ones with "div" in
> the name come to about 67K, so probably less than that.

Ok.

>>> diff --git a/extras/mini-os/arch/arm/arm32.S
>>> b/extras/mini-os/arch/arm/arm32.S
>>> new file mode 100644
>>> index 0000000..de74ed9
>>> --- /dev/null
>>> +++ b/extras/mini-os/arch/arm/arm32.S
>>> @@ -0,0 +1,266 @@
>>> +@ Virtual address of the start of RAM (any value will do, but it must be
>>> +@ section-aligned). Update the lds script if changed.
>>> +#define VIRT_BASE 0x400000
>>> +
>>> +@ Offset of the kernel within the RAM. This is a zImage convention which
>>> we
>>> +@ rely on.
>>> +#define ZIMAGE_KERNEL_OFFSET 0x8000
>>
>>
>> Hmmm... this is not a zImage convention... IIRC Linux is using this offset
>> to have enough space to create startup page table during boot.
>
> OK, so this is a convention of Linux only? I found this reference:
>
> http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
>
> "Despite the ability to place zImage anywhere within memory,
> convention has it that it is loaded at the base of physical RAM plus
> an offset of 0x8000 (32K). This leaves space for the parameter block
> usually placed at offset 0x100, zero page exception vectors and page
> tables. This convention is *very* common."

I think this convention is for kernel which are able to load only in a 
specific address (i.e CONFIG_AUTO_ZRELADDR=n). Linux Xen guest need to 
have this option set to be able to boot. So Linux will calculate the 
relocation address itself:

#ifdef CONFIG_AUTO_ZRELADDR
                 @ determine final kernel image address
                 mov     r4, pc
                 and     r4, r4, #0xf8000000
                 add     r4, r4, #TEXT_OFFSET
#else
                 ldr     r4, =zreladdr
#endif

TEXT_OFFSET is equal to 0x8000 here.

This code lives in Linux since at least 2010 (last commit in git blame 
arch/arm/boot/compressed/head.S).

Futhermore, for DOM0 we are using a 2MB-aligned address. I think it's 
time to make the same thing for the guest (see the patch I sent earlier 
today: https://patches.linaro.org/32742/).

This will also help to add support more easily for Xen in new OS.

>> The Linux zImage is able to relocate itself in the memory to respect this
>> convention. But the zImage itself can be loaded anywhere in the memory.
>>
>> By looking to your code below your are relying that the kernel will be
>> loaded at 0xXXXX8000 which is incorrect. This offset is odd and make other
>> kernel (such as FreeBSD) requiring the same trick which is not part of the
>> Linux boot protocol.
>
> Sorry, I don't understand this. You're saying that Xen's choice of
> 0x8000 forces FreeBSD to support this offset too? But that isn't
> caused by anything in Mini-OS.
>
>> I plan to send a patch to require the start address to be 2MB aligned, so
>> kernels will be able to use 2MB (for LPAE) and 1MB section for there early
>> page table.
>>
>> If the kernel wants another alignment, then you will have to relocate
>> yourself. Even though in your case, you don't need this odd 0xXXXX8000.
>
> It's very convenient to know at least the offset where we will be
> loaded. Otherwise, we have to move the image around in memory with
> loads and stores. I think there is some work going on to share images
> between VMs (for running large numbers of VMs on one machine). I don't
> know the details, but presumably it would be easier to support that if
> the image's text section can be mapped read-only.

I sent a patch to handle 2MB-align with is less odd than the 0x8000. 
IHMO, the latter offset has no sense as it's not part of the ABI.

>> [..]
>>
>>
>>> +       @ Fill in the whole top-level translation table (at page_dir).
>>> +       @ Populate the whole pagedir with 1MB section descriptors.
>>> +
>>> +       mov     r1, r7                  @ r1 -> first section entry
>>> +       add     r3, r1, #4*4*1024       @ limit (4 GB address space, 4
>>> byte entries)
>>> +       orr     r0, r8, r9              @ r0 = entry mapping section zero
>>> to start of physical RAM
>>> +1:
>>> +       str     r0, [r1],#4             @ write the section entry
>>> +       add     r0, r0, #1 << 20        @ next physical page (wraps)
>>> +       cmp     r1, r3
>>> +       bne     1b
>>
>>
>> I would document a bit more this part. It took me a bit of time to
>> understand that you mapping the whole address space in an odd manner.
>
> Could you suggest something? It's hard to know what other people will
> find confusing. For reference, here's the existing comment in the code
> where I tried to explain the scheme:
>
>      @ Problem: the C code wants to be at a known address (VIRT_BASE),
> but Xen might
>      @ load us anywhere. We initialise the MMU (mapping virtual to
> physical @ addresses)
>      @ so everything ends up where the code expects it to be.
>      @
>      @ We calculate the offet between where the linker thought _start
> would be and where
>      @ it actually is and initialise the page tables to have that
> offset for every page.
>      @
>      @ When we turn on the MMU, we're still executing at the old
> address. We don't want
>      @ the code to disappear from under us. So we have to do the
> mapping in stages:
>      @
>      @ 1. set up a mapping to our current page from both its current
> and desired addresses
>      @ 2. enable the MMU
>      @ 3. jump to the new address
>      @ 4. remap all the other pages with the calculated offset

Actually,  I like the existing comment. It tell the problems and explain 
how to solve it. Can you keep it?

>> While it's fine for a first version of Mini-OS support for ARM. It think at
>> long term you want to map only necessary bank rank. It will be easier to
>> catch programming error and avoid to trap in the hypervisor because the
>> physical address doesn't exist.
>
> Yes, this is just the boot code. Eventually, the C code should make
> the .text read-only (and unmap pages that don't exist, although I
> don't think there's currently any disadvantage to having the trap
> caused by the second stage page tables). I also want to add guard
> pages to the thread stacks once these initial patches are in.
>
>> Futhermore, the data abort sent by the hypervisor is odd (debug smth).
>
> Could you explain what you mean by "odd" here?

Xen is injecting a debug fault when it needs to send a data abort to the 
guest. It may be confusing for the developer that doesn't know Xen internal.

Anyway, I'm fine with the current solution.

>>> +.pushsection .data
>>> +_data:
>>> +.align 14
>>> +.globl page_dir
>>> +@ Each word maps one 1MB virtual section to a physical section
>>> +page_dir:
>>> +       .fill (4*1024), 4, 0x0
>>> +
>>> +.align 12
>>> +.globl shared_info_page
>>> +shared_info_page:
>>> +       .fill (1024), 4, 0x0
>>> +
>>> +.align 3
>>> +.globl stack
>>> +stack:
>>> +       .fill (4*1024), 4, 0x0
>>> +stack_end:
>>> +
>>> +.align 3
>>> +irqstack:
>>> +       .fill (1024), 4, 0x0
>>> +irqstack_end:
>>> +
>>> +.globl physical_address_offset
>>> +physical_address_offset:
>>> +       .long   0
>>> +
>>> +.popsection
>>
>>
>> Any reason to define theses variables in ASM rather than C?
>
> I normally prefer to define variables in the module that sets them,
> but it doesn't make much difference to me.
>
> Though perhaps they should be moved to the .bss section (except for
> the page table, which could be moved to the start of RAM to simplify
> things).

It would help for ARM64 port as I don't think those variables is 32bit 
specific.

>>> diff --git a/extras/mini-os/arch/arm/gic.c b/extras/mini-os/arch/arm/gic.c
>>> new file mode 100644
>>> index 0000000..5641eb0
>>> --- /dev/null
>>> +++ b/extras/mini-os/arch/arm/gic.c
>>> @@ -0,0 +1,222 @@
>>> +// ARM GIC implementation
>>> +
>>> +#include <mini-os/os.h>
>>> +#include <mini-os/hypervisor.h>
>>> +#include <libfdt.h>
>>> +
>>> +//#define VGIC_DEBUG
>>> +#ifdef VGIC_DEBUG
>>> +#define DEBUG(_f, _a...) \
>>> +    DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a)
>>
>>
>> Did you intend to use printk here?
>
> It does look odd. I'll take a look.

Thanks.

>> [..]
>>
>>
>>> +void gic_init(void) {
>>> +    gic.gicd_base = NULL;
>>> +    int node = 0;
>>> +    int depth = 0;
>>> +    for (;;)
>>> +    {
>>> +        node = fdt_next_node(device_tree, node, &depth);
>>> +        if (node <= 0 || depth < 0)
>>> +            break;
>>> +
>>> +        if (fdt_getprop(device_tree, node, "interrupt-controller", NULL))
>>> {
>>> +            int len = 0;
>>> +
>>> +            if (fdt_node_check_compatible(device_tree, node,
>>> "arm,cortex-a15-gic") &&
>>> +                fdt_node_check_compatible(device_tree, node,
>>> "arm,cortex-a9-gic") &&
>>
>>
>> I don't think this compatible is necessary. Cortex A9 doesn't support
>> virtualisation.
>
> OK. I was just matching on the values that Xen provides. a15-gic
> should be fine on its own, though.

IIRC, the toolstack doesn't provide arm,cortex-a9-gic :).

>>> +                fdt_node_check_compatible(device_tree, node,
>>> "arm,cortex-a7-gic")) {
>>> +                printk("Skipping incompatible interrupt-controller
>>> node\n");
>>> +                continue;
>>> +            }
>>> +
>>> +            const uint64_t *reg = fdt_getprop(device_tree, node, "reg",
>>> &len);
>>> +            if (reg == NULL || len != 32) {
>>
>>
>> As asked on the previous version, if you plan to assume specific range size
>> for the time-being, please explain the 32.
>
> OK, so we have two registers (GICC and GICD), each of which contains
> two parts (an address and a size), each of which is a 64-bit value (8
> bytes). So 2 * 2 * 8 = 32. Should I check this as a minimum, or
> require it to match exactly?

Match exactly is better. It will catch easily any change in the device 
tree provided by the toolstack.

Can you add what you said as a comment?

>>> +                /* TODO: support other formats */
>>> +                printk("Bad 'reg' property: %p %d\n", reg, len);
>>> +                continue;
>>> +            }
>>> +            gic.gicd_base = to_virt((long) fdt64_to_cpu(reg[0]));
>>> +            gic.gicc_base = to_virt((long) fdt64_to_cpu(reg[2]));
>>
>>
>> AFAIU, your are mapping the GIC region with normal attribute. With this
>> attribute, the processor may reorder the write in the device memory, preload
>> memory, caching.... Which is completely wrong in this case. I'm sa bit
>> surprised that it works correctly. You have to map thoses regions as device
>> memory.
>
> I believe that the ARM uses the most restrictive memory type from the
> two stages of the translation table, so if Xen maps it as device
> memory then it will work. We can set it here as well, though.
>
> (see "Overlaying the memory type attribute" in the Architecture
> Reference Manual)

I don't really want to see this such assumption in Mini-OS. Let say, we 
decide to change the memory type attribute in Xen 4.x to "Normal". Then 
we screw Mini-OS, and it would be very hard to debug.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-30 19:12     ` Thomas Leonard
  2014-06-30 21:08       ` Julien Grall
@ 2014-07-02  8:23       ` Ian Campbell
  2014-07-02  9:22         ` karim.allah.ahmed
  1 sibling, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2014-07-02  8:23 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On Mon, 2014-06-30 at 20:12 +0100, Thomas Leonard wrote:
> > IHMO all these changes doesn't belong to the commit message, i.e should not
> > appear in the commit message when Ian will apply your commit message.
> 
> As I understand it, as I'm not the author of the patch, it's polite to
> indicate how I have modified it. I'm trying to follow the guidelines
> here:

I'm not suggesting you change what you've done here at this stage, but
for next time:

It's a bit of a judgement call based on the scale of the changes. For
the number of changes you have done I might have considered making
myself the "Author" and saying in the commit log "Based on an initial
patch by Karim, but heavily modified, bugs are all mine" or something
along those lines etc.

Or if you felt your changes weren't sufficient to justify a change of
the primary author then a single "Extensively/slightly* modified" (*
delete as applicable) note would be OK.

The full intra-patch changelog could still usefully go after the "---"
break to aid reviewers.

Ian.

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

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-06-30 21:08       ` Julien Grall
@ 2014-07-02  8:41         ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-07-02  8:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Thomas Leonard, David Scott, Anil Madhavapeddy,
	Stefano Stabellini, Samuel Thibault, xen-devel

On Mon, 2014-06-30 at 22:08 +0100, Julien Grall wrote:

> >>> diff --git a/extras/mini-os/arch/arm/arm32.S
> >>> b/extras/mini-os/arch/arm/arm32.S
> >>> new file mode 100644
> >>> index 0000000..de74ed9
> >>> --- /dev/null
> >>> +++ b/extras/mini-os/arch/arm/arm32.S
> >>> @@ -0,0 +1,266 @@
> >>> +@ Virtual address of the start of RAM (any value will do, but it must be
> >>> +@ section-aligned). Update the lds script if changed.
> >>> +#define VIRT_BASE 0x400000
> >>> +
> >>> +@ Offset of the kernel within the RAM. This is a zImage convention which
> >>> we
> >>> +@ rely on.
> >>> +#define ZIMAGE_KERNEL_OFFSET 0x8000
> >>
> >>
> >> Hmmm... this is not a zImage convention... IIRC Linux is using this offset
> >> to have enough space to create startup page table during boot.
> >
> > OK, so this is a convention of Linux only? I found this reference:
> >
> > http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
> >
> > "Despite the ability to place zImage anywhere within memory,
> > convention has it that it is loaded at the base of physical RAM plus
> > an offset of 0x8000 (32K). This leaves space for the parameter block
> > usually placed at offset 0x100, zero page exception vectors and page
> > tables. This convention is *very* common."

Documentation/arm/Booting is the more canonical reference here.

> I think this convention is for kernel which are able to load only in a 
> specific address (i.e CONFIG_AUTO_ZRELADDR=n). Linux Xen guest need to 
> have this option set to be able to boot. So Linux will calculate the 
> relocation address itself:
> 
> #ifdef CONFIG_AUTO_ZRELADDR
>                  @ determine final kernel image address
>                  mov     r4, pc
>                  and     r4, r4, #0xf8000000
>                  add     r4, r4, #TEXT_OFFSET
> #else
>                  ldr     r4, =zreladdr
> #endif
> 
> TEXT_OFFSET is equal to 0x8000 here.
> 
> This code lives in Linux since at least 2010 (last commit in git blame 
> arch/arm/boot/compressed/head.S).
> 
> Futhermore, for DOM0 we are using a 2MB-aligned address. I think it's 
> time to make the same thing for the guest

Guest OSes are entitled to expect that we will load them in accordance
with the Linux zImage protocol, nothing more or less. Likewise a guest
which relies on something which is not guaranteed by that spec is buggy.

(By spec I mean the combination of Documentation/arm/Booting and the
various comments in the Linux code, which are the closest we come to a
formal spec here)

So it would be wrong for a guest kernel to indicate (via offset 0x24 in
the header) that it is relocatable while at the same time assuming that
it is loaded at either a 0x8000 offset or a 2MB aligned address. It's
either PIC on entry or it isn't (in which case offset 0x24 should give
an explicit load address).

(Xen itself probably violates this, by assuming 2MB alignment. We are in
the wrong and I expect that eventually it will bite us in the ass on
some platform/bootloader and then we'll have to fix it, not complain
that it used to work with older platforms/bootloaders. The same is true
of any guests which make similar assumptions IMHO -- i.e. it's their bug
when it breaks because we changed Xen)

>  (see the patch I sent earlier 
> today: https://patches.linaro.org/32742/).
> 
> This will also help to add support more easily for Xen in new OS.
> 
> >> The Linux zImage is able to relocate itself in the memory to respect this
> >> convention. But the zImage itself can be loaded anywhere in the memory.
> >>
> >> By looking to your code below your are relying that the kernel will be
> >> loaded at 0xXXXX8000 which is incorrect. This offset is odd and make other
> >> kernel (such as FreeBSD) requiring the same trick which is not part of the
> >> Linux boot protocol.
> >
> > Sorry, I don't understand this. You're saying that Xen's choice of
> > 0x8000 forces FreeBSD to support this offset too? But that isn't
> > caused by anything in Mini-OS.

I don't know what Julien was saying, but as far as I'm concerned FreeBSD
needs to either be PIC on entry or give a specific load address (or make
buggy assumptions about Xen's current guest loader behaviour).

> >>> +                fdt_node_check_compatible(device_tree, node,
> >>> "arm,cortex-a7-gic")) {
> >>> +                printk("Skipping incompatible interrupt-controller
> >>> node\n");
> >>> +                continue;
> >>> +            }
> >>> +
> >>> +            const uint64_t *reg = fdt_getprop(device_tree, node, "reg",
> >>> &len);
> >>> +            if (reg == NULL || len != 32) {
> >>
> >>
> >> As asked on the previous version, if you plan to assume specific range size
> >> for the time-being, please explain the 32.
> >
> > OK, so we have two registers (GICC and GICD), each of which contains
> > two parts (an address and a size), each of which is a 64-bit value (8
> > bytes). So 2 * 2 * 8 = 32. Should I check this as a minimum, or
> > require it to match exactly?
> 
> Match exactly is better. It will catch easily any change in the device 
> tree provided by the toolstack.

It would be perfectly reasonable in the future for a DT binding to be
enhanced such that a new compatiblity string was defined which had a
superset of the registers of the existing string.

You should check for whatever minimum the compatibility string you
actually know about says and ignore any additional registers.

(I don't know how likely this is for the GIC, but as a general principal
it's what should be done)

Ian.

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

* Re: [PATCH ARM v5 19/20] mini-os: initial ARM support
  2014-07-02  8:23       ` Ian Campbell
@ 2014-07-02  9:22         ` karim.allah.ahmed
  0 siblings, 0 replies; 54+ messages in thread
From: karim.allah.ahmed @ 2014-07-02  9:22 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Thomas Leonard, David Scott, Anil Madhavapeddy, Julien Grall,
	xen-devel, Samuel Thibault, Stefano Stabellini

On Wed, Jul 2, 2014 at 9:23 AM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Mon, 2014-06-30 at 20:12 +0100, Thomas Leonard wrote:
>> > IHMO all these changes doesn't belong to the commit message, i.e should not
>> > appear in the commit message when Ian will apply your commit message.
>>
>> As I understand it, as I'm not the author of the patch, it's polite to
>> indicate how I have modified it. I'm trying to follow the guidelines
>> here:
>
> I'm not suggesting you change what you've done here at this stage, but
> for next time:
>
> It's a bit of a judgement call based on the scale of the changes. For
> the number of changes you have done I might have considered making
> myself the "Author" and saying in the commit log "Based on an initial
> patch by Karim, but heavily modified, bugs are all mine" or something
> along those lines etc.
>
> Or if you felt your changes weren't sufficient to justify a change of
> the primary author then a single "Extensively/slightly* modified" (*
> delete as applicable) note would be OK.
>
> The full intra-patch changelog could still usefully go after the "---"
> break to aid reviewers.

I do agree with Ian.

Thomas, feel free to drop me as the author of the patch since you are
heavily modifying the patch anyway. :)


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



-- 
Karim Allah Ahmed.

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

end of thread, other threads:[~2014-07-02  9:22 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-26 11:28 [PATCH ARM v5 00/20] mini-os: initial ARM support Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 01/20] mini-os: build fixes Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 02/20] mini-os: fixed shutdown thread Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 03/20] mini-os: fixed format string error in unbind_evtchn Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 04/20] mini-os: use unbind_evtchn in unbind_all_ports Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 05/20] mini-os: made off_t type signed Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 06/20] mini-os: switched initial C entry point to arch_init Thomas Leonard
2014-06-26 11:28 ` [PATCH ARM v5 07/20] mini-os: whitespace Thomas Leonard
2014-06-26 11:35   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 08/20] mini-os: added arch_init_gnttab Thomas Leonard
2014-06-26 11:36   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 09/20] mini-os: don't require XEN_HAVE_PV_UPCALL_MASK Thomas Leonard
2014-06-26 11:37   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 10/20] mini-os: add missing casts to MM printk Thomas Leonard
2014-06-26 11:37   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 11/20] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
2014-06-26 11:38   ` Samuel Thibault
2014-06-27 13:13     ` Ian Campbell
2014-06-27 13:56       ` Thomas Leonard
2014-06-27 15:43         ` Thomas Leonard
2014-06-27 15:50           ` Samuel Thibault
2014-06-27 16:47         ` Ian Campbell
2014-06-26 11:28 ` [PATCH ARM v5 12/20] mini-os: added arch_unbind_ports Thomas Leonard
2014-06-26 11:38   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 13/20] mini-os: moved __pte to x86 Thomas Leonard
2014-06-26 11:39   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 14/20] mini-os: moved unlikely/likely macros to new compiler.h Thomas Leonard
2014-06-26 11:40   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 15/20] mini-os: enable test_xenbus again Thomas Leonard
2014-06-26 11:40   ` Samuel Thibault
2014-06-27 11:05   ` Ian Campbell
2014-06-27 12:48     ` Thomas Leonard
2014-06-27 12:54       ` Ian Campbell
2014-06-26 11:28 ` [PATCH ARM v5 16/20] mini-os: use irqs_disabled() helper in schedule Thomas Leonard
2014-06-26 11:42   ` Samuel Thibault
2014-06-26 11:28 ` [PATCH ARM v5 17/20] mini-os: headers for ARM Thomas Leonard
2014-06-26 16:26   ` Julien Grall
2014-06-27 13:02     ` Thomas Leonard
2014-06-27 13:11       ` Ian Campbell
2014-06-26 11:28 ` [PATCH ARM v5 18/20] mini-os: import libfdt Thomas Leonard
2014-06-28 12:01   ` Julien Grall
2014-06-28 12:27     ` Thomas Leonard
2014-06-28 15:14       ` Julien Grall
2014-06-28 16:35         ` Anil Madhavapeddy
2014-06-28 16:45           ` Julien Grall
2014-06-26 11:28 ` [PATCH ARM v5 19/20] mini-os: initial ARM support Thomas Leonard
2014-06-28 18:31   ` Julien Grall
2014-06-30 19:12     ` Thomas Leonard
2014-06-30 21:08       ` Julien Grall
2014-07-02  8:41         ` Ian Campbell
2014-07-02  8:23       ` Ian Campbell
2014-07-02  9:22         ` karim.allah.ahmed
2014-06-26 11:28 ` [PATCH ARM v5 20/20] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
2014-06-27 13:34 ` [PATCH ARM v5 00/20] mini-os: initial ARM support Ian Campbell

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.