All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH ARM v6 00/14] mini-os: initial ARM support
@ 2014-07-16 11:07 Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
                   ` (15 more replies)
  0 siblings, 16 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 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 series is rebased on staging, dropping patches that have already been
  applied.

- The changes have been further split into smaller patches to ease reviewing.
  Note that the build system isn't changed to allow building the new code until
  patch 13.

- Define BUG to cause an undefined instruction fault. This lets us us dump the
  registers.

- Renamed stack to _boot_stack for clarity.

- Include kernel.h from arm/os.h. This is for consistency with x86/os.h
  and is needed to compile with lwIP.

- Moved SVC stack to first 16KB of RAM (provides some protection against
  stack overlow corrupting memory).

- Put translation table in second 16KB (simplifies boot code).

- Moved shared_info_page and irqstack to .bss section (smaller image).

- Moved __bss_start and _edata inside section in linker script.
  The linker adds non-listed sections, such as .got, just before .bss.
  This meant that we accidentally zeroed those out too.

- Enable floating point unit.

- Require only minimum FDT property lengths (requested by Ian Campbell).

Addressed Julien Grall's comments:

- Get hypercall numbers from xen.h.
- Avoid duplicating the definition of _start's virtual address.
- Moved definition of physical_address_offset from asm to C.
- Added paddr_t type to represent physical addresses.
- Added comments explaining the lengths when checking FDT properties.
- Fixed (commented) DEBUG macro.
- Drop check for arm,cortex-a9-gic.

There are two assumptions the code makes that may need changing in the future, but
which hopefully don't need to hold up this initial support:

- The assumption that the kernel will be loaded at start of RAM + 0x8000.

- The assumption that Xen will mark the GIC address range as device memory.
  This should probably be fixed when the C code gains the ability to control
  the translation tables, map 4K pages, etc.


Karim Raslan (3):
  mini-os: headers for ARM
  mini-os: import libfdt
  mini-os: arm: events

Thomas Leonard (11):
  mini-os: x86_64: make thread stacks 16-byte aligned
  mini-os: don't include lib.h from mm.h
  mini-os: added HYPERVISOR_xsm_op
  mini-os: use generic local_irq_enable function
  mini-os: arm: boot code
  mini-os: arm: memory management
  mini-os: arm: scheduling
  mini-os: arm: time
  mini-os: arm: interrupt controller
  mini-os: arm: build system
  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                          |   22 +
 extras/mini-os/arch/arm/Makefile                 |   32 +
 extras/mini-os/arch/arm/arch.mk                  |    7 +
 extras/mini-os/arch/arm/arm32.S                  |  294 +++++
 extras/mini-os/arch/arm/events.c                 |   31 +
 extras/mini-os/arch/arm/gic.c                    |  232 ++++
 extras/mini-os/arch/arm/hypercalls32.S           |   64 +
 extras/mini-os/arch/arm/minios-arm32.lds         |   79 ++
 extras/mini-os/arch/arm/mm.c                     |  138 ++
 extras/mini-os/arch/arm/panic.c                  |   98 ++
 extras/mini-os/arch/arm/sched.c                  |   38 +
 extras/mini-os/arch/arm/setup.c                  |  119 ++
 extras/mini-os/arch/arm/time.c                   |  202 +++
 extras/mini-os/arch/x86/sched.c                  |    3 +
 extras/mini-os/events.c                          |    4 +-
 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             |   38 +
 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                  |  216 ++++
 extras/mini-os/include/arm/traps.h               |   20 +
 extras/mini-os/include/fdt.h                     |   60 +
 extras/mini-os/include/hypervisor.h              |    2 +
 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                      |    5 +-
 extras/mini-os/include/types.h                   |   10 +-
 extras/mini-os/include/x86/os.h                  |    7 +
 extras/mini-os/kernel.c                          |    2 +-
 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/lock.c                            |    1 +
 extras/mini-os/main.c                            |    1 +
 extras/mini-os/tpmfront.c                        |    1 +
 50 files changed, 5433 insertions(+), 11 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/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.1

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

* [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-17 15:50   ` Ian Campbell
  2014-07-17 18:15   ` Samuel Thibault
  2014-07-16 11:07 ` [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h Thomas Leonard
                   ` (14 subsequent siblings)
  15 siblings, 2 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Otherwise, passing doubles to varargs functions causes a crash.

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

diff --git a/extras/mini-os/arch/x86/sched.c b/extras/mini-os/arch/x86/sched.c
index 8a05b58..e4a3dc2 100644
--- a/extras/mini-os/arch/x86/sched.c
+++ b/extras/mini-os/arch/x86/sched.c
@@ -107,6 +107,9 @@ struct thread* arch_create_thread(char *name, void (*function)(void *),
     thread->sp = (unsigned long)thread->stack + STACK_SIZE;
     /* Save pointer to the thread on the stack, used by current macro */
     *((unsigned long *)thread->stack) = (unsigned long)thread;
+
+    /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
+    thread->sp -= sizeof(unsigned long);
     
     stack_push(thread, (unsigned long) function);
     stack_push(thread, (unsigned long) data);
-- 
2.0.1

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

* [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 13:30   ` Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 03/14] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
-> lib.h -> gntmap.h -> os.h -> hypervisor.h.

Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/include/mm.h | 3 +--
 extras/mini-os/lock.c       | 1 +
 extras/mini-os/main.c       | 1 +
 extras/mini-os/tpmfront.c   | 1 +
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..a177251 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -32,8 +32,7 @@
 #else
 #error "Unsupported architecture"
 #endif
-
-#include <mini-os/lib.h>
+#include <xen/xen.h>
 
 #include <mini-os/arch_limits.h>
 #include <mini-os/arch_mm.h>
diff --git a/extras/mini-os/lock.c b/extras/mini-os/lock.c
index 71a4971..61194e5 100644
--- a/extras/mini-os/lock.c
+++ b/extras/mini-os/lock.c
@@ -9,6 +9,7 @@
 #include <sys/lock.h>
 #include <sched.h>
 #include <wait.h>
+#include <mini-os/lib.h>
 
 int ___lock_init(_LOCK_T *lock)
 {
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index aec0586..4ec40b5 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <xenbus.h>
 #include <events.h>
+#include <mini-os/lib.h>
 
 extern int main(int argc, char *argv[], char *envp[]);
 extern void __libc_init_array(void);
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index ce5b3e1..6049244 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -31,6 +31,7 @@
 #include <xen/io/xenbus.h>
 #include <xen/io/tpmif.h>
 #include <mini-os/tpmfront.h>
+#include <mini-os/lib.h>
 #include <fcntl.h>
 
 //#define TPMFRONT_PRINT_DEBUG
-- 
2.0.1

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

* [PATCH ARM v6 03/14] mini-os: added HYPERVISOR_xsm_op
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 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>
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 48742de..2a23042 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -245,7 +245,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;
@@ -253,7 +253,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 192b23cd..7a1bdc5 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -15,6 +15,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))
 
@@ -558,6 +559,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.1

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

* [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (2 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 03/14] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 21:25   ` Julien Grall
                     ` (2 more replies)
  2014-07-16 11:07 ` [PATCH ARM v6 05/14] mini-os: import libfdt Thomas Leonard
                   ` (11 subsequent siblings)
  15 siblings, 3 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 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.
Based on work by Karim Allah Ahmed.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

Since v5:

Define BUG to cause an undefined instruction fault. This will let
us dump the registers.

Renamed stack to _boot_stack for clarity.

Include kernel.h from arm/os.h. This is for consistency with x86/os.h
and is needed to compile with lwIP.

Added paddr_t type to represent physical addresses (requested by Julien
Grall).
---
 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             |  38 ++++
 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                  | 216 +++++++++++++++++++++++
 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, 454 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..8e10e4b
--- /dev/null
+++ b/extras/mini-os/include/arm/arch_mm.h
@@ -0,0 +1,38 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+typedef unsigned long paddr_t;
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern int _boot_stack[];
+extern int _boot_stack_end[];
+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)                 ((paddr_t)(x)+physical_address_offset)
+#define to_virt(x)                 ((void *)((paddr_t)(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..6a1cc37
--- /dev/null
+++ b/extras/mini-os/include/arm/os.h
@@ -0,0 +1,216 @@
+#ifndef _OS_H_
+#define _OS_H_
+
+#ifndef __ASSEMBLY__
+
+#include <mini-os/hypervisor.h>
+#include <mini-os/types.h>
+#include <mini-os/compiler.h>
+#include <mini-os/kernel.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){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */
+
+#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 a177251..f57d8ab 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.1

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

* [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (3 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 11:44   ` Andrew Cooper
  2014-07-16 11:07 ` [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function Thomas Leonard
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 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 (r246827).

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 62836c7..cc7dc7f 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -95,6 +95,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);
@@ -104,7 +105,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.1

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

* [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (4 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 05/14] mini-os: import libfdt Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-17 16:00   ` Ian Campbell
  2014-07-17 18:32   ` Samuel Thibault
  2014-07-16 11:07 ` [PATCH ARM v6 07/14] mini-os: arm: boot code Thomas Leonard
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

__sti is x86 specific.

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

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.1

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

* [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (5 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 21:49   ` Julien Grall
  2014-07-17 16:28   ` Ian Campbell
  2014-07-16 11:07 ` [PATCH ARM v6 08/14] mini-os: arm: memory management Thomas Leonard
                   ` (8 subsequent siblings)
  15 siblings, 2 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

Changes since v5:

- Moved SVC stack to first 16KB of RAM (provides some protection against
  stack overlow corrupting memory).
- Put translation table in second 16KB (simplifies boot code).
- Moved definition of physical_address_offset out of asm.
- Moved shared_info_page and irqstack to .bss section (smaller image).
- Moved __bss_start and _edata inside section in linker script.
  The linker adds non-listed sections, such as .got, just before .bss.
  This meant that we accidentally zeroed those out too.
- Enable floating point unit during boot.

Addressed Julien Grall's comments:
- Get hypercall numbers from xen.h.
- Avoid duplicating the definition of _start's virtual address.
---
 extras/mini-os/arch/arm/arm32.S          | 211 +++++++++++++++++++++++++++++++
 extras/mini-os/arch/arm/hypercalls32.S   |  64 ++++++++++
 extras/mini-os/arch/arm/minios-arm32.lds |  79 ++++++++++++
 extras/mini-os/arch/arm/setup.c          | 119 +++++++++++++++++
 4 files changed, 473 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/arm32.S
 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/setup.c

diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
new file mode 100644
index 0000000..88efe24
--- /dev/null
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -0,0 +1,211 @@
+@ Offset of the kernel within the RAM. This is a Linux/zImage convention which we
+@ rely on for now.
+#define ZIMAGE_KERNEL_OFFSET 0x8000
+
+.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 (_start), 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, =_start		@ r3 = (desired) virtual address of _start
+	sub 	r9, r1, r3		@ r9 = (physical - virtual) offset
+
+	ldr	r7, =_page_dir		@ r7 = (desired) virtual addr of translation table
+	add	r1, r7, r9		@ r1 = physical addr of translation table
+
+	@ Tell the system where our page table is located.
+	@ This is the 16 KB top-level translation table, in which
+	@ each word maps one 1MB virtual section to a physical section.
+	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 an entry for the current physical section, at the old and new
+	@ addresses. It's OK if they're the same.
+	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
+	ldr	r4, =_start		@ r4 = desired virtual address of this section
+	str	r3, [r1, r4, lsr#18] 	@ map desired virtual section to this code
+	str	r3, [r1, r0, lsr#18]	@ map current section to this code too
+
+	@ 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)
+@    r7 = virtual address of page table
+@    r8 = section entry template (flags)
+@    r9 = desired physical - virtual offset
+@    pc -> somewhere in newly-mapped virtual code section
+stage2:
+	@ 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
+
+	@ Enable hardware floating point:
+	@ 1. Access to CP10 and CP11 must be enabled in the Coprocessor Access
+	@    Control Register (CP15.CACR):
+	mrc	p15, 0, r1, c1, c0, 2		@ CACR
+	orr	r1, r1, #(3 << 20) + (3 << 22)	@ full access for CP10 & CP11
+	mcr	p15, 0, r1, c1, c0, 2
+	@ 2. The EN bit in the FPEXC register must be set:
+	vmrs	r0, FPEXC
+	orr	r0, r0, #1<<30		@ EN (enable)
+	vmsr	FPEXC, r0
+
+	@ Initialise 16 KB stack
+	ldr	sp, =_boot_stack_end
+
+	sub	r0, r2, r9		@ r0 -> device tree (virtual address)
+	mov	r1, r9			@ r1 = physical_address_offset
+
+	b	arch_init
+
+.pushsection .bss
+@ Note: calling arch_init zeroes out this region.
+.align 12
+.globl shared_info_page
+shared_info_page:
+	.fill (1024), 4, 0x0
+
+.align 3
+.globl irqstack
+.globl irqstack_end
+irqstack:
+	.fill (1024), 4, 0x0
+irqstack_end:
+
+.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
+
+@ 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
diff --git a/extras/mini-os/arch/arm/hypercalls32.S b/extras/mini-os/arch/arm/hypercalls32.S
new file mode 100644
index 0000000..af8e175
--- /dev/null
+++ b/extras/mini-os/arch/arm/hypercalls32.S
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * 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.
+ */
+
+#include <xen/xen.h>
+
+#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..21c3893
--- /dev/null
+++ b/extras/mini-os/arch/arm/minios-arm32.lds
@@ -0,0 +1,79 @@
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  _boot_stack 	 = 0x400000;	/* 16 KB boot stack */
+  _boot_stack_end = 0x404000;
+  _page_dir      = 0x404000;	/* 16 KB translation table */
+  .		 = 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)
+	}
+
+  /* Note: linker will insert any extra sections here, just before .bss */
+
+  .bss : {
+	_edata = .;			/* End of data included in image */
+	/* Nothing after here is included in the zImage's size */
+
+	__bss_start = .;
+	*(.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/setup.c b/extras/mini-os/arch/arm/setup.c
new file mode 100644
index 0000000..57fd62f
--- /dev/null
+++ b/extras/mini-os/arch/arm/setup.c
@@ -0,0 +1,119 @@
+#include <mini-os/os.h>
+#include <mini-os/kernel.h>
+#include <mini-os/gic.h>
+#include <mini-os/console.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, int physical_offset)
+{
+    struct xen_add_to_physmap xatp;
+    int r;
+
+    memset(&__bss_start, 0, &_end - &__bss_start);
+
+    physical_address_offset = physical_offset;
+
+    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)
+{
+}
-- 
2.0.1


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

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

* [PATCH ARM v6 08/14] mini-os: arm: memory management
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (6 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 07/14] mini-os: arm: boot code Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-21 17:36   ` Julien Grall
  2014-07-16 11:07 ` [PATCH ARM v6 09/14] mini-os: arm: scheduling Thomas Leonard
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

Changes since v5:

- Require only minimum property lengths (requested by Ian Campbell).

Addressed Julien Grall's comments:
- Added comments explaining the lengths when checking FDT properties.
- Use paddr_t type to represent physical addresses.
---
 extras/mini-os/arch/arm/mm.c | 138 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/mm.c

diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
new file mode 100644
index 0000000..ec1f821
--- /dev/null
+++ b/extras/mini-os/arch/arm/mm.c
@@ -0,0 +1,138 @@
+#include <mini-os/console.h>
+#include <xen/memory.h>
+#include <arch_mm.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.h>
+#include <lib.h>
+
+int physical_address_offset;
+
+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", _boot_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);
+
+    /* The property must contain at least the start address
+     * and size, each of which is 8-bytes. */
+    if (regs == NULL || prop_len < 16) {
+        printk("Bad 'reg' property: %p %d\n", regs, prop_len);
+        BUG();
+    }
+
+    unsigned int end = (unsigned int) &_end;
+    paddr_t 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 paddr_t get_gnttab_base(void)
+{
+    int hypervisor;
+    int len = 0;
+    const uint64_t *regs;
+    paddr_t 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);
+    /* The property contains the address and size, 8-bytes each. */
+    if (regs == NULL || len < 16) {
+        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];
+    paddr_t 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);
+}
-- 
2.0.1

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

* [PATCH ARM v6 09/14] mini-os: arm: scheduling
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (7 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 08/14] mini-os: arm: memory management Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-28 10:53   ` Ian Campbell
  2014-07-16 11:07 ` [PATCH ARM v6 10/14] mini-os: arm: events Thomas Leonard
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/arm/arm32.S | 22 ++++++++++++++++++++++
 extras/mini-os/arch/arm/sched.c | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/sched.c

diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
index 88efe24..56429b1 100644
--- a/extras/mini-os/arch/arm/arm32.S
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -204,8 +204,30 @@ 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/sched.c b/extras/mini-os/arch/arm/sched.c
new file mode 100644
index 0000000..9fb884e
--- /dev/null
+++ b/extras/mini-os/arch/arm/sched.c
@@ -0,0 +1,38 @@
+#include <mini-os/sched.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/console.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! */
+}
-- 
2.0.1

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

* [PATCH ARM v6 10/14] mini-os: arm: events
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (8 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 09/14] mini-os: arm: scheduling Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-28 10:55   ` Ian Campbell
  2014-07-16 11:07 ` [PATCH ARM v6 11/14] mini-os: arm: time Thomas Leonard
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 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>
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/arm/events.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/events.c

diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
new file mode 100644
index 0000000..441010d
--- /dev/null
+++ b/extras/mini-os/arch/arm/events.c
@@ -0,0 +1,31 @@
+#include <mini-os/os.h>
+#include <mini-os/events.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/console.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)
+{
+}
-- 
2.0.1

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

* [PATCH ARM v6 11/14] mini-os: arm: time
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (9 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 10/14] mini-os: arm: events Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-21 17:45   ` Julien Grall
  2014-07-16 11:07 ` [PATCH ARM v6 12/14] mini-os: arm: interrupt controller Thomas Leonard
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>
---
 extras/mini-os/arch/arm/time.c | 202 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/time.c

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);
+    }
+}
-- 
2.0.1

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

* [PATCH ARM v6 12/14] mini-os: arm: interrupt controller
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (10 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 11/14] mini-os: arm: time Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-21 17:56   ` Julien Grall
  2014-07-16 11:07 ` [PATCH ARM v6 13/14] mini-os: arm: build system Thomas Leonard
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

Changes since v5:

Addressed Julien Grall's comments:
- Added comments explaining the lengths when checking FDT properties.
- Fixed (commented) DEBUG macro.
- Drop check for arm,cortex-a9-gic.

- Require only minimum property lengths (requested by Ian Campbell).
---
 extras/mini-os/arch/arm/gic.c | 232 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 232 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/gic.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..1afa099
--- /dev/null
+++ b/extras/mini-os/arch/arm/gic.c
@@ -0,0 +1,232 @@
+// ARM GIC implementation
+
+#include <mini-os/os.h>
+#include <mini-os/hypervisor.h>
+#include <mini-os/console.h>
+#include <libfdt.h>
+
+//#define VGIC_DEBUG
+#ifdef VGIC_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("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-a7-gic")) {
+                printk("Skipping incompatible interrupt-controller node\n");
+                continue;
+            }
+
+            const uint64_t *reg = fdt_getprop(device_tree, node, "reg", &len);
+
+            /* 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 we expect a length of 2 * 2 * 8 = 32.
+             * If any extra values are passed in future, we ignore them. */
+            if (reg == NULL || len < 32) {
+                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();
+
+    /* Note: we could mark this as "device" memory here, but Xen will have already
+     * set it that way in the second stage translation table, so it's not necessary.
+     * See "Overlaying the memory type attribute" in the Architecture Reference Manual.
+     */
+
+    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 */);
+}
-- 
2.0.1

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

* [PATCH ARM v6 13/14] mini-os: arm: build system
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (11 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 12/14] mini-os: arm: interrupt controller Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-16 22:03   ` Julien Grall
  2014-07-28 10:58   ` Ian Campbell
  2014-07-16 11:07 ` [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
                   ` (2 subsequent siblings)
  15 siblings, 2 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Based on an initial patch by Karim Raslan.

This activates the ARM code added in the previous patches. 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>
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 +++++++
 5 files changed, 56 insertions(+)
 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

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..ad6e05f
--- /dev/null
+++ b/extras/mini-os/arch/arm/arch.mk
@@ -0,0 +1,7 @@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+DEF_ASFLAGS += -march=armv7-a -mfpu=vfpv3
+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
+
-- 
2.0.1

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

* [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (12 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 13/14] mini-os: arm: build system Thomas Leonard
@ 2014-07-16 11:07 ` Thomas Leonard
  2014-07-28 11:13   ` Ian Campbell
  2014-07-16 21:29 ` [PATCH ARM v6 00/14] mini-os: initial ARM support Julien Grall
  2014-07-18 12:45 ` Ian Campbell
  15 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 11:07 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini, samuel.thibault

Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

Exit with SHUTDOWN_crash on BUG or fault (suggested by Ian Campbell).
---
 extras/mini-os/ARM-TODO.txt     |  1 -
 extras/mini-os/arch/arm/arm32.S | 75 ++++++++++++++++++++++++++++---
 extras/mini-os/arch/arm/panic.c | 98 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+), 8 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 56429b1..fab9f9f 100644
--- a/extras/mini-os/arch/arm/arm32.S
+++ b/extras/mini-os/arch/arm/arm32.S
@@ -166,8 +166,69 @@ irqstack:
 	.fill (1024), 4, 0x0
 irqstack_end:
 
+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	sp, =_boot_stack_end
+	bl	dump_registers
+	b	do_exit
+
+@ 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
@@ -177,13 +238,13 @@ irqstack_end:
 @  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..d0547b0
--- /dev/null
+++ b/extras/mini-os/arch/arm/panic.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * 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 <mini-os/console.h>
+#include <arch_mm.h>
+
+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 >= _boot_stack && sp <= _boot_stack_end)
+        stack_top = _boot_stack_end;                    /* The boot stack */
+    else if (sp >= irqstack && sp <= irqstack_end)
+        stack_top = irqstack_end;                       /* The 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;
+}
-- 
2.0.1


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

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 11:07 ` [PATCH ARM v6 05/14] mini-os: import libfdt Thomas Leonard
@ 2014-07-16 11:44   ` Andrew Cooper
  2014-07-16 12:29     ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Andrew Cooper @ 2014-07-16 11:44 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

On 16/07/14 12:07, 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
>
> The memmove implementation is from FreeBSD's
> contrib/ldns/compat/memmove.c (r246827).
>
> 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>

Xen already has a copy of libfdt in xen/common/libfdt.

I think it sets a poor precedent to have multiple different copies of
the same library in the source tree.

Libraries like this should live in their own part of the Xen source tree
(libs/ or perhaps common/) and each component wanting to use them (Xen,
libxc, mini-os) can VPATH themselves access to the headers/source.

This would have the added advantage of making it obvious which shared
libraries are used by multiple components in the tree (libelf is another
example), and avoids duplication and stagnation.

~Andrew

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 11:44   ` Andrew Cooper
@ 2014-07-16 12:29     ` Ian Campbell
  2014-07-16 13:02       ` Andrew Cooper
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-16 12:29 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel

On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
> On 16/07/14 12:07, 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
> >
> > The memmove implementation is from FreeBSD's
> > contrib/ldns/compat/memmove.c (r246827).
> >
> > 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>
> 
> Xen already has a copy of libfdt in xen/common/libfdt.

Please review the thread on this from the previous postings.

Ian.

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 12:29     ` Ian Campbell
@ 2014-07-16 13:02       ` Andrew Cooper
  2014-07-16 13:34         ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Andrew Cooper @ 2014-07-16 13:02 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel

On 16/07/14 13:29, Ian Campbell wrote:
> On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
>> On 16/07/14 12:07, 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
>>>
>>> The memmove implementation is from FreeBSD's
>>> contrib/ldns/compat/memmove.c (r246827).
>>>
>>> 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>
>> Xen already has a copy of libfdt in xen/common/libfdt.
> Please review the thread on this from the previous postings.
>
> Ian.
>

Which appears to be unconcluded.

libfdt is a 3rd party library which, from what I can tell in the
history, is unmodified.  Therefore, my suggestion of moving it outside
of the xen/ tree and having both minios and Xen VPATH themselves access
to it helps with the end goal of preventing minios becoming dependent on
Xen code.  It further prevents both Xen and minios from accidentally
gaining localisation hacks in the library itself, which makes it easier
to updates to the base libdft if/when necessary.

~Andrew

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

* Re: [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h
  2014-07-16 11:07 ` [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h Thomas Leonard
@ 2014-07-16 13:30   ` Thomas Leonard
  2014-07-17 15:51     ` Ian Campbell
  2014-07-17 18:17     ` Samuel Thibault
  0 siblings, 2 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-16 13:30 UTC (permalink / raw)
  To: xen-devel
  Cc: Thomas Leonard, David Scott, Anil Madhavapeddy,
	Stefano Stabellini, Samuel Thibault

[-- Attachment #1: Type: text/plain, Size: 465 bytes --]

On 16 July 2014 12:07, Thomas Leonard <talex5@gmail.com> wrote:
> This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
> -> lib.h -> gntmap.h -> os.h -> hypervisor.h.

I've just realised this is missing an include in tpm_tis.c (which
isn't built by default). Fixed patch attached.


-- 
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

[-- Attachment #2: 0002-mini-os-don-t-include-lib.h-from-mm.h.patch --]
[-- Type: text/x-patch, Size: 2341 bytes --]

From 98705b128feb2e46272c4d29205f384899108704 Mon Sep 17 00:00:00 2001
From: Thomas Leonard <talex5@gmail.com>
Date: Mon, 7 Jul 2014 13:20:43 +0100
Subject: [PATCH] mini-os: don't include lib.h from mm.h

This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
-> lib.h -> gntmap.h -> os.h -> hypervisor.h.

Signed-off-by: Thomas Leonard <talex5@gmail.com>

---

- Added missing #include <mini-os/lib.h> to tpm_tis.c
---
 extras/mini-os/include/mm.h | 3 +--
 extras/mini-os/lock.c       | 1 +
 extras/mini-os/main.c       | 1 +
 extras/mini-os/tpm_tis.c    | 1 +
 extras/mini-os/tpmfront.c   | 1 +
 5 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..a177251 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -32,8 +32,7 @@
 #else
 #error "Unsupported architecture"
 #endif
-
-#include <mini-os/lib.h>
+#include <xen/xen.h>
 
 #include <mini-os/arch_limits.h>
 #include <mini-os/arch_mm.h>
diff --git a/extras/mini-os/lock.c b/extras/mini-os/lock.c
index 71a4971..61194e5 100644
--- a/extras/mini-os/lock.c
+++ b/extras/mini-os/lock.c
@@ -9,6 +9,7 @@
 #include <sys/lock.h>
 #include <sched.h>
 #include <wait.h>
+#include <mini-os/lib.h>
 
 int ___lock_init(_LOCK_T *lock)
 {
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index aec0586..4ec40b5 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <xenbus.h>
 #include <events.h>
+#include <mini-os/lib.h>
 
 extern int main(int argc, char *argv[], char *envp[]);
 extern void __libc_init_array(void);
diff --git a/extras/mini-os/tpm_tis.c b/extras/mini-os/tpm_tis.c
index e8ca69f..09234e5 100644
--- a/extras/mini-os/tpm_tis.c
+++ b/extras/mini-os/tpm_tis.c
@@ -26,6 +26,7 @@
 #include <mini-os/events.h>
 #include <mini-os/wait.h>
 #include <mini-os/xmalloc.h>
+#include <mini-os/lib.h>
 #include <errno.h>
 #include <stdbool.h>
 
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index ce5b3e1..6049244 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -31,6 +31,7 @@
 #include <xen/io/xenbus.h>
 #include <xen/io/tpmif.h>
 #include <mini-os/tpmfront.h>
+#include <mini-os/lib.h>
 #include <fcntl.h>
 
 //#define TPMFRONT_PRINT_DEBUG
-- 
2.0.1


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

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

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 13:02       ` Andrew Cooper
@ 2014-07-16 13:34         ` Ian Campbell
  2014-07-16 14:13           ` Anil Madhavapeddy
  2014-07-17 18:30           ` Samuel Thibault
  0 siblings, 2 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-16 13:34 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel

On Wed, 2014-07-16 at 14:02 +0100, Andrew Cooper wrote:
> On 16/07/14 13:29, Ian Campbell wrote:
> > On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
> >> On 16/07/14 12:07, 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
> >>>
> >>> The memmove implementation is from FreeBSD's
> >>> contrib/ldns/compat/memmove.c (r246827).
> >>>
> >>> 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>
> >> Xen already has a copy of libfdt in xen/common/libfdt.
> > Please review the thread on this from the previous postings.
> >
> > Ian.
> >
> 
> Which appears to be unconcluded.

http://article.gmane.org/gmane.comp.emulators.xen.devel/205280 looked
conclusive to me.

> libfdt is a 3rd party library which, from what I can tell in the
> history, is unmodified.  Therefore, my suggestion of moving it outside
> of the xen/ tree and having both minios and Xen VPATH themselves access
> to it helps with the end goal of preventing minios becoming dependent on
> Xen code.  It further prevents both Xen and minios from accidentally
> gaining localisation hacks in the library itself, which makes it easier
> to updates to the base libdft if/when necessary.

This would mean that splitting extras/mini-os off wouldn't be just a
case of doing that, you'd also need arrange for the VPATH to be
satisfied, I don't know if Anil et al will be happy with that.

Ultimately this is up to Samuel if he is happy with the current approach
or not.

Ian.

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 13:34         ` Ian Campbell
@ 2014-07-16 14:13           ` Anil Madhavapeddy
  2014-07-16 14:35             ` Ian Campbell
  2014-07-17 18:30           ` Samuel Thibault
  1 sibling, 1 reply; 75+ messages in thread
From: Anil Madhavapeddy @ 2014-07-16 14:13 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Thomas Leonard, Dave.Scott, stefano.stabellini, Andrew Cooper,
	xen-devel, samuel.thibault

On 16 Jul 2014, at 14:34, Ian Campbell <ian.campbell@citrix.com> wrote:

> On Wed, 2014-07-16 at 14:02 +0100, Andrew Cooper wrote:
>> On 16/07/14 13:29, Ian Campbell wrote:
>>> On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
>>>> On 16/07/14 12:07, 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
>>>>> 
>>>>> The memmove implementation is from FreeBSD's
>>>>> contrib/ldns/compat/memmove.c (r246827).
>>>>> 
>>>>> 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>
>>>> Xen already has a copy of libfdt in xen/common/libfdt.
>>> Please review the thread on this from the previous postings.
>>> 
>>> Ian.
>>> 
>> 
>> Which appears to be unconcluded.
> 
> http://article.gmane.org/gmane.comp.emulators.xen.devel/205280 looked
> conclusive to me.
> 
>> libfdt is a 3rd party library which, from what I can tell in the
>> history, is unmodified.  Therefore, my suggestion of moving it outside
>> of the xen/ tree and having both minios and Xen VPATH themselves access
>> to it helps with the end goal of preventing minios becoming dependent on
>> Xen code.  It further prevents both Xen and minios from accidentally
>> gaining localisation hacks in the library itself, which makes it easier
>> to updates to the base libdft if/when necessary.
> 
> This would mean that splitting extras/mini-os off wouldn't be just a
> case of doing that, you'd also need arrange for the VPATH to be
> satisfied, I don't know if Anil et al will be happy with that.

As long as we can resist the urge to locally modify libfdt, that shouldn't
be too onerous.  However, if libfdt isn't being modified at all, then
why import it into the tree at all?  We could just clone the right revision
in the build system as happens for some other upstream tools.

-anil

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 14:13           ` Anil Madhavapeddy
@ 2014-07-16 14:35             ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-16 14:35 UTC (permalink / raw)
  To: Anil Madhavapeddy
  Cc: Thomas Leonard, Dave.Scott, stefano.stabellini, Andrew Cooper,
	xen-devel, samuel.thibault

On Wed, 2014-07-16 at 15:13 +0100, Anil Madhavapeddy wrote:
> On 16 Jul 2014, at 14:34, Ian Campbell <ian.campbell@citrix.com> wrote:
> 
> > On Wed, 2014-07-16 at 14:02 +0100, Andrew Cooper wrote:
> >> On 16/07/14 13:29, Ian Campbell wrote:
> >>> On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
> >>>> On 16/07/14 12:07, 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
> >>>>> 
> >>>>> The memmove implementation is from FreeBSD's
> >>>>> contrib/ldns/compat/memmove.c (r246827).
> >>>>> 
> >>>>> 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>
> >>>> Xen already has a copy of libfdt in xen/common/libfdt.
> >>> Please review the thread on this from the previous postings.
> >>> 
> >>> Ian.
> >>> 
> >> 
> >> Which appears to be unconcluded.
> > 
> > http://article.gmane.org/gmane.comp.emulators.xen.devel/205280 looked
> > conclusive to me.
> > 
> >> libfdt is a 3rd party library which, from what I can tell in the
> >> history, is unmodified.  Therefore, my suggestion of moving it outside
> >> of the xen/ tree and having both minios and Xen VPATH themselves access
> >> to it helps with the end goal of preventing minios becoming dependent on
> >> Xen code.  It further prevents both Xen and minios from accidentally
> >> gaining localisation hacks in the library itself, which makes it easier
> >> to updates to the base libdft if/when necessary.
> > 
> > This would mean that splitting extras/mini-os off wouldn't be just a
> > case of doing that, you'd also need arrange for the VPATH to be
> > satisfied, I don't know if Anil et al will be happy with that.
> 
> As long as we can resist the urge to locally modify libfdt, that shouldn't
> be too onerous.  However, if libfdt isn't being modified at all, then
> why import it into the tree at all?  We could just clone the right revision
> in the build system as happens for some other upstream tools.

That's generally a sucky approach though, I'd like to see less not more
of it.

libfdt is somewhat designed to be embedded in this way.

Ian.

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
@ 2014-07-16 21:25   ` Julien Grall
  2014-07-17  8:14     ` Thomas Leonard
  2014-07-17 15:59   ` Ian Campbell
  2014-07-17 18:27   ` Samuel Thibault
  2 siblings, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-16 21:25 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, David Scott, anil

Hi Thomas,

On 16/07/14 12:07, Thomas Leonard wrote:
> diff --git a/extras/mini-os/include/arm/os.h b/extras/mini-os/include/arm/os.h
> new file mode 100644
> index 0000000..6a1cc37
> --- /dev/null
> +++ b/extras/mini-os/include/arm/os.h
> @@ -0,0 +1,216 @@
> +#ifndef _OS_H_
> +#define _OS_H_
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <mini-os/hypervisor.h>
> +#include <mini-os/types.h>
> +#include <mini-os/compiler.h>
> +#include <mini-os/kernel.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){asm volatile (".word 0xe7f000f0\n");} /* Undefined instruction; will call our fault handler. */

NIT: I would explain that ARM doesn't provide any undefined instruction 
so we use an encoding that is invalid on ARMv7.

The other part of this patch looks good to me.

FWIW: Acked-by: Julien Grall <julien.grall@linaro.org>

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (13 preceding siblings ...)
  2014-07-16 11:07 ` [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
@ 2014-07-16 21:29 ` Julien Grall
  2014-07-17 15:55   ` Ian Campbell
  2014-07-18 12:45 ` Ian Campbell
  15 siblings, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-16 21:29 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 16/07/14 12:07, Thomas Leonard wrote:
> 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 series is rebased on staging, dropping patches that have already been
>    applied.
>
> - The changes have been further split into smaller patches to ease reviewing.
>    Note that the build system isn't changed to allow building the new code until
>    patch 13.
>
> - Define BUG to cause an undefined instruction fault. This lets us us dump the
>    registers.
>
> - Renamed stack to _boot_stack for clarity.
>
> - Include kernel.h from arm/os.h. This is for consistency with x86/os.h
>    and is needed to compile with lwIP.
>
> - Moved SVC stack to first 16KB of RAM (provides some protection against
>    stack overlow corrupting memory).
>
> - Put translation table in second 16KB (simplifies boot code).
>
> - Moved shared_info_page and irqstack to .bss section (smaller image).
>
> - Moved __bss_start and _edata inside section in linker script.
>    The linker adds non-listed sections, such as .got, just before .bss.
>    This meant that we accidentally zeroed those out too.
>
> - Enable floating point unit.
>
> - Require only minimum FDT property lengths (requested by Ian Campbell).
>
> Addressed Julien Grall's comments:
>
> - Get hypercall numbers from xen.h.
> - Avoid duplicating the definition of _start's virtual address.
> - Moved definition of physical_address_offset from asm to C.
> - Added paddr_t type to represent physical addresses.
> - Added comments explaining the lengths when checking FDT properties.
> - Fixed (commented) DEBUG macro.
> - Drop check for arm,cortex-a9-gic.
>
> There are two assumptions the code makes that may need changing in the future, but
> which hopefully don't need to hold up this initial support:
>
> - The assumption that the kernel will be loaded at start of RAM + 0x8000.
>
> - The assumption that Xen will mark the GIC address range as device memory.
>    This should probably be fixed when the C code gains the ability to control
>    the translation tables, map 4K pages, etc.

I'm fine with the assumptions for an initial support. Did you write-down 
somewhere those restrictions? So if an issue happen in the future, we 
will be able to find quickly the issue.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-16 11:07 ` [PATCH ARM v6 07/14] mini-os: arm: boot code Thomas Leonard
@ 2014-07-16 21:49   ` Julien Grall
  2014-07-17  9:37     ` Thomas Leonard
  2014-07-17 16:28   ` Ian Campbell
  1 sibling, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-16 21:49 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 16/07/14 12:07, Thomas Leonard wrote:
> +
> +	@ Tell the system where our page table is located.
> +	@ This is the 16 KB top-level translation table, in which
> +	@ each word maps one 1MB virtual section to a physical section.
> +	mcr	p15, 0, r1, c2, c0, 0	@ set ttbr0 = r1

I don't see any modification of TTBCR (so the initial value is 0). I 
guess you are using short-descriptor translation table format, right? If 
so, I would write somewhere.

> +	@ 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 an entry for the current physical section, at the old and new
> +	@ addresses. It's OK if they're the same.
> +	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
> +	ldr	r4, =_start		@ r4 = desired virtual address of this section
> +	str	r3, [r1, r4, lsr#18] 	@ map desired virtual section to this code
> +	str	r3, [r1, r0, lsr#18]	@ map current section to this code too
> +
> +	@ 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.

Did you intend to mean page table rather than TLB?

[..]

> +irq_handler:
> +	ldr	sp, =irqstack_end
> +	push	{r0 - r12, r14}
> +
> +	ldr	r0, IRQ_handler
> +	cmp	r0, #0
> +	.word	0x07f000f0    	@ undeq - panic if no handler

Hrmmm, I didn't spot this earlier. How can this work? You 
unconditionally called an undefined encoding.

[..]

> 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..21c3893
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/minios-arm32.lds
> @@ -0,0 +1,79 @@
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> +  _boot_stack 	 = 0x400000;	/* 16 KB boot stack */
> +  _boot_stack_end = 0x404000;
> +  _page_dir      = 0x404000;	/* 16 KB translation table */

It might be worse to explain that you are relying on there is a hole 
before the kernel address.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 13/14] mini-os: arm: build system
  2014-07-16 11:07 ` [PATCH ARM v6 13/14] mini-os: arm: build system Thomas Leonard
@ 2014-07-16 22:03   ` Julien Grall
  2014-07-17 10:16     ` Thomas Leonard
  2014-07-28 10:58   ` Ian Campbell
  1 sibling, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-16 22:03 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 16/07/14 12:07, Thomas Leonard wrote:
> Based on an initial patch by Karim Raslan.
>
> This activates the ARM code added in the previous patches. 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

Can you provide instructions to build (git tag/branch...) and test 
mini-os? Also, is there any particular to not build blkfront, netfront, 
consfront?

It would be nice if they are working from the initial support.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-16 21:25   ` Julien Grall
@ 2014-07-17  8:14     ` Thomas Leonard
  2014-07-17  9:04       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-17  8:14 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 16 July 2014 22:25, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
>
> On 16/07/14 12:07, Thomas Leonard wrote:
>>
>> diff --git a/extras/mini-os/include/arm/os.h
>> b/extras/mini-os/include/arm/os.h
>> new file mode 100644
>> index 0000000..6a1cc37
>> --- /dev/null
>> +++ b/extras/mini-os/include/arm/os.h
>> @@ -0,0 +1,216 @@
>> +#ifndef _OS_H_
>> +#define _OS_H_
>> +
>> +#ifndef __ASSEMBLY__
>> +
>> +#include <mini-os/hypervisor.h>
>> +#include <mini-os/types.h>
>> +#include <mini-os/compiler.h>
>> +#include <mini-os/kernel.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){asm volatile (".word 0xe7f000f0\n");} /* Undefined
>> instruction; will call our fault handler. */
>
>
> NIT: I would explain that ARM doesn't provide any undefined instruction so
> we use an encoding that is invalid on ARMv7.

I think it does, although I can't find it in the ARMv7 reference at
the moment. But from
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHJIJCA.html
:

"UND pseudo-instruction

Generate an architecturally undefined instruction. An attempt to
execute an undefined instruction causes the Undefined instruction
exception. Architecturally undefined instructions are expected to
remain undefined.

ARM : 0xV7FYYYFY"

(V is the 4 bits that encode for the condition code, Y allows passing
extra data)


> The other part of this patch looks good to me.
>
> FWIW: Acked-by: Julien Grall <julien.grall@linaro.org>
>
> Regards,
>
> --
> Julien Grall



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

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-17  8:14     ` Thomas Leonard
@ 2014-07-17  9:04       ` Ian Campbell
  2014-07-17 11:41         ` Julien Grall
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-17  9:04 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On Thu, 2014-07-17 at 09:14 +0100, Thomas Leonard wrote:
> On 16 July 2014 22:25, Julien Grall <julien.grall@linaro.org> wrote:
> > Hi Thomas,
> >
> >
> > On 16/07/14 12:07, Thomas Leonard wrote:
> >>
> >> diff --git a/extras/mini-os/include/arm/os.h
> >> b/extras/mini-os/include/arm/os.h
> >> new file mode 100644
> >> index 0000000..6a1cc37
> >> --- /dev/null
> >> +++ b/extras/mini-os/include/arm/os.h
> >> @@ -0,0 +1,216 @@
> >> +#ifndef _OS_H_
> >> +#define _OS_H_
> >> +
> >> +#ifndef __ASSEMBLY__
> >> +
> >> +#include <mini-os/hypervisor.h>
> >> +#include <mini-os/types.h>
> >> +#include <mini-os/compiler.h>
> >> +#include <mini-os/kernel.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){asm volatile (".word 0xe7f000f0\n");} /* Undefined
> >> instruction; will call our fault handler. */
> >
> >
> > NIT: I would explain that ARM doesn't provide any undefined instruction so
> > we use an encoding that is invalid on ARMv7.
> 
> I think it does, although I can't find it in the ARMv7 reference at
> the moment.

In the past I've looked pretty hard for this and been completely unable
to find it. It's interesting that they document it in the assembler
reference.

Prompted by this I took another look and there it is, A8.8.247 defines
"UDF" as a permanently undefined encoding.

>  But from
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHJIJCA.html
> :
> 
> "UND pseudo-instruction

Thanks for the tip, this is the same encoding as the ARM ARM calls UDF,
helpfully with a different name, but it did lead mean to find UDF in the
ARM.

ARMv8 Aarch64 doesn't seem to have the same. It looks like C5.2.2
together with C5.2.7 is defining a set of undefined encodings, but I'm
not 100% clear that they are "permanently undefined", nor does there
appear to be a mnemonic for these encodings. Not sure we can rely on
that.

Ian.

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-16 21:49   ` Julien Grall
@ 2014-07-17  9:37     ` Thomas Leonard
  2014-07-17  9:46       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-17  9:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 16 July 2014 22:49, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
>
> On 16/07/14 12:07, Thomas Leonard wrote:
>>
>> +
>> +       @ Tell the system where our page table is located.
>> +       @ This is the 16 KB top-level translation table, in which
>> +       @ each word maps one 1MB virtual section to a physical section.
>> +       mcr     p15, 0, r1, c2, c0, 0   @ set ttbr0 = r1
>
>
> I don't see any modification of TTBCR (so the initial value is 0). I guess
> you are using short-descriptor translation table format, right? If so, I
> would write somewhere.

Yes, good idea.

>> +       @ 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 an entry for the current physical section, at the old and
>> new
>> +       @ addresses. It's OK if they're the same.
>> +       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
>> +       ldr     r4, =_start             @ r4 = desired virtual address of
>> this section
>> +       str     r3, [r1, r4, lsr#18]    @ map desired virtual section to
>> this code
>> +       str     r3, [r1, r0, lsr#18]    @ map current section to this code
>> too
>> +
>> +       @ 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.
>
>
> Did you intend to mean page table rather than TLB?

Yes. Fixed.

> [..]
>
>
>> +irq_handler:
>> +       ldr     sp, =irqstack_end
>> +       push    {r0 - r12, r14}
>> +
>> +       ldr     r0, IRQ_handler
>> +       cmp     r0, #0
>> +       .word   0x07f000f0      @ undeq - panic if no handler
>
>
> Hrmmm, I didn't spot this earlier. How can this work? You unconditionally
> called an undefined encoding.

Here, the leading "0" is EQ, so it's only executed if IRQ_handler is
unset ("undEQ").

> [..]
>
>
>> 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..21c3893
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/minios-arm32.lds
>> @@ -0,0 +1,79 @@
>> +OUTPUT_ARCH(arm)
>> +ENTRY(_start)
>> +SECTIONS
>> +{
>> +  _boot_stack   = 0x400000;    /* 16 KB boot stack */
>> +  _boot_stack_end = 0x404000;
>> +  _page_dir      = 0x404000;   /* 16 KB translation table */
>
>
> It might be worse to explain that you are relying on there is a hole before
> the kernel address.

OK, will add a note here.


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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-17  9:37     ` Thomas Leonard
@ 2014-07-17  9:46       ` Ian Campbell
  2014-07-17  9:48         ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-17  9:46 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On Thu, 2014-07-17 at 10:37 +0100, Thomas Leonard wrote:

> >> +irq_handler:
> >> +       ldr     sp, =irqstack_end
> >> +       push    {r0 - r12, r14}
> >> +
> >> +       ldr     r0, IRQ_handler
> >> +       cmp     r0, #0
> >> +       .word   0x07f000f0      @ undeq - panic if no handler
> >
> >
> > Hrmmm, I didn't spot this earlier. How can this work? You unconditionally
> > called an undefined encoding.
> 
> Here, the leading "0" is EQ, so it's only executed if IRQ_handler is
> unset ("undEQ").

ARMv7 ARM A8.8.247 says that UDF isn't conditional,so you probably odn't
want to rely on that.

Ian.

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-17  9:46       ` Ian Campbell
@ 2014-07-17  9:48         ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-17  9:48 UTC (permalink / raw)
  To: Ian Campbell
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On 17 July 2014 10:46, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Thu, 2014-07-17 at 10:37 +0100, Thomas Leonard wrote:
>
>> >> +irq_handler:
>> >> +       ldr     sp, =irqstack_end
>> >> +       push    {r0 - r12, r14}
>> >> +
>> >> +       ldr     r0, IRQ_handler
>> >> +       cmp     r0, #0
>> >> +       .word   0x07f000f0      @ undeq - panic if no handler
>> >
>> >
>> > Hrmmm, I didn't spot this earlier. How can this work? You unconditionally
>> > called an undefined encoding.
>>
>> Here, the leading "0" is EQ, so it's only executed if IRQ_handler is
>> unset ("undEQ").
>
> ARMv7 ARM A8.8.247 says that UDF isn't conditional,so you probably odn't
> want to rely on that.

Yes, just noticed that myself. Will replace it with a branch.


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

* Re: [PATCH ARM v6 13/14] mini-os: arm: build system
  2014-07-16 22:03   ` Julien Grall
@ 2014-07-17 10:16     ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-17 10:16 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 16 July 2014 23:03, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
>
> On 16/07/14 12:07, Thomas Leonard wrote:
>>
>> Based on an initial patch by Karim Raslan.
>>
>> This activates the ARM code added in the previous patches. 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
>
>
> Can you provide instructions to build (git tag/branch...) and test mini-os?

$ git clone -b next https://github.com/talex5/xen.git
$ cd xen/extras/mini-os
$ make CONFIG_TEST=y

(if cross-compiling, add XEN_TARGET_ARCH=arm32
CROSS_COMPILE=arm-linux-gnueabihf- )

This is my mini-os.cfg file:

  name = 'mini-os'
  kernel = 'mini-os.img'
  builder = 'linux'
  memory = 16
  on_crash = 'preserve'
  disk = ['/dev/vg0/test,,xvda' ]
  vif = ['mac=c0:ff:ee:c0:ff:ee,bridge=br0' ]

> Also, is there any particular to not build blkfront, netfront, consfront?
>
> It would be nice if they are working from the initial support.

It turned out it didn't build because it wanted rand() from math.c
(which ARM doesn't use).

As rand probably isn't something that should be exposed for general
use (it just calls gettimeofday), I've moved it into test.c (on the
next branch mentioned above).


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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-17  9:04       ` Ian Campbell
@ 2014-07-17 11:41         ` Julien Grall
  0 siblings, 0 replies; 75+ messages in thread
From: Julien Grall @ 2014-07-17 11:41 UTC (permalink / raw)
  To: Ian Campbell, Thomas Leonard
  Cc: xen-devel, Anil Madhavapeddy, David Scott, Samuel Thibault,
	Stefano Stabellini

On 07/17/2014 10:04 AM, Ian Campbell wrote:
> Prompted by this I took another look and there it is, A8.8.247 defines
> "UDF" as a permanently undefined encoding.
> 
>>  But from
>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHJIJCA.html
>> :
>>
>> "UND pseudo-instruction

Good to know, I will also put a link to this section on my WARN series.

-- 
Julien Grall

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

* Re: [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
@ 2014-07-17 15:50   ` Ian Campbell
  2014-07-17 18:15     ` Samuel Thibault
  2014-07-17 18:15   ` Samuel Thibault
  1 sibling, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 15:50 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> Otherwise, passing doubles to varargs functions causes a crash.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

> +    /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */

Is this really effectively a requirement for the stack to start out
misaligned? Or am I misinterpreting it?

Assuming I'm not reading it wrong is this some weird architectural quirk
which I've forgotten about or is it something to do with the behaviour
of thread_starter?

In either case, but especially the latter, I think it would be good to
explain more fully in the comment how this need arises.

...

So, reading the asm code it seems that x86_64 thread_starter will pop
2*quad words and push one, undoing the misalignment you've set up here.
A comment there pointing to this setup here would be good at a minimum,
but an even better fix would be to add a dummy push at that point
keeping both halves of this equation in the same place in that one
function making it responsible for maintaining the invariant.

Ian.


> +    thread->sp -= sizeof(unsigned long);
>      
>      stack_push(thread, (unsigned long) function);
>      stack_push(thread, (unsigned long) data);

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

* Re: [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h
  2014-07-16 13:30   ` Thomas Leonard
@ 2014-07-17 15:51     ` Ian Campbell
  2014-07-17 18:17     ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 15:51 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Wed, 2014-07-16 at 14:30 +0100, Thomas Leonard wrote:
> On 16 July 2014 12:07, Thomas Leonard <talex5@gmail.com> wrote:
> > This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
> > -> lib.h -> gntmap.h -> os.h -> hypervisor.h.
> 
> I've just realised this is missing an include in tpm_tis.c (which
> isn't built by default). Fixed patch attached.

This version looks good to me:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Ian.

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-16 21:29 ` [PATCH ARM v6 00/14] mini-os: initial ARM support Julien Grall
@ 2014-07-17 15:55   ` Ian Campbell
  2014-07-17 16:17     ` Ian Campbell
  2014-07-18  8:17     ` Thomas Leonard
  0 siblings, 2 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 15:55 UTC (permalink / raw)
  To: Julien Grall
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel

On Wed, 2014-07-16 at 22:29 +0100, Julien Grall wrote:

> > There are two assumptions the code makes that may need changing in the future, but
> > which hopefully don't need to hold up this initial support:
> >
> > - The assumption that the kernel will be loaded at start of RAM + 0x8000.
> >
> > - The assumption that Xen will mark the GIC address range as device memory.
> >    This should probably be fixed when the C code gains the ability to control
> >    the translation tables, map 4K pages, etc.
> 
> I'm fine with the assumptions for an initial support. Did you write-down 
> somewhere those restrictions? So if an issue happen in the future, we 
> will be able to find quickly the issue.

Yeah. we can live with them for now, I think. It should be documented
though.

What sort of time line are you foreseeing for fixing them, in terms of
before or after 4.5?

We should probably consider sticking a "tech preview" or similar label
on mini-os/ARM in 4.5 if these issues remain (the load address one in
particular).

Ian.

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
  2014-07-16 21:25   ` Julien Grall
@ 2014-07-17 15:59   ` Ian Campbell
  2014-07-18  1:29     ` Chen Baozi
  2014-07-18  7:58     ` Thomas Leonard
  2014-07-17 18:27   ` Samuel Thibault
  2 siblings, 2 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 15:59 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> 
> Adds header files for future ARM support.
> Based on work by Karim Allah Ahmed.
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>
[...]
> +/********************* common arm32 and arm64  ****************************/
[...]
> +#elif defined(__arm__) || defined(__aarch64__)
> +#include <hypercall-arm.h>
[...]
> +#elif defined(__arm__) || defined(__aarch64__)
> +#include <xen/arch-arm.h>

This series isn't adding aarch64 as well, is it?

I don't object to these being here, I would just be pleasantly surprised
to find arm64 being supported too ;-)

Ian.

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

* Re: [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function
  2014-07-16 11:07 ` [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function Thomas Leonard
@ 2014-07-17 16:00   ` Ian Campbell
  2014-07-17 18:32   ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 16:00 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> __sti is x86 specific.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-17 15:55   ` Ian Campbell
@ 2014-07-17 16:17     ` Ian Campbell
  2014-07-18  8:07       ` Thomas Leonard
  2014-07-18  8:17     ` Thomas Leonard
  1 sibling, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 16:17 UTC (permalink / raw)
  To: Julien Grall
  Cc: Thomas Leonard, Dave.Scott, stefano.stabellini, anil, xen-devel,
	samuel.thibault

On Thu, 2014-07-17 at 16:55 +0100, Ian Campbell wrote:

> > > - The assumption that the kernel will be loaded at start of RAM + 0x8000.

Reading the comments in 07/14 -- is this limitation still present? It
looks like you are at least partially handling it?

Ian.

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-16 11:07 ` [PATCH ARM v6 07/14] mini-os: arm: boot code Thomas Leonard
  2014-07-16 21:49   ` Julien Grall
@ 2014-07-17 16:28   ` Ian Campbell
  2014-07-30 10:47     ` Thomas Leonard
  1 sibling, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-17 16:28 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> +	@ 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.

ARMv7 (or perhaps it was the virt extensions, either way you can rely on
it here) makes the MMU cache coherent, so you don't need to flush the
caches when doing a PTE write any more.

> +       @ 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

I think you want a dsb here to ensure that any previous PTE write you
did when setting up the PTs have actually occurred.

> +       mcr     p15, 0, r1, c1, c0, 0   @ SCTLR
> +       isb
> +

> +	adr	r1, stage2		@ Physical address of stage2
> +	sub	r1, r1, r9		@ Virtual address of stage2

ldr r1, =stage2

would do this in one, I think.

> +	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)
> +@    r7 = virtual address of page table
> +@    r8 = section entry template (flags)
> +@    r9 = desired physical - virtual offset
> +@    pc -> somewhere in newly-mapped virtual code section
> +stage2:

I think you want another dsb around here somewhere to ensure that none
of the PT updates you do in a moment float up and interfere with the
mapping of the code between the write to SCTLR until the bx r1.

> +	@ 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

dsb here to make sure those writes have actually occurred before you
come to rely on them.

If there is any chance of any of those writes going through a mapping
which you are then changing at the same time then I worry that you might
also need a dsb before each write. I'm not 100% sure what would happen
in this case, I think you'd be better off creating a whole new set of
PTs rather than pulling the rug out from under yourself. It's either
that or cold towel on head time ;-)

Ian.

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

* Re: [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-17 15:50   ` Ian Campbell
@ 2014-07-17 18:15     ` Samuel Thibault
  2014-07-18 10:00       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:15 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Thomas Leonard, stefano.stabellini, Dave.Scott, anil

Ian Campbell, le Thu 17 Jul 2014 16:50:25 +0100, a écrit :
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> > Otherwise, passing doubles to varargs functions causes a crash.
> > 
> > Signed-off-by: Thomas Leonard <talex5@gmail.com>
> 
> > +    /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
> 
> Is this really effectively a requirement for the stack to start out
> misaligned?

Yes. From the x86_64 ABI pdf I have here:

“
The end of the input argument area shall be aligned on a 16 byte boundary.
In other words, the value (%rsp - 8) is always a multiple of 16 when control is
transferred to the function entry point.
”

So the proposed comment is exactly the ABI requirement. Maybe it should
even say

/* x86_64 ABI requires that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */

Samuel

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

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

* Re: [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
  2014-07-17 15:50   ` Ian Campbell
@ 2014-07-17 18:15   ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:15 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Wed 16 Jul 2014 12:07:41 +0100, a écrit :
> Otherwise, passing doubles to varargs functions causes a crash.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/arch/x86/sched.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/extras/mini-os/arch/x86/sched.c b/extras/mini-os/arch/x86/sched.c
> index 8a05b58..e4a3dc2 100644
> --- a/extras/mini-os/arch/x86/sched.c
> +++ b/extras/mini-os/arch/x86/sched.c
> @@ -107,6 +107,9 @@ struct thread* arch_create_thread(char *name, void (*function)(void *),
>      thread->sp = (unsigned long)thread->stack + STACK_SIZE;
>      /* Save pointer to the thread on the stack, used by current macro */
>      *((unsigned long *)thread->stack) = (unsigned long)thread;
> +
> +    /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
> +    thread->sp -= sizeof(unsigned long);
>      
>      stack_push(thread, (unsigned long) function);
>      stack_push(thread, (unsigned long) data);
> -- 
> 2.0.1
> 

-- 
Samuel
<m> argh, pi est plus grand que 2. Ca casse tout
 -+- #ens-mim -+-

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

* Re: [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h
  2014-07-16 13:30   ` Thomas Leonard
  2014-07-17 15:51     ` Ian Campbell
@ 2014-07-17 18:17     ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:17 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Anil Madhavapeddy, David Scott, Stefano Stabellini

Thomas Leonard, le Wed 16 Jul 2014 14:30:43 +0100, a écrit :
> On 16 July 2014 12:07, Thomas Leonard <talex5@gmail.com> wrote:
> > This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
> > -> lib.h -> gntmap.h -> os.h -> hypervisor.h.
> 
> I've just realised this is missing an include in tpm_tis.c (which
> isn't built by default). Fixed patch attached.

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

> 
> -- 
> 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

> From 98705b128feb2e46272c4d29205f384899108704 Mon Sep 17 00:00:00 2001
> From: Thomas Leonard <talex5@gmail.com>
> Date: Mon, 7 Jul 2014 13:20:43 +0100
> Subject: [PATCH] mini-os: don't include lib.h from mm.h
> 
> This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
> -> lib.h -> gntmap.h -> os.h -> hypervisor.h.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> 
> ---
> 
> - Added missing #include <mini-os/lib.h> to tpm_tis.c
> ---
>  extras/mini-os/include/mm.h | 3 +--
>  extras/mini-os/lock.c       | 1 +
>  extras/mini-os/main.c       | 1 +
>  extras/mini-os/tpm_tis.c    | 1 +
>  extras/mini-os/tpmfront.c   | 1 +
>  5 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
> index a94cd6d..a177251 100644
> --- a/extras/mini-os/include/mm.h
> +++ b/extras/mini-os/include/mm.h
> @@ -32,8 +32,7 @@
>  #else
>  #error "Unsupported architecture"
>  #endif
> -
> -#include <mini-os/lib.h>
> +#include <xen/xen.h>
>  
>  #include <mini-os/arch_limits.h>
>  #include <mini-os/arch_mm.h>
> diff --git a/extras/mini-os/lock.c b/extras/mini-os/lock.c
> index 71a4971..61194e5 100644
> --- a/extras/mini-os/lock.c
> +++ b/extras/mini-os/lock.c
> @@ -9,6 +9,7 @@
>  #include <sys/lock.h>
>  #include <sched.h>
>  #include <wait.h>
> +#include <mini-os/lib.h>
>  
>  int ___lock_init(_LOCK_T *lock)
>  {
> diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
> index aec0586..4ec40b5 100644
> --- a/extras/mini-os/main.c
> +++ b/extras/mini-os/main.c
> @@ -15,6 +15,7 @@
>  #include <unistd.h>
>  #include <xenbus.h>
>  #include <events.h>
> +#include <mini-os/lib.h>
>  
>  extern int main(int argc, char *argv[], char *envp[]);
>  extern void __libc_init_array(void);
> diff --git a/extras/mini-os/tpm_tis.c b/extras/mini-os/tpm_tis.c
> index e8ca69f..09234e5 100644
> --- a/extras/mini-os/tpm_tis.c
> +++ b/extras/mini-os/tpm_tis.c
> @@ -26,6 +26,7 @@
>  #include <mini-os/events.h>
>  #include <mini-os/wait.h>
>  #include <mini-os/xmalloc.h>
> +#include <mini-os/lib.h>
>  #include <errno.h>
>  #include <stdbool.h>
>  
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index ce5b3e1..6049244 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -31,6 +31,7 @@
>  #include <xen/io/xenbus.h>
>  #include <xen/io/tpmif.h>
>  #include <mini-os/tpmfront.h>
> +#include <mini-os/lib.h>
>  #include <fcntl.h>
>  
>  //#define TPMFRONT_PRINT_DEBUG
> -- 
> 2.0.1
> 


-- 
Samuel
<d> bah à défaut de ligne TGV, ils ont un GR
 -+- #ens-mim - comment ça, paumé ?! -+-

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
  2014-07-16 21:25   ` Julien Grall
  2014-07-17 15:59   ` Ian Campbell
@ 2014-07-17 18:27   ` Samuel Thibault
  2014-07-18  7:54     ` Thomas Leonard
  2 siblings, 1 reply; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:27 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Wed 16 Jul 2014 12:07:44 +0100, a écrit :
> +extern int physical_address_offset;	/* Add this to a virtual address to get the physical address (wraps) */

int only?

Apart from that,

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

Samuel

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

* Re: [PATCH ARM v6 05/14] mini-os: import libfdt
  2014-07-16 13:34         ` Ian Campbell
  2014-07-16 14:13           ` Anil Madhavapeddy
@ 2014-07-17 18:30           ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:30 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Thomas Leonard, Dave.Scott, anil, Andrew Cooper,
	stefano.stabellini, xen-devel

Ian Campbell, le Wed 16 Jul 2014 14:34:42 +0100, a écrit :
> On Wed, 2014-07-16 at 14:02 +0100, Andrew Cooper wrote:
> > On 16/07/14 13:29, Ian Campbell wrote:
> > > On Wed, 2014-07-16 at 12:44 +0100, Andrew Cooper wrote:
> > >> On 16/07/14 12:07, 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
> > >>>
> > >>> The memmove implementation is from FreeBSD's
> > >>> contrib/ldns/compat/memmove.c (r246827).
> > >>>
> > >>> 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>
> > >> Xen already has a copy of libfdt in xen/common/libfdt.
> > > Please review the thread on this from the previous postings.
> > >
> > > Ian.
> > >
> > 
> > Which appears to be unconcluded.
> 
> http://article.gmane.org/gmane.comp.emulators.xen.devel/205280 looked
> conclusive to me.
> 
> > libfdt is a 3rd party library which, from what I can tell in the
> > history, is unmodified.  Therefore, my suggestion of moving it outside
> > of the xen/ tree and having both minios and Xen VPATH themselves access
> > to it helps with the end goal of preventing minios becoming dependent on
> > Xen code.  It further prevents both Xen and minios from accidentally
> > gaining localisation hacks in the library itself, which makes it easier
> > to updates to the base libdft if/when necessary.
> 
> This would mean that splitting extras/mini-os off wouldn't be just a
> case of doing that, you'd also need arrange for the VPATH to be
> satisfied, I don't know if Anil et al will be happy with that.
> 
> Ultimately this is up to Samuel if he is happy with the current approach
> or not.

I'd say it should be fine to make mini-os use a shared copy of libfdt if
it's made easy to make it use a copy from another place: people who want
to build mini-os out of a xen tree can then just stuff a copy of libfdt
wherever they feel like, and point mini-os to it.

Samuel

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

* Re: [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function
  2014-07-16 11:07 ` [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function Thomas Leonard
  2014-07-17 16:00   ` Ian Campbell
@ 2014-07-17 18:32   ` Samuel Thibault
  1 sibling, 0 replies; 75+ messages in thread
From: Samuel Thibault @ 2014-07-17 18:32 UTC (permalink / raw)
  To: Thomas Leonard; +Cc: xen-devel, anil, Dave.Scott, stefano.stabellini

Thomas Leonard, le Wed 16 Jul 2014 12:07:46 +0100, a écrit :
> __sti is x86 specific.
> 
> Signed-off-by: Thomas Leonard <talex5@gmail.com>

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

> ---
>  extras/mini-os/kernel.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> 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.1
> 

-- 
Samuel
Accroche-toi au terminal, j'enlève le shell...
 -+- nojhan -+-

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-17 15:59   ` Ian Campbell
@ 2014-07-18  1:29     ` Chen Baozi
  2014-07-18  7:58     ` Thomas Leonard
  1 sibling, 0 replies; 75+ messages in thread
From: Chen Baozi @ 2014-07-18  1:29 UTC (permalink / raw)
  To: Campbell Ian
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel


On Jul 17, 2014, at 23:59, Ian Campbell <Ian.Campbell@citrix.com> wrote:

> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>> 
>> Adds header files for future ARM support.
>> Based on work by Karim Allah Ahmed.
>> 
>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> [...]
>> +/********************* common arm32 and arm64  ****************************/
> [...]
>> +#elif defined(__arm__) || defined(__aarch64__)
>> +#include <hypercall-arm.h>
> [...]
>> +#elif defined(__arm__) || defined(__aarch64__)
>> +#include <xen/arch-arm.h>
> 
> This series isn't adding aarch64 as well, is it?
> 
> I don't object to these being here, I would just be pleasantly surprised
> to find arm64 being supported too ;-)


I’ve made an initial (very early stage) repo for arm64 on https://github.com/baozich/minios-arm64
Haven’t got time to complement the rest codes yet...

Cheers,

Baozi

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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-17 18:27   ` Samuel Thibault
@ 2014-07-18  7:54     ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-18  7:54 UTC (permalink / raw)
  To: Samuel Thibault, Thomas Leonard, xen-devel, Stefano Stabellini,
	Anil Madhavapeddy, David Scott, KarimAllah Ahmed

On 17 July 2014 19:27, Samuel Thibault <samuel.thibault@ens-lyon.org> wrote:
> Thomas Leonard, le Wed 16 Jul 2014 12:07:44 +0100, a écrit :
>> +extern int physical_address_offset;  /* Add this to a virtual address to get the physical address (wraps) */
>
> int only?

I'll make it "unsigned long" (long and int are the same on ARM, but
paddr_t is defined that way too).


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

* Re: [PATCH ARM v6 04/14] mini-os: headers for ARM
  2014-07-17 15:59   ` Ian Campbell
  2014-07-18  1:29     ` Chen Baozi
@ 2014-07-18  7:58     ` Thomas Leonard
  1 sibling, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-18  7:58 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 17 July 2014 16:59, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> From: Karim Raslan <karim.allah.ahmed@gmail.com>
>>
>> Adds header files for future ARM support.
>> Based on work by Karim Allah Ahmed.
>>
>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> [...]
>> +/********************* common arm32 and arm64  ****************************/
> [...]
>> +#elif defined(__arm__) || defined(__aarch64__)
>> +#include <hypercall-arm.h>
> [...]
>> +#elif defined(__arm__) || defined(__aarch64__)
>> +#include <xen/arch-arm.h>
>
> This series isn't adding aarch64 as well, is it?
>
> I don't object to these being here, I would just be pleasantly surprised
> to find arm64 being supported too ;-)

These changes are from Karim's original patches. Unfortunately, I
don't have any arm64 hardware myself.


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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-17 16:17     ` Ian Campbell
@ 2014-07-18  8:07       ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-07-18  8:07 UTC (permalink / raw)
  To: Ian Campbell
  Cc: David Scott, Stefano Stabellini, Julien Grall, xen-devel,
	Samuel Thibault, Anil Madhavapeddy

On 17 July 2014 17:17, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Thu, 2014-07-17 at 16:55 +0100, Ian Campbell wrote:
>
>> > > - The assumption that the kernel will be loaded at start of RAM + 0x8000.
>
> Reading the comments in 07/14 -- is this limitation still present? It
> looks like you are at least partially handling it?

It's still present.

Before (in v5), the translation table was in the .data section and
therefore could end up in a different memory section to the boot code.
By moving it to 0x4000, I simplified all that logic because we now
know that the translation table and the boot code are both in the same
1MB memory section, which avoids any problem with the old and new
mappings overlapping.


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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-17 15:55   ` Ian Campbell
  2014-07-17 16:17     ` Ian Campbell
@ 2014-07-18  8:17     ` Thomas Leonard
  2014-07-18 10:07       ` Ian Campbell
  1 sibling, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-18  8:17 UTC (permalink / raw)
  To: Ian Campbell
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On 17 July 2014 16:55, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-16 at 22:29 +0100, Julien Grall wrote:
>
>> > There are two assumptions the code makes that may need changing in the future, but
>> > which hopefully don't need to hold up this initial support:
>> >
>> > - The assumption that the kernel will be loaded at start of RAM + 0x8000.
>> >
>> > - The assumption that Xen will mark the GIC address range as device memory.
>> >    This should probably be fixed when the C code gains the ability to control
>> >    the translation tables, map 4K pages, etc.
>>
>> I'm fine with the assumptions for an initial support. Did you write-down
>> somewhere those restrictions? So if an issue happen in the future, we
>> will be able to find quickly the issue.
>
> Yeah. we can live with them for now, I think. It should be documented
> though.

I've noted the offset requirement in the linker script and the GIC
memory type assumption in a comment in gic.c.

> What sort of time line are you foreseeing for fixing them, in terms of
> before or after 4.5?

If the GIC will always occupy a distinct set of 1MB sections then
flagging those is easy enough. Otherwise, we'd have to add support for
the second-level page tables, which would complicate things a little.

Making the boot code work from arbitrary offsets looks very difficult.
I guess we'd need to compile libfdt as PIC, set up a temporary C stack
after the kernel (we can assume there's some RAM following it I
think), parse the FDT to find the base address, copy the kernel
forwards or backwards word by word (first copying the copying code to
a safe location somewhere).

It all seems very inefficient. From my point of view, it would seem
better to have some way to specify the desired load offset.

> We should probably consider sticking a "tech preview" or similar label
> on mini-os/ARM in 4.5 if these issues remain (the load address one in
> particular).


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

* Re: [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-17 18:15     ` Samuel Thibault
@ 2014-07-18 10:00       ` Ian Campbell
  2014-07-18 13:22         ` Samuel Thibault
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-18 10:00 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: xen-devel, Thomas Leonard, stefano.stabellini, Dave.Scott, anil

On Thu, 2014-07-17 at 20:15 +0200, Samuel Thibault wrote:
> Ian Campbell, le Thu 17 Jul 2014 16:50:25 +0100, a écrit :
> > On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> > > Otherwise, passing doubles to varargs functions causes a crash.
> > > 
> > > Signed-off-by: Thomas Leonard <talex5@gmail.com>
> > 
> > > +    /* Must ensure that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */
> > 
> > Is this really effectively a requirement for the stack to start out
> > misaligned?
> 
> Yes. From the x86_64 ABI pdf I have here:
> 
> “
> The end of the input argument area shall be aligned on a 16 byte boundary.
> In other words, the value (%rsp - 8) is always a multiple of 16 when control is
> transferred to the function entry point.
> ”
> 
> So the proposed comment is exactly the ABI requirement.

I see. How exciting!

I suppose this comes from the stack normally being 16-byte aligned but
the actual call to the function adding another 8 by pushing the return
address, so on funciton entry you are "misaligned" by 8 bytes. So this
offset is accounting for the fact that thread_starter is (in effect)
entered with a jmp and not a call.

>  Maybe it should
> even say
> 
> /* x86_64 ABI requires that (%rsp + 8) is 16-byte aligned at the start of thread_starter. */

With your explanation I'm happy with whatever you are happy with ;-)

Ian.


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

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-18  8:17     ` Thomas Leonard
@ 2014-07-18 10:07       ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-18 10:07 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: David Scott, Anil Madhavapeddy, Julien Grall, Samuel Thibault,
	xen-devel, Stefano Stabellini

On Fri, 2014-07-18 at 09:17 +0100, Thomas Leonard wrote:
> On 17 July 2014 16:55, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Wed, 2014-07-16 at 22:29 +0100, Julien Grall wrote:
> >
> >> > There are two assumptions the code makes that may need changing in the future, but
> >> > which hopefully don't need to hold up this initial support:
> >> >
> >> > - The assumption that the kernel will be loaded at start of RAM + 0x8000.
> >> >
> >> > - The assumption that Xen will mark the GIC address range as device memory.
> >> >    This should probably be fixed when the C code gains the ability to control
> >> >    the translation tables, map 4K pages, etc.
> >>
> >> I'm fine with the assumptions for an initial support. Did you write-down
> >> somewhere those restrictions? So if an issue happen in the future, we
> >> will be able to find quickly the issue.
> >
> > Yeah. we can live with them for now, I think. It should be documented
> > though.
> 
> I've noted the offset requirement in the linker script and the GIC
> memory type assumption in a comment in gic.c.
> 
> > What sort of time line are you foreseeing for fixing them, in terms of
> > before or after 4.5?
> 
> If the GIC will always occupy a distinct set of 1MB sections then
> flagging those is easy enough.

I don't think that is guaranteed, but I've not dug deeply into the GIC
spec, I don't think it says anything about the relative placement of the
various sub functions though.

>  Otherwise, we'd have to add support for
> the second-level page tables, which would complicate things a little.
> 
> Making the boot code work from arbitrary offsets looks very difficult.

Xen itself manages it (not quite arbitrary, it assumes 4K alignment), so
does Linux (completely arbitrary I think), it's not that hard, you just
need to switch to a virtual mapping before you hit C or any non-PIE
code. Once you have a virtual mapping you don't actually care about the
load address any more.

> I guess we'd need to compile libfdt as PIC, set up a temporary C stack
> after the kernel (we can assume there's some RAM following it I
> think), parse the FDT to find the base address, copy the kernel
> forwards or backwards word by word (first copying the copying code to
> a safe location somewhere).
> 
> It all seems very inefficient.

The mechanism which you propose certainly is, yes. But I don't think any
of what you describe is necessary.

>  From my point of view, it would seem
> better to have some way to specify the desired load offset.

Sadly the zImage header is what it is and doesn't include this.

Ian.

> > We should probably consider sticking a "tech preview" or similar label
> > on mini-os/ARM in 4.5 if these issues remain (the load address one in
> > particular).
> 
> 

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
                   ` (14 preceding siblings ...)
  2014-07-16 21:29 ` [PATCH ARM v6 00/14] mini-os: initial ARM support Julien Grall
@ 2014-07-18 12:45 ` Ian Campbell
  2014-08-05 10:56   ` Thomas Leonard
  15 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-18 12:45 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil


On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:

I tried to apply:
mini-os: x86_64: make thread stacks 16-byte aligned
mini-os: don't include lib.h from mm.h (the second, attached, version)
mini-os: added HYPERVISOR_xsm_op
mini-os: use generic local_irq_enable function

but got:
        vtpm_cmd_handler.c: In function ‘tm_dhkx_gen’:
        vtpm_cmd_handler.c:486:3: error: implicit declaration of function ‘ARRAY_SIZE’ [-Werror=implicit-function-declaration]
        cc1: all warnings being treated as errors
        make[2]: *** [vtpm_cmd_handler.o] Error 1
        make[2]: *** Waiting for unfinished jobs....
        disk_tpm.c: In function ‘TPM_disk_seal’:
        disk_tpm.c:84:2: error: implicit declaration of function ‘printk’ [-Werror=implicit-function-declaration]
        cc1: all warnings being treated as errors
        make[2]: *** [disk_tpm.o] Error 1
        make[2]: Entering directory `/local/scratch/ianc/devel/committer-amd64.git/stubdom/libxc-x86_64'
        make libs

Which I think was the mm.h one.

Then I got:
        In file included from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
                         from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/lib.h:55,
                         from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/mm.h:36,
                         from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/x86/x86_64/hypercall-x86_64.h:39,
                         from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/hypervisor.h:20,
                         from mini-os.c:13:
        /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/x86/os.h: In function ‘HYPERVISOR_xsm_op’:
        /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/x86/os.h:566:21: error: expected expression before ‘int’
        mini-os.c: In function ‘main’:
        mini-os.c:756:35: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
        make[2]: *** [/local/scratch/ianc/devel/committer-amd64.git/stubdom/grub-x86_64/mini-os.o] Error 1
        make[2]: *** Waiting for unfinished jobs....

Which I assume was the XSM one.

So I only ended up applying:
mini-os: x86_64: make thread stacks 16-byte aligned
mini-os: use generic local_irq_enable function


Cheers,
Ian



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

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

* Re: [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned
  2014-07-18 10:00       ` Ian Campbell
@ 2014-07-18 13:22         ` Samuel Thibault
  0 siblings, 0 replies; 75+ messages in thread
From: Samuel Thibault @ 2014-07-18 13:22 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Thomas Leonard, stefano.stabellini, Dave.Scott, anil

Ian Campbell, le Fri 18 Jul 2014 11:00:45 +0100, a écrit :
> I suppose this comes from the stack normally being 16-byte aligned but
> the actual call to the function adding another 8 by pushing the return
> address, so on funciton entry you are "misaligned" by 8 bytes.

Yes.

Samuel

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

* Re: [PATCH ARM v6 08/14] mini-os: arm: memory management
  2014-07-16 11:07 ` [PATCH ARM v6 08/14] mini-os: arm: memory management Thomas Leonard
@ 2014-07-21 17:36   ` Julien Grall
  2014-08-03 10:23     ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-21 17:36 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 07/16/2014 12:07 PM, Thomas Leonard wrote:
> Based on an initial patch by Karim Raslan.
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> 
> ---
> 
> Changes since v5:
> 
> - Require only minimum property lengths (requested by Ian Campbell).
> 
> Addressed Julien Grall's comments:
> - Added comments explaining the lengths when checking FDT properties.
> - Use paddr_t type to represent physical addresses.
> ---
>  extras/mini-os/arch/arm/mm.c | 138 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 138 insertions(+)
>  create mode 100644 extras/mini-os/arch/arm/mm.c
> 
> diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
> new file mode 100644
> index 0000000..ec1f821
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/mm.c
> @@ -0,0 +1,138 @@
> +#include <mini-os/console.h>
> +#include <xen/memory.h>
> +#include <arch_mm.h>
> +#include <mini-os/hypervisor.h>
> +#include <libfdt.h>
> +#include <lib.h>
> +
> +int physical_address_offset;

int64_t maybe?

> +
> +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)
> +{

[..]

> +    unsigned int end = (unsigned int) &_end;
> +    paddr_t mem_base = fdt64_to_cpu(regs[0]);
> +    unsigned int mem_size = fdt64_to_cpu(regs[1]);

mem_size should be a paddr_t. Even though, the first bank will always
have the size fit in 32 bits.

> +    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);

You need to use at least an unsigned int here. And it will be better if
you use paddr_t.

> +    *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);

uint32_t has the definition of the field totalsize in the fdt structure.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 11/14] mini-os: arm: time
  2014-07-16 11:07 ` [PATCH ARM v6 11/14] mini-os: arm: time Thomas Leonard
@ 2014-07-21 17:45   ` Julien Grall
  2014-07-28 10:41     ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Julien Grall @ 2014-07-21 17:45 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 07/16/2014 12:07 PM, Thomas Leonard wrote:
> +/* 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;
> +}

It looks the code above is the same as x86. Did you think about sharing
the code which used Xen time?

Looking closer to this patch, nothing is using the field of this shared
structure, which is CPU time consuming and adding line for no
improvement. So I think you can drop all the code related the PV timer
for now.

Regards,

-- 
Julien Grall

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

* Re: [PATCH ARM v6 12/14] mini-os: arm: interrupt controller
  2014-07-16 11:07 ` [PATCH ARM v6 12/14] mini-os: arm: interrupt controller Thomas Leonard
@ 2014-07-21 17:56   ` Julien Grall
  0 siblings, 0 replies; 75+ messages in thread
From: Julien Grall @ 2014-07-21 17:56 UTC (permalink / raw)
  To: Thomas Leonard, xen-devel
  Cc: samuel.thibault, stefano.stabellini, Dave.Scott, anil

Hi Thomas,

On 07/16/2014 12:07 PM, Thomas Leonard wrote:
> +/* 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);

I didn't spot this before. Why didn't you use if (level_sensitive)...?

I found this line very hard to read.

[..]

> +//FIXME Get event_irq from dt
> +#define EVENTS_IRQ 31
> +#define VIRTUALTIMER_IRQ 27

Any plan to get this from the DT soon?

The rest of the patch looks good to me.

Regards,


-- 
Julien Grall

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

* Re: [PATCH ARM v6 11/14] mini-os: arm: time
  2014-07-21 17:45   ` Julien Grall
@ 2014-07-28 10:41     ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 10:41 UTC (permalink / raw)
  To: Julien Grall
  Cc: Thomas Leonard, Dave.Scott, anil, stefano.stabellini,
	samuel.thibault, xen-devel

On Mon, 2014-07-21 at 18:45 +0100, Julien Grall wrote:
> Hi Thomas,
> 
> On 07/16/2014 12:07 PM, Thomas Leonard wrote:
> > +/* 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;
> > +}
> 
> It looks the code above is the same as x86. Did you think about sharing
> the code which used Xen time?
> 
> Looking closer to this patch, nothing is using the field of this shared
> structure, which is CPU time consuming and adding line for no
> improvement. So I think you can drop all the code related the PV timer
> for now.

Does Xen even populate this struct on ARM? I'm not sure...

Ian.

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

* Re: [PATCH ARM v6 09/14] mini-os: arm: scheduling
  2014-07-16 11:07 ` [PATCH ARM v6 09/14] mini-os: arm: scheduling Thomas Leonard
@ 2014-07-28 10:53   ` Ian Campbell
  2014-07-28 11:20     ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 10:53 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> Based on an initial patch by Karim Raslan.
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/arch/arm/arm32.S | 22 ++++++++++++++++++++++
>  extras/mini-os/arch/arm/sched.c | 38 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 60 insertions(+)
>  create mode 100644 extras/mini-os/arch/arm/sched.c
> 
> diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
> index 88efe24..56429b1 100644
> --- a/extras/mini-os/arch/arm/arm32.S
> +++ b/extras/mini-os/arch/arm/arm32.S
> @@ -204,8 +204,30 @@ 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

I'm a bit confused by the lack of saving of the GPRs here. Shouldn't at
least the caller saved registers (r4..r11) be saved/restored here?

> +void run_idle_thread(void)
> +{
> +    __asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), "r"(idle_thread->ip));

Is bx preferred to mov pc these days? I don't know if it matters in this
case...


> +    /* Never arrive here! */
> +}

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

* Re: [PATCH ARM v6 10/14] mini-os: arm: events
  2014-07-16 11:07 ` [PATCH ARM v6 10/14] mini-os: arm: events Thomas Leonard
@ 2014-07-28 10:55   ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 10:55 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> From: Karim Raslan <karim.allah.ahmed@gmail.com>
> 
> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> ---
>  extras/mini-os/arch/arm/events.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 extras/mini-os/arch/arm/events.c
> 
> diff --git a/extras/mini-os/arch/arm/events.c b/extras/mini-os/arch/arm/events.c
> new file mode 100644
> index 0000000..441010d
> --- /dev/null
> +++ b/extras/mini-os/arch/arm/events.c
> @@ -0,0 +1,31 @@
> +#include <mini-os/os.h>
> +#include <mini-os/events.h>
> +#include <mini-os/hypervisor.h>
> +#include <mini-os/console.h>
> +
> +static void virq_debug(evtchn_port_t port, struct pt_regs *regs, void *params)
> +{
> +    printk("Received a virq_debug event\n");

It hardly seems worth the effort of receiving this ;-)

Acked-by: Ian Campbell <ian.campbell@citrix.com>

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

* Re: [PATCH ARM v6 13/14] mini-os: arm: build system
  2014-07-16 11:07 ` [PATCH ARM v6 13/14] mini-os: arm: build system Thomas Leonard
  2014-07-16 22:03   ` Julien Grall
@ 2014-07-28 10:58   ` Ian Campbell
  1 sibling, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 10:58 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> +* make sure that wallclock is functioning properly

FYI:
http://wiki.xen.org/wiki/Xen_ARM_TODO#Expose_Wallclock_time_to_guests

[...]

Ian.

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

* Re: [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault
  2014-07-16 11:07 ` [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
@ 2014-07-28 11:13   ` Ian Campbell
  2014-07-28 11:49     ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 11:13 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, stefano.stabellini, Dave.Scott, samuel.thibault, anil

On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> +@ 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.

You do corrupt r13 though.

The way many OSes handle this is to make at least the initial saving
(i.e. that which you have at fault:) into a macro and inlining a copy at
each entry point. They also arrange for each SP_$mode to always point to
something useful (in your case fault_dump, I guess) to avoid using a
register as the save target.

BTW you can infer the same information as you do all this -12 stuff for
from the saved CPSR.

Ian.

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

* Re: [PATCH ARM v6 09/14] mini-os: arm: scheduling
  2014-07-28 10:53   ` Ian Campbell
@ 2014-07-28 11:20     ` Thomas Leonard
  2014-07-28 11:26       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-28 11:20 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 28 July 2014 11:53, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> Based on an initial patch by Karim Raslan.
>>
>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>> ---
>>  extras/mini-os/arch/arm/arm32.S | 22 ++++++++++++++++++++++
>>  extras/mini-os/arch/arm/sched.c | 38 ++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 60 insertions(+)
>>  create mode 100644 extras/mini-os/arch/arm/sched.c
>>
>> diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
>> index 88efe24..56429b1 100644
>> --- a/extras/mini-os/arch/arm/arm32.S
>> +++ b/extras/mini-os/arch/arm/arm32.S
>> @@ -204,8 +204,30 @@ 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
>
> I'm a bit confused by the lack of saving of the GPRs here. Shouldn't at
> least the caller saved registers (r4..r11) be saved/restored here?

If they were caller saved then sched.c would save them itself before
calling switch_threads. But the AAPCS says:

"A subroutine must preserve the contents of the registers r4-r8, r10,
r11 and SP (and r9 in PCS variants that designate r9 as v6)."

So I think these are callee-saved and we should save them here.

>> +void run_idle_thread(void)
>> +{
>> +    __asm__ __volatile__ ("mov sp, %0; mov pc, %1"::"r"(idle_thread->sp), "r"(idle_thread->ip));
>
> Is bx preferred to mov pc these days? I don't know if it matters in this
> case...

Yes, that would probably be better (in both places).


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

* Re: [PATCH ARM v6 09/14] mini-os: arm: scheduling
  2014-07-28 11:20     ` Thomas Leonard
@ 2014-07-28 11:26       ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 11:26 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Mon, 2014-07-28 at 12:20 +0100, Thomas Leonard wrote:
> On 28 July 2014 11:53, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> >> Based on an initial patch by Karim Raslan.
> >>
> >> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
> >> Signed-off-by: Thomas Leonard <talex5@gmail.com>
> >> ---
> >>  extras/mini-os/arch/arm/arm32.S | 22 ++++++++++++++++++++++
> >>  extras/mini-os/arch/arm/sched.c | 38 ++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 60 insertions(+)
> >>  create mode 100644 extras/mini-os/arch/arm/sched.c
> >>
> >> diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S
> >> index 88efe24..56429b1 100644
> >> --- a/extras/mini-os/arch/arm/arm32.S
> >> +++ b/extras/mini-os/arch/arm/arm32.S
> >> @@ -204,8 +204,30 @@ 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
> >
> > I'm a bit confused by the lack of saving of the GPRs here. Shouldn't at
> > least the caller saved registers (r4..r11) be saved/restored here?
> 
> If they were caller saved then sched.c would save them itself before
> calling switch_threads. But the AAPCS says:
> 
> "A subroutine must preserve the contents of the registers r4-r8, r10,
> r11 and SP (and r9 in PCS variants that designate r9 as v6)."
> 
> So I think these are callee-saved and we should save them here.

I had a typo in my register/AAPCS cheatsheet but not in my head, so I
was kind of right for the wrong reason ;-). r4..r11 are indeed *callee*
saved.

Normally on ctxt switch you would save and restore everything to prevent
information leaks but since mini-os processes^Wthreads are mutually
trusting it doesn't seem entirely necessary here (but it does save
remembering which registers are which ;-)).

Ian.

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

* Re: [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault
  2014-07-28 11:13   ` Ian Campbell
@ 2014-07-28 11:49     ` Thomas Leonard
  2014-07-28 12:01       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-28 11:49 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 28 July 2014 12:13, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> +@ 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.
>
> You do corrupt r13 though.

r13 is banked for all faults except SVC. Possibly for SVC we should do
something different (though you'll always lose r14 anyway if SVC code
makes an SVC call for some reason).

> The way many OSes handle this is to make at least the initial saving
> (i.e. that which you have at fault:) into a macro and inlining a copy at
> each entry point. They also arrange for each SP_$mode to always point to
> something useful (in your case fault_dump, I guess) to avoid using a
> register as the save target.

You mean dumping the registers to the SVC stack in the SVC fault
handler? That might cause another fault if the stack is full, but I
may be misunderstanding you.

> BTW you can infer the same information as you do all this -12 stuff for
> from the saved CPSR.

You mean by looking at the processor mode? There are two exceptions
that both go to Abort mode though. I haven't checked to see whether
the information could be recovered some other way; substracting 12
seemed pretty easy.


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

* Re: [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault
  2014-07-28 11:49     ` Thomas Leonard
@ 2014-07-28 12:01       ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-28 12:01 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Mon, 2014-07-28 at 12:49 +0100, Thomas Leonard wrote:
> On 28 July 2014 12:13, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> >> +@ 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.
> >
> > You do corrupt r13 though.
> 
> r13 is banked for all faults except SVC.

Oh yes, I'd a) spent too much time with the hyp exception model (which
differs here) and b) momentarily forgotten that r13 is sp.

>  Possibly for SVC we should do
> something different (though you'll always lose r14 anyway if SVC code
> makes an SVC call for some reason).
> 
> > The way many OSes handle this is to make at least the initial saving
> > (i.e. that which you have at fault:) into a macro and inlining a copy at
> > each entry point. They also arrange for each SP_$mode to always point to
> > something useful (in your case fault_dump, I guess) to avoid using a
> > register as the save target.
> 
> You mean dumping the registers to the SVC stack in the SVC fault
> handler? That might cause another fault if the stack is full, but I
> may be misunderstanding you.

It was what I meant but now that you've reminded me about r13 its a bit
moot.

> > BTW you can infer the same information as you do all this -12 stuff for
> > from the saved CPSR.
> 
> You mean by looking at the processor mode? There are two exceptions
> that both go to Abort mode though.

Once again I've been spending too much time with the hyp exception
model ;-)

>  I haven't checked to see whether
> the information could be recovered some other way; substracting 12
> seemed pretty easy.

OK.

Ian.

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-17 16:28   ` Ian Campbell
@ 2014-07-30 10:47     ` Thomas Leonard
  2014-07-30 11:26       ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-30 10:47 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 17 July 2014 17:28, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> +     @ 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.
>
> ARMv7 (or perhaps it was the virt extensions, either way you can rely on
> it here) makes the MMU cache coherent, so you don't need to flush the
> caches when doing a PTE write any more.

I tried enabling the D-cache here, but then it frequently (but not
always) fails to boot, even with various dsb and isb instructions
scattered around.

If I enable the D-cache immediately before the loop that writes the
translation table entries, it fails. Adding a dsb after the loop
doesn't help. But if I enable it after the loop then it's fine.

I don't know what's going on there - any suggestions? Here's my
(failing) test-case (tested using Xen/stable-4.4 -
4.4.1-rc1-28-gee81dda):

https://github.com/talex5/xen/commit/adadfa7e483aa3f3a351c0aeca6a560614fcdead

>> +       @ 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
>
> I think you want a dsb here to ensure that any previous PTE write you
> did when setting up the PTs have actually occurred.

Presumably this isn't needed in the current code, since the caches are off?

>> +       mcr     p15, 0, r1, c1, c0, 0   @ SCTLR
>> +       isb
>> +
>
>> +     adr     r1, stage2              @ Physical address of stage2
>> +     sub     r1, r1, r9              @ Virtual address of stage2
>
> ldr r1, =stage2
>
> would do this in one, I think.

Yes, OK.

>> +     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)
>> +@    r7 = virtual address of page table
>> +@    r8 = section entry template (flags)
>> +@    r9 = desired physical - virtual offset
>> +@    pc -> somewhere in newly-mapped virtual code section
>> +stage2:
>
> I think you want another dsb around here somewhere to ensure that none
> of the PT updates you do in a moment float up and interfere with the
> mapping of the code between the write to SCTLR until the bx r1.

How does that happen? Presumably the isb below will block that.

>> +     @ 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
>
> dsb here to make sure those writes have actually occurred before you
> come to rely on them.
>
> If there is any chance of any of those writes going through a mapping
> which you are then changing at the same time then I worry that you might
> also need a dsb before each write.

The mapping for the translation table itself doesn't change (its entry
will be written with the same value as previously).

> I'm not 100% sure what would happen
> in this case, I think you'd be better off creating a whole new set of
> PTs rather than pulling the rug out from under yourself. It's either
> that or cold towel on head time ;-)
>
> Ian.



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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-30 10:47     ` Thomas Leonard
@ 2014-07-30 11:26       ` Ian Campbell
  2014-07-30 12:20         ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-30 11:26 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Wed, 2014-07-30 at 11:47 +0100, Thomas Leonard wrote:
> On 17 July 2014 17:28, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
> >> +     @ 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.
> >
> > ARMv7 (or perhaps it was the virt extensions, either way you can rely on
> > it here) makes the MMU cache coherent, so you don't need to flush the
> > caches when doing a PTE write any more.
> 
> I tried enabling the D-cache here, but then it frequently (but not
> always) fails to boot, even with various dsb and isb instructions
> scattered around.
> 
> If I enable the D-cache immediately before the loop that writes the
> translation table entries, it fails. Adding a dsb after the loop
> doesn't help. But if I enable it after the loop then it's fine.
> 
> I don't know what's going on there - any suggestions? Here's my
> (failing) test-case (tested using Xen/stable-4.4 -
> 4.4.1-rc1-28-gee81dda):
> 
> https://github.com/talex5/xen/commit/adadfa7e483aa3f3a351c0aeca6a560614fcdead

My guess would be that it is related to the lack of dsb before the
initial write to SCTLR which turns on M. Try:
        mrc	p15, 0, r1, c1, c0, 0	@ SCTLR
        orr	r1, r1, #0x1 @ Enable MMU
        dsb
        mcr	p15, 0, r1, c1, c0, 0	@ SCTLR
        isb

Otherwise I worry that the dsb() involved when you turn on caching are
causing differences it what you are seeing at this point depending on
where you place it. Xen enables caches at the same time and MMU BTW.

> >> +       @ 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
> >
> > I think you want a dsb here to ensure that any previous PTE write you
> > did when setting up the PTs have actually occurred.
> 
> Presumably this isn't needed in the current code, since the caches are off?

The processor can still reorder writes and things like that, so I think
it is still needed.


> >> +     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)
> >> +@    r7 = virtual address of page table
> >> +@    r8 = section entry template (flags)
> >> +@    r9 = desired physical - virtual offset
> >> +@    pc -> somewhere in newly-mapped virtual code section
> >> +stage2:
> >
> > I think you want another dsb around here somewhere to ensure that none
> > of the PT updates you do in a moment float up and interfere with the
> > mapping of the code between the write to SCTLR until the bx r1.
> 
> How does that happen? Presumably the isb below will block that.

I don't think it will, it's effectively just a pipeline flush but that
doesn't necessarily mean there isn't a write from below already in that
pipeline.

(I think, I haven't actually gone back to the spec on this one...)

In Xen we do dsb+isb before and after the TLB flush.

> >> +     @ 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
> >
> > dsb here to make sure those writes have actually occurred before you
> > come to rely on them.
> >
> > If there is any chance of any of those writes going through a mapping
> > which you are then changing at the same time then I worry that you might
> > also need a dsb before each write.
> 
> The mapping for the translation table itself doesn't change (its entry
> will be written with the same value as previously).

Phew!

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-30 11:26       ` Ian Campbell
@ 2014-07-30 12:20         ` Thomas Leonard
  2014-07-30 12:54           ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-30 12:20 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 30 July 2014 12:26, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-30 at 11:47 +0100, Thomas Leonard wrote:
>> On 17 July 2014 17:28, Ian Campbell <Ian.Campbell@citrix.com> wrote:
>> > On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>> >> +     @ 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.
>> >
>> > ARMv7 (or perhaps it was the virt extensions, either way you can rely on
>> > it here) makes the MMU cache coherent, so you don't need to flush the
>> > caches when doing a PTE write any more.
>>
>> I tried enabling the D-cache here, but then it frequently (but not
>> always) fails to boot, even with various dsb and isb instructions
>> scattered around.
>>
>> If I enable the D-cache immediately before the loop that writes the
>> translation table entries, it fails. Adding a dsb after the loop
>> doesn't help. But if I enable it after the loop then it's fine.
>>
>> I don't know what's going on there - any suggestions? Here's my
>> (failing) test-case (tested using Xen/stable-4.4 -
>> 4.4.1-rc1-28-gee81dda):
>>
>> https://github.com/talex5/xen/commit/adadfa7e483aa3f3a351c0aeca6a560614fcdead
>
> My guess would be that it is related to the lack of dsb before the
> initial write to SCTLR which turns on M. Try:
>         mrc     p15, 0, r1, c1, c0, 0   @ SCTLR
>         orr     r1, r1, #0x1 @ Enable MMU
>         dsb
>         mcr     p15, 0, r1, c1, c0, 0   @ SCTLR
>         isb
>
> Otherwise I worry that the dsb() involved when you turn on caching are
> causing differences it what you are seeing at this point depending on
> where you place it.

Doesn't help.

> Xen enables caches at the same time and MMU BTW.

Also doesn't help (actualy, I only split it out to narrow down the
problem a bit).

>> >> +       @ 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
>> >
>> > I think you want a dsb here to ensure that any previous PTE write you
>> > did when setting up the PTs have actually occurred.
>>
>> Presumably this isn't needed in the current code, since the caches are off?
>
> The processor can still reorder writes and things like that, so I think
> it is still needed.

Ah, I'd assumed it would default everything to Strongly Ordered with
the MMU off, but I see it depends on how Xen sets the "Default
cacheable" bit.

>> >> +     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)
>> >> +@    r7 = virtual address of page table
>> >> +@    r8 = section entry template (flags)
>> >> +@    r9 = desired physical - virtual offset
>> >> +@    pc -> somewhere in newly-mapped virtual code section
>> >> +stage2:
>> >
>> > I think you want another dsb around here somewhere to ensure that none
>> > of the PT updates you do in a moment float up and interfere with the
>> > mapping of the code between the write to SCTLR until the bx r1.
>>
>> How does that happen? Presumably the isb below will block that.
>
> I don't think it will, it's effectively just a pipeline flush but that
> doesn't necessarily mean there isn't a write from below already in that
> pipeline.
>
> (I think, I haven't actually gone back to the spec on this one...)
>
> In Xen we do dsb+isb before and after the TLB flush.

I've added these in various places, but no improvement:

https://github.com/talex5/xen/commit/39199da8493ad6e235849d7ecd51a1415d7d60a7

>> >> +     @ 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
>> >
>> > dsb here to make sure those writes have actually occurred before you
>> > come to rely on them.
>> >
>> > If there is any chance of any of those writes going through a mapping
>> > which you are then changing at the same time then I worry that you might
>> > also need a dsb before each write.
>>
>> The mapping for the translation table itself doesn't change (its entry
>> will be written with the same value as previously).
>
> Phew!
>
>



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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-30 12:20         ` Thomas Leonard
@ 2014-07-30 12:54           ` Ian Campbell
  2014-07-30 13:37             ` Thomas Leonard
  0 siblings, 1 reply; 75+ messages in thread
From: Ian Campbell @ 2014-07-30 12:54 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Wed, 2014-07-30 at 13:20 +0100, Thomas Leonard wrote:

> > The processor can still reorder writes and things like that, so I think
> > it is still needed.
> 
> Ah, I'd assumed it would default everything to Strongly Ordered with
> the MMU off, but I see it depends on how Xen sets the "Default
> cacheable" bit.

Even if memory accesses are strongly ordered that doesn't include co
processor register accesses so they can still be reordered wrt
loads/stores.

> >> How does that happen? Presumably the isb below will block that.
> >
> > I don't think it will, it's effectively just a pipeline flush but that
> > doesn't necessarily mean there isn't a write from below already in that
> > pipeline.
> >
> > (I think, I haven't actually gone back to the spec on this one...)
> >
> > In Xen we do dsb+isb before and after the TLB flush.
> 
> I've added these in various places, but no improvement:
> 
> https://github.com/talex5/xen/commit/39199da8493ad6e235849d7ecd51a1415d7d60a7

Ah, you aren't setting the cacheability of the PT walks, I bet that's
it. If you don't do that then you do need cache maintenance when writing
PTEs (or to have caches disabled).

Xen uses LPAE mode and therefore the extended format of TTBCR (called
HTCR for Xen), which is where the bits controlling the cacheability of
page table walks are held for LPAE.

In non-LPAE mode it looks like the cacheability bits are in TTBR[01] in
bits 0..6.

Ian.

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-30 12:54           ` Ian Campbell
@ 2014-07-30 13:37             ` Thomas Leonard
  2014-07-30 13:43               ` Ian Campbell
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Leonard @ 2014-07-30 13:37 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 30 July 2014 13:54, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Wed, 2014-07-30 at 13:20 +0100, Thomas Leonard wrote:
>
>> > The processor can still reorder writes and things like that, so I think
>> > it is still needed.
>>
>> Ah, I'd assumed it would default everything to Strongly Ordered with
>> the MMU off, but I see it depends on how Xen sets the "Default
>> cacheable" bit.
>
> Even if memory accesses are strongly ordered that doesn't include co
> processor register accesses so they can still be reordered wrt
> loads/stores.
>
>> >> How does that happen? Presumably the isb below will block that.
>> >
>> > I don't think it will, it's effectively just a pipeline flush but that
>> > doesn't necessarily mean there isn't a write from below already in that
>> > pipeline.
>> >
>> > (I think, I haven't actually gone back to the spec on this one...)
>> >
>> > In Xen we do dsb+isb before and after the TLB flush.
>>
>> I've added these in various places, but no improvement:
>>
>> https://github.com/talex5/xen/commit/39199da8493ad6e235849d7ecd51a1415d7d60a7
>
> Ah, you aren't setting the cacheability of the PT walks, I bet that's
> it. If you don't do that then you do need cache maintenance when writing
> PTEs (or to have caches disabled).
>
> Xen uses LPAE mode and therefore the extended format of TTBCR (called
> HTCR for Xen), which is where the bits controlling the cacheability of
> page table walks are held for LPAE.
>
> In non-LPAE mode it looks like the cacheability bits are in TTBR[01] in
> bits 0..6.

You're right - that was it - 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

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

* Re: [PATCH ARM v6 07/14] mini-os: arm: boot code
  2014-07-30 13:37             ` Thomas Leonard
@ 2014-07-30 13:43               ` Ian Campbell
  0 siblings, 0 replies; 75+ messages in thread
From: Ian Campbell @ 2014-07-30 13:43 UTC (permalink / raw)
  To: Thomas Leonard
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On Wed, 2014-07-30 at 14:37 +0100, Thomas Leonard wrote:
> On 30 July 2014 13:54, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Wed, 2014-07-30 at 13:20 +0100, Thomas Leonard wrote:
> >
> >> > The processor can still reorder writes and things like that, so I think
> >> > it is still needed.
> >>
> >> Ah, I'd assumed it would default everything to Strongly Ordered with
> >> the MMU off, but I see it depends on how Xen sets the "Default
> >> cacheable" bit.
> >
> > Even if memory accesses are strongly ordered that doesn't include co
> > processor register accesses so they can still be reordered wrt
> > loads/stores.
> >
> >> >> How does that happen? Presumably the isb below will block that.
> >> >
> >> > I don't think it will, it's effectively just a pipeline flush but that
> >> > doesn't necessarily mean there isn't a write from below already in that
> >> > pipeline.
> >> >
> >> > (I think, I haven't actually gone back to the spec on this one...)
> >> >
> >> > In Xen we do dsb+isb before and after the TLB flush.
> >>
> >> I've added these in various places, but no improvement:
> >>
> >> https://github.com/talex5/xen/commit/39199da8493ad6e235849d7ecd51a1415d7d60a7
> >
> > Ah, you aren't setting the cacheability of the PT walks, I bet that's
> > it. If you don't do that then you do need cache maintenance when writing
> > PTEs (or to have caches disabled).
> >
> > Xen uses LPAE mode and therefore the extended format of TTBCR (called
> > HTCR for Xen), which is where the bits controlling the cacheability of
> > page table walks are held for LPAE.
> >
> > In non-LPAE mode it looks like the cacheability bits are in TTBR[01] in
> > bits 0..6.
> 
> You're right - that was it - thanks!

My pleasure. You had me scratching my head for a while though ;-)

Ian.

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

* Re: [PATCH ARM v6 08/14] mini-os: arm: memory management
  2014-07-21 17:36   ` Julien Grall
@ 2014-08-03 10:23     ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-08-03 10:23 UTC (permalink / raw)
  To: Julien Grall
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

On 21 July 2014 18:36, Julien Grall <julien.grall@linaro.org> wrote:
> Hi Thomas,
>
> On 07/16/2014 12:07 PM, Thomas Leonard wrote:
>> Based on an initial patch by Karim Raslan.
>>
>> Signed-off-by: Karim Allah Ahmed <karim.allah.ahmed@gmail.com>
>> Signed-off-by: Thomas Leonard <talex5@gmail.com>
>>
>> ---
>>
>> Changes since v5:
>>
>> - Require only minimum property lengths (requested by Ian Campbell).
>>
>> Addressed Julien Grall's comments:
>> - Added comments explaining the lengths when checking FDT properties.
>> - Use paddr_t type to represent physical addresses.
>> ---
>>  extras/mini-os/arch/arm/mm.c | 138 +++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 138 insertions(+)
>>  create mode 100644 extras/mini-os/arch/arm/mm.c
>>
>> diff --git a/extras/mini-os/arch/arm/mm.c b/extras/mini-os/arch/arm/mm.c
>> new file mode 100644
>> index 0000000..ec1f821
>> --- /dev/null
>> +++ b/extras/mini-os/arch/arm/mm.c
>> @@ -0,0 +1,138 @@
>> +#include <mini-os/console.h>
>> +#include <xen/memory.h>
>> +#include <arch_mm.h>
>> +#include <mini-os/hypervisor.h>
>> +#include <libfdt.h>
>> +#include <lib.h>
>> +
>> +int physical_address_offset;
>
> int64_t maybe?

Currently we're using the short descriptor format, so we do assume
physical addresses are 32-bit. But it probably does make sense to
treat them as 64-bit and BUG_ON any we can't handle for now, so I will
change this as you suggest.

>> +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)
>> +{
>
> [..]
>
>> +    unsigned int end = (unsigned int) &_end;
>> +    paddr_t mem_base = fdt64_to_cpu(regs[0]);
>> +    unsigned int mem_size = fdt64_to_cpu(regs[1]);
>
> mem_size should be a paddr_t. Even though, the first bank will always
> have the size fit in 32 bits.
>
>> +    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);
>
> You need to use at least an unsigned int here. And it will be better if
> you use paddr_t.
>
>> +    *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);
>
> uint32_t has the definition of the field totalsize in the fdt structure.

OK.

> Regards,
>
> --
> Julien Grall



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

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

* Re: [PATCH ARM v6 00/14] mini-os: initial ARM support
  2014-07-18 12:45 ` Ian Campbell
@ 2014-08-05 10:56   ` Thomas Leonard
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Leonard @ 2014-08-05 10:56 UTC (permalink / raw)
  To: Ian Campbell
  Cc: xen-devel, Stefano Stabellini, David Scott, Samuel Thibault,
	Anil Madhavapeddy

[-- Attachment #1: Type: text/plain, Size: 1956 bytes --]

On 18 July 2014 13:45, Ian Campbell <Ian.Campbell@citrix.com> wrote:
>
> On Wed, 2014-07-16 at 12:07 +0100, Thomas Leonard wrote:
>
> I tried to apply:
> mini-os: x86_64: make thread stacks 16-byte aligned
> mini-os: don't include lib.h from mm.h (the second, attached, version)
> mini-os: added HYPERVISOR_xsm_op
> mini-os: use generic local_irq_enable function
>
> but got:
>         vtpm_cmd_handler.c: In function ‘tm_dhkx_gen’:
>         vtpm_cmd_handler.c:486:3: error: implicit declaration of function ‘ARRAY_SIZE’ [-Werror=implicit-function-declaration]
>         cc1: all warnings being treated as errors
>         make[2]: *** [vtpm_cmd_handler.o] Error 1
>         make[2]: *** Waiting for unfinished jobs....
>         disk_tpm.c: In function ‘TPM_disk_seal’:
>         disk_tpm.c:84:2: error: implicit declaration of function ‘printk’ [-Werror=implicit-function-declaration]
>         cc1: all warnings being treated as errors
>         make[2]: *** [disk_tpm.o] Error 1
>         make[2]: Entering directory `/local/scratch/ianc/devel/committer-amd64.git/stubdom/libxc-x86_64'
>         make libs
>
> Which I think was the mm.h one.

Oops. The attached updated patch fixes compiling the stubdoms for me.

> Then I got:
>         In file included from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/gntmap.h:4:0,
>                          from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/lib.h:55,
>                          from /local/scratch/ianc/devel/committer-amd64.git/stubdom/../extras/mini-os/include/mini-os/mm.h:36,

I guess this is just due to skipping the previous patch, since after
that mm.h will no longer inlcude lib.h.


-- 
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

[-- Attachment #2: 0001-mini-os-don-t-include-lib.h-from-mm.h.patch --]
[-- Type: text/x-patch, Size: 3262 bytes --]

From b102c8ad50db789e850e482770c3809e60167375 Mon Sep 17 00:00:00 2001
From: Thomas Leonard <talex5@gmail.com>
Date: Mon, 7 Jul 2014 13:20:43 +0100
Subject: [PATCH] mini-os: don't include lib.h from mm.h

This breaks the include cycle hypervisor.h -> hypercall-x86_32.h -> mm.h
-> lib.h -> gntmap.h -> os.h -> hypervisor.h.

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>

---

Added missing includes in stubdom code.
---
 extras/mini-os/include/mm.h        | 3 +--
 extras/mini-os/lock.c              | 1 +
 extras/mini-os/main.c              | 1 +
 extras/mini-os/tpm_tis.c           | 1 +
 extras/mini-os/tpmfront.c          | 1 +
 stubdom/vtpmmgr/disk_tpm.c         | 1 +
 stubdom/vtpmmgr/vtpm_cmd_handler.c | 1 +
 7 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index a94cd6d..a177251 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -32,8 +32,7 @@
 #else
 #error "Unsupported architecture"
 #endif
-
-#include <mini-os/lib.h>
+#include <xen/xen.h>
 
 #include <mini-os/arch_limits.h>
 #include <mini-os/arch_mm.h>
diff --git a/extras/mini-os/lock.c b/extras/mini-os/lock.c
index 71a4971..61194e5 100644
--- a/extras/mini-os/lock.c
+++ b/extras/mini-os/lock.c
@@ -9,6 +9,7 @@
 #include <sys/lock.h>
 #include <sched.h>
 #include <wait.h>
+#include <mini-os/lib.h>
 
 int ___lock_init(_LOCK_T *lock)
 {
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
index aec0586..4ec40b5 100644
--- a/extras/mini-os/main.c
+++ b/extras/mini-os/main.c
@@ -15,6 +15,7 @@
 #include <unistd.h>
 #include <xenbus.h>
 #include <events.h>
+#include <mini-os/lib.h>
 
 extern int main(int argc, char *argv[], char *envp[]);
 extern void __libc_init_array(void);
diff --git a/extras/mini-os/tpm_tis.c b/extras/mini-os/tpm_tis.c
index dc4134a..b067cb7 100644
--- a/extras/mini-os/tpm_tis.c
+++ b/extras/mini-os/tpm_tis.c
@@ -26,6 +26,7 @@
 #include <mini-os/events.h>
 #include <mini-os/wait.h>
 #include <mini-os/xmalloc.h>
+#include <mini-os/lib.h>
 #include <errno.h>
 #include <stdbool.h>
 
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index ce5b3e1..6049244 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -31,6 +31,7 @@
 #include <xen/io/xenbus.h>
 #include <xen/io/tpmif.h>
 #include <mini-os/tpmfront.h>
+#include <mini-os/lib.h>
 #include <fcntl.h>
 
 //#define TPMFRONT_PRINT_DEBUG
diff --git a/stubdom/vtpmmgr/disk_tpm.c b/stubdom/vtpmmgr/disk_tpm.c
index a9f4552..d650fbc 100644
--- a/stubdom/vtpmmgr/disk_tpm.c
+++ b/stubdom/vtpmmgr/disk_tpm.c
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <mini-os/byteorder.h>
+#include <mini-os/lib.h>
 #include <polarssl/aes.h>
 #include <polarssl/sha1.h>
 
diff --git a/stubdom/vtpmmgr/vtpm_cmd_handler.c b/stubdom/vtpmmgr/vtpm_cmd_handler.c
index 8a42790..13ead93 100644
--- a/stubdom/vtpmmgr/vtpm_cmd_handler.c
+++ b/stubdom/vtpmmgr/vtpm_cmd_handler.c
@@ -38,6 +38,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <mini-os/console.h>
+#include <mini-os/lib.h>
 #include <polarssl/sha1.h>
 #include <polarssl/sha2.h>
 
-- 
2.0.3


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

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

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

end of thread, other threads:[~2014-08-05 10:56 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-16 11:07 [PATCH ARM v6 00/14] mini-os: initial ARM support Thomas Leonard
2014-07-16 11:07 ` [PATCH ARM v6 01/14] mini-os: x86_64: make thread stacks 16-byte aligned Thomas Leonard
2014-07-17 15:50   ` Ian Campbell
2014-07-17 18:15     ` Samuel Thibault
2014-07-18 10:00       ` Ian Campbell
2014-07-18 13:22         ` Samuel Thibault
2014-07-17 18:15   ` Samuel Thibault
2014-07-16 11:07 ` [PATCH ARM v6 02/14] mini-os: don't include lib.h from mm.h Thomas Leonard
2014-07-16 13:30   ` Thomas Leonard
2014-07-17 15:51     ` Ian Campbell
2014-07-17 18:17     ` Samuel Thibault
2014-07-16 11:07 ` [PATCH ARM v6 03/14] mini-os: added HYPERVISOR_xsm_op Thomas Leonard
2014-07-16 11:07 ` [PATCH ARM v6 04/14] mini-os: headers for ARM Thomas Leonard
2014-07-16 21:25   ` Julien Grall
2014-07-17  8:14     ` Thomas Leonard
2014-07-17  9:04       ` Ian Campbell
2014-07-17 11:41         ` Julien Grall
2014-07-17 15:59   ` Ian Campbell
2014-07-18  1:29     ` Chen Baozi
2014-07-18  7:58     ` Thomas Leonard
2014-07-17 18:27   ` Samuel Thibault
2014-07-18  7:54     ` Thomas Leonard
2014-07-16 11:07 ` [PATCH ARM v6 05/14] mini-os: import libfdt Thomas Leonard
2014-07-16 11:44   ` Andrew Cooper
2014-07-16 12:29     ` Ian Campbell
2014-07-16 13:02       ` Andrew Cooper
2014-07-16 13:34         ` Ian Campbell
2014-07-16 14:13           ` Anil Madhavapeddy
2014-07-16 14:35             ` Ian Campbell
2014-07-17 18:30           ` Samuel Thibault
2014-07-16 11:07 ` [PATCH ARM v6 06/14] mini-os: use generic local_irq_enable function Thomas Leonard
2014-07-17 16:00   ` Ian Campbell
2014-07-17 18:32   ` Samuel Thibault
2014-07-16 11:07 ` [PATCH ARM v6 07/14] mini-os: arm: boot code Thomas Leonard
2014-07-16 21:49   ` Julien Grall
2014-07-17  9:37     ` Thomas Leonard
2014-07-17  9:46       ` Ian Campbell
2014-07-17  9:48         ` Thomas Leonard
2014-07-17 16:28   ` Ian Campbell
2014-07-30 10:47     ` Thomas Leonard
2014-07-30 11:26       ` Ian Campbell
2014-07-30 12:20         ` Thomas Leonard
2014-07-30 12:54           ` Ian Campbell
2014-07-30 13:37             ` Thomas Leonard
2014-07-30 13:43               ` Ian Campbell
2014-07-16 11:07 ` [PATCH ARM v6 08/14] mini-os: arm: memory management Thomas Leonard
2014-07-21 17:36   ` Julien Grall
2014-08-03 10:23     ` Thomas Leonard
2014-07-16 11:07 ` [PATCH ARM v6 09/14] mini-os: arm: scheduling Thomas Leonard
2014-07-28 10:53   ` Ian Campbell
2014-07-28 11:20     ` Thomas Leonard
2014-07-28 11:26       ` Ian Campbell
2014-07-16 11:07 ` [PATCH ARM v6 10/14] mini-os: arm: events Thomas Leonard
2014-07-28 10:55   ` Ian Campbell
2014-07-16 11:07 ` [PATCH ARM v6 11/14] mini-os: arm: time Thomas Leonard
2014-07-21 17:45   ` Julien Grall
2014-07-28 10:41     ` Ian Campbell
2014-07-16 11:07 ` [PATCH ARM v6 12/14] mini-os: arm: interrupt controller Thomas Leonard
2014-07-21 17:56   ` Julien Grall
2014-07-16 11:07 ` [PATCH ARM v6 13/14] mini-os: arm: build system Thomas Leonard
2014-07-16 22:03   ` Julien Grall
2014-07-17 10:16     ` Thomas Leonard
2014-07-28 10:58   ` Ian Campbell
2014-07-16 11:07 ` [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault Thomas Leonard
2014-07-28 11:13   ` Ian Campbell
2014-07-28 11:49     ` Thomas Leonard
2014-07-28 12:01       ` Ian Campbell
2014-07-16 21:29 ` [PATCH ARM v6 00/14] mini-os: initial ARM support Julien Grall
2014-07-17 15:55   ` Ian Campbell
2014-07-17 16:17     ` Ian Campbell
2014-07-18  8:07       ` Thomas Leonard
2014-07-18  8:17     ` Thomas Leonard
2014-07-18 10:07       ` Ian Campbell
2014-07-18 12:45 ` Ian Campbell
2014-08-05 10:56   ` Thomas Leonard

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.