Skip to contentSkip to conversation

mini-os: initial ARM support

PATCH Superseded Thomas Leonard 5 participants 31 messages Aug 8, 2014 – Oct 1, 2014

v7 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v7 cover mini-os: initial ARM support

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

Changes since v6:

- Added missing includes in stubdom code.
- Move poor rand function to test.c.
- Fixed printk format types.
- Only build libfdt with read support, since that's all we need.
- Compiling with debug=n now works.

Addressed Andrew Cooper's comment:
- Use Xen's existing copy of libfdt instead of including our own copy.

Addressed Ian Campbell's comments:
- ARMv7 A8.8.247 says udf should not be used conditionally, so use a branch instead.
- Enable caching earlier (required setting the cacheability for the translation table walks).
- Added some extra dsb instructions to protect against reordering.
- Replace "mov pc" with "bx".
- Preserve all callee-saved registers on thread switch.

Addressed Julien Grall's comments:
- Note that TTBCR is zero (using short-descriptors, TTBR0 only).
- Note about relying on 0x8000 load offset.
- Remove wall-clock time support (doesn't work on ARM anyway).
- Converted an ?: to an if.
- paddr_t is now uint64_t.

Karim Raslan (2):
mini-os: arm: add header files
mini-os: arm: events

Thomas Leonard (11):
mini-os: don't include lib.h from mm.h
mini-os: added HYPERVISOR_xsm_op
mini-os: move poor rand function to test.c
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
mini-os: fixed compiling with debug=n

 .gitignore                                       |   3 +
 extras/mini-os/ARM-TODO.txt                      |   4 +
 extras/mini-os/COPYING                           |  27 +++
 extras/mini-os/Config.mk                         |   2 +
 extras/mini-os/Makefile                          |  38 ++-
 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                    | 237 ++++++++++++++++++
 extras/mini-os/arch/arm/hypercalls32.S           |  64 +++++
 extras/mini-os/arch/arm/minios-arm32.lds         |  83 +++++++
 extras/mini-os/arch/arm/mm.c                     | 139 +++++++++++
 extras/mini-os/arch/arm/panic.c                  |  98 ++++++++
 extras/mini-os/arch/arm/sched.c                  |  47 ++++
 extras/mini-os/arch/arm/setup.c                  | 119 +++++++++
 extras/mini-os/arch/arm/time.c                   | 141 +++++++++++
 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/hypervisor.h              |   2 +
 extras/mini-os/include/lib.h                     |   4 +-
 extras/mini-os/include/libfdt_env.h              |  29 +++
 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/lib/math.c                        |  13 -
 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/minios.mk                         |   2 +-
 extras/mini-os/test.c                            |  13 +
 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 +
 xen/common/libfdt/fdt_ro.c                       |   2 +-
 46 files changed, 1938 insertions(+), 27 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/libfdt_env.h
 create mode 100644 extras/mini-os/lib/memmove.c
Signature · 1 line
2.0.3
#1 lore raw

PATCH v7 1/13 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.

---

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(-)
extras/mini-os/include/mm.h +1 -2
index a94cd6d..a177251 100644
@@ -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>
extras/mini-os/lock.c +1 -0
index 71a4971..61194e5 100644
@@ -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)
 {
extras/mini-os/main.c +1 -0
index aec0586..4ec40b5 100644
@@ -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);
extras/mini-os/tpm_tis.c +1 -0
index 936e854..d40b391 100644
@@ -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>
 
extras/mini-os/tpmfront.c +1 -0
index ce5b3e1..6049244 100644
@@ -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
stubdom/vtpmmgr/disk_tpm.c +1 -0
index a9f4552..d650fbc 100644
@@ -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>
 
stubdom/vtpmmgr/vtpm_cmd_handler.c +1 -0
index 8a42790..13ead93 100644
@@ -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>
 
Signature · 1 line
2.0.3
#2 lore raw

PATCH v7 2/13 mini-os: added HYPERVISOR_xsm_op

In reply to Thomas Leonard

Avoids using _hypercall1 in events.c.

---
 extras/mini-os/events.c         | 4 ++--
 extras/mini-os/include/x86/os.h | 7 +++++++
 2 files changed, 9 insertions(+), 2 deletions(-)
extras/mini-os/events.c +2 -2
index 48742de..2a23042 100644
@@ -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;
 }
 
extras/mini-os/include/x86/os.h +7 -0
index 192b23cd..ee9050b 100644
@@ -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
 
Signature · 1 line
2.0.3
#3 lore raw

PATCH v7 3/13 mini-os: move poor rand function to test.c

In reply to Thomas Leonard

It's only used by test.c and probably isn't something that should be exposed for general use (it just calls gettimeofday).

This is also useful for ARM, which doesn't use math.c, where this used to live.

---
 extras/mini-os/lib/math.c | 13 -------------
 extras/mini-os/test.c     | 13 +++++++++++++
 2 files changed, 13 insertions(+), 13 deletions(-)
extras/mini-os/lib/math.c +0 -13
index c941b4c..561393e 100644
@@ -424,16 +424,3 @@ __moddi3(quad_t a, quad_t b)
 	(void)__qdivrem(ua, ub, &ur);
 	return (neg ? -ur : ur);
 }
-
-#ifndef HAVE_LIBC
-/* Should be random enough for our uses */
-int rand(void)
-{
-    static unsigned int previous;
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    previous += tv.tv_sec + tv.tv_usec;
-    previous *= RAND_MIX;
-    return previous;
-}
-#endif
extras/mini-os/test.c +13 -0
index 64a4057..154af49 100644
@@ -60,6 +60,19 @@ static void xenbus_tester(void *p)
 }
 #endif
 
+#ifndef HAVE_LIBC
+/* Should be random enough for our uses */
+int rand(void)
+{
+    static unsigned int previous;
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    previous += tv.tv_sec + tv.tv_usec;
+    previous *= RAND_MIX;
+    return previous;
+}
+#endif
+
 static void periodic_thread(void *p)
 {
     struct timeval tv;
Signature · 1 line
2.0.3
#4 lore raw

Re: [PATCH ARM v7 03/13] mini-os: move poor rand function to test.c

Quoted 1 line · Thomas Leonard, le Fri 08 Aug 2014 16:47:32 +0100, a écrit :

It's only used by test.c

It's also used by qemu.

Samuel

#5 lore raw

Re: [PATCH ARM v7 03/13] mini-os: move poor rand function to test.c

Quoted 4 lines · Samuel Thibault
Quoted 1 line · Thomas Leonard, le Fri 08 Aug 2014 16:47:32 +0100, a écrit :

It's only used by test.c

It's also used by qemu.

Oh. I thought all the existing stuff using mini-os was using it with a libc. How can I test this?

Signature · 8 lines
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
[email protected]
http://lists.xen.org/xen-devel
#6 lore raw

Re: [PATCH ARM v7 03/13] mini-os: move poor rand function to test.c

Quoted 7 lines · Thomas Leonard, le Mon 11 Aug 2014 08:59:06 +0100, a écrit :
Quoted 4 lines · Samuel Thibault
Quoted 1 line · Thomas Leonard, le Fri 08 Aug 2014 16:47:32 +0100, a écrit :

It's only used by test.c

It's also used by qemu.

Oh. I thought all the existing stuff using mini-os was using it with a libc.

Ah, sorry, I missed the #ifndef HAVE_LIBC, and thought that libc wasn't providing it. Then,

Samuel

#7 lore raw

Re: [PATCH ARM v7 03/13] mini-os: move poor rand function to test.c

Quoted 5 lines · Samuel Thibault
Quoted 4 lines · Thomas Leonard, le Mon 11 Aug 2014 08:59:06 +0100, a écrit :
Quoted 3 lines · Samuel Thibault
Quoted 1 line · Thomas Leonard, le Fri 08 Aug 2014 16:47:32 +0100, a écrit :

It's only used by test.c

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

It's also used by qemu.

Oh. I thought all the existing stuff using mini-os was using it with a libc.

Ah, sorry, I missed the #ifndef HAVE_LIBC, and thought that libc wasn't providing it. Then,

Thanks. Any other comments on this patch series?

Signature · 8 lines
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
[email protected]
http://lists.xen.org/xen-devel
#8 lore raw

PATCH v7 4/13 mini-os: arm: add header files

In reply to Thomas Leonard

From: Karim Raslan <[email protected]>

Adds header files for future ARM support.
Based on work by Karim Allah Ahmed.

---
Changes since v6:

- paddr_t is now uint64_t (even though we only use 32-bits)
- physical_address_offset is now uint32_t (wraps at 4 GB)

---
 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
extras/mini-os/include/arm/arch_endian.h new file +7 -0
new file mode 100644
index 0000000..0771683
@@ -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
extras/mini-os/include/arm/arch_limits.h new file +9 -0
new file mode 100644
index 0000000..bae99e1
@@ -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
extras/mini-os/include/arm/arch_mm.h new file +38 -0
new file mode 100644
index 0000000..085d4e5
@@ -0,0 +1,38 @@
+#ifndef _ARCH_MM_H_
+#define _ARCH_MM_H_
+
+typedef uint64_t paddr_t;
+
+extern char _text, _etext, _erodata, _edata, _end, __bss_start;
+extern int _boot_stack[];
+extern int _boot_stack_end[];
+extern uint32_t physical_address_offset;	/* Add this to a virtual address to get the physical address (wraps at 4GB) */
+
+#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) & 0xffffffff)
+#define to_virt(x)                 ((void *)(((x)-physical_address_offset) & 0xffffffff))
+
+#define PFN_UP(x)    (unsigned long)(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
+#define PFN_DOWN(x)    (unsigned long)((x) >> L1_PAGETABLE_SHIFT)
+#define PFN_PHYS(x)    ((uint64_t)(x) << L1_PAGETABLE_SHIFT)
+#define PHYS_PFN(x)    (unsigned long)((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
extras/mini-os/include/arm/arch_sched.h new file +19 -0
new file mode 100644
index 0000000..de3ac02
@@ -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__ */
extras/mini-os/include/arm/arch_spinlock.h new file +36 -0
new file mode 100755
index 0000000..dccb9fc
@@ -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
extras/mini-os/include/arm/arm32/arch_wordsize.h new file +1 -0
new file mode 100644
index 0000000..b47eee9
@@ -0,0 +1 @@
+#define __WORDSIZE 32
extras/mini-os/include/arm/gic.h new file +1 -0
new file mode 100644
index 0000000..cead2e5
@@ -0,0 +1 @@
+void gic_init(void);
extras/mini-os/include/arm/hypercall-arm.h new file +98 -0

98 lines not on this page · raw message

extras/mini-os/include/arm/os.h new file +216 -0

216 lines not on this page · raw message

extras/mini-os/include/arm/traps.h new file +20 -0
new file mode 100644
index 0000000..704df22
@@ -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
extras/mini-os/include/hypervisor.h +2 -0
index a62cb78..21b3566 100644
@@ -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
extras/mini-os/include/mm.h +2 -0
index a177251..f57d8ab 100644
@@ -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
extras/mini-os/include/types.h +5 -5
index 93356fe..be9f1d3 100644
@@ -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
Signature · 1 line
2.0.3
#9 lore raw

PATCH v7 5/13 mini-os: arm: boot code

In reply to Thomas Leonard

Based on an initial patch by Karim Raslan.

---

Changes since v6:

- Fixed printk format types.

Addressed Ian Campbell's comments:
- ARMv7 A8.8.247 says udf should not be used conditionally, so use a branch instead.
- Enable caching earlier (required setting the cacheability for the translation table walks).
- Added some extra dsb instructions to protect against reordering.

Addressed Julien Grall's comments:
- Note that TTBCR is zero (using short-descriptors, TTBR0 only).
- Note about relying on 0x8000 load offset.

---
 extras/mini-os/arch/arm/arm32.S          | 211 +++++++++++++++++++++++++++++++
 extras/mini-os/arch/arm/hypercalls32.S   |  64 ++++++++++
 extras/mini-os/arch/arm/minios-arm32.lds |  83 ++++++++++++
 extras/mini-os/arch/arm/setup.c          | 119 +++++++++++++++++
 4 files changed, 477 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
extras/mini-os/arch/arm/arm32.S new file +211 -0
new file mode 100644
index 0000000..d2e6932
@@ -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.
+	@ Note: We leave TTBCR as 0, meaning that only TTBR0 is used and
+	@ we use the short-descriptor format (32-bit physical addresses).
+	orr	r0, r1, #0b0001011	@ Sharable, Inner/Outer Write-Back Write-Allocate Cacheable
+	mcr	p15, 0, r0, c2, c0, 0	@ set TTBR0
+
+	@ 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
+	dsb				@ Caching is off, but must still prevent reordering
+	mcr	p15, 0, r1, c8, c7, 0	@ TLBIALL
+
+	@ Enable MMU / SCTLR
+	mrc	p15, 0, r1, c1, c0, 0	@ SCTLR
+	orr	r1, r1, #3 << 11	@ enable icache, branch prediction
+	orr	r1, r1, #4 + 1		@ enable dcache, MMU
+	mcr	p15, 0, r1, c1, c0, 0	@ SCTLR
+	isb
+
+	ldr	r1, =stage2		@ 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
+	dsb
+	mcr	p15, 0, r1, c8, c7, 0	@ TLBIALL
+	isb
+
+	@ 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
+
+@ Call fault_undefined_instruction in "Undefined mode"
+bug:
+	.word	0xe7f000f0    	@ und/udf - a "Permanently Undefined" instruction
+
+irq_handler:
+	ldr	sp, =irqstack_end
+	push	{r0 - r12, r14}
+
+	ldr	r0, IRQ_handler
+	cmp	r0, #0
+	beq	bug
+	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
extras/mini-os/arch/arm/hypercalls32.S new file +64 -0

64 lines not on this page · raw message

extras/mini-os/arch/arm/minios-arm32.lds new file +83 -0

83 lines not on this page · raw message

extras/mini-os/arch/arm/setup.c new file +119 -0

119 lines not on this page · raw message

Signature · 7 lines
2.0.3


_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel
#10 lore raw

PATCH v7 6/13 mini-os: arm: memory management

In reply to Thomas Leonard

Based on an initial patch by Karim Raslan.

---

Changes since v6:

- fixed printk format types
- physical_address_offset is now uint32_t

---
 extras/mini-os/arch/arm/mm.c | 139 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/mm.c
extras/mini-os/arch/arm/mm.c new file +139 -0
new file mode 100644
index 0000000..efecc51
@@ -0,0 +1,139 @@
+#include <mini-os/console.h>
+#include <xen/memory.h>
+#include <arch_mm.h>
+#include <mini-os/hypervisor.h>
+#include <libfdt.h>
+#include <lib.h>
+
+uint32_t 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]);
+    uint64_t mem_size = fdt64_to_cpu(regs[1]);
+    printk("Found memory at 0x%llx (len 0x%llx)\n",
+            (unsigned long long) mem_base, (unsigned long long) 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));
+    uint64_t heap_len = mem_size - (PFN_PHYS(*start_pfn_p) - mem_base);
+    *max_pfn_p = *start_pfn_p + PFN_DOWN(heap_len);
+
+    printk("Using pages %lu to %lu 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.
+     */
+    uint32_t 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 %llx\n", (unsigned long long) 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);
+}
Signature · 1 line
2.0.3
#11 lore raw

PATCH v7 7/13 mini-os: arm: scheduling

In reply to Thomas Leonard

Based on an initial patch by Karim Raslan.

---
Changes since v6:

- fixed printk format types

Addressed Ian Campbell's points:
- replace "mov pc" with "bx"
- preserve all callee-saved registers on context switch

---
 extras/mini-os/arch/arm/arm32.S | 22 +++++++++++++++++++
 extras/mini-os/arch/arm/sched.c | 47 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/sched.c
extras/mini-os/arch/arm/arm32.S +22 -0
index d2e6932..73223c8 100644
@@ -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:
+	push	{r4-r11}	@ Store callee-saved registers to old thread's stack
+	stmia	r0, {sp, lr}	@ Store current sp and ip to prev's struct thread
+
+	ldmia	r1, {sp, lr}	@ Load new sp, ip from next's struct thread
+	pop	{r4-r11}	@ Load callee-saved registers from new thread's stack
+
+	bx	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
extras/mini-os/arch/arm/sched.c new file +47 -0

47 lines not on this page · raw message

Signature · 1 line
2.0.3
#12 lore raw

PATCH v7 8/13 mini-os: arm: events

In reply to Thomas Leonard

From: Karim Raslan <[email protected]>

---
 extras/mini-os/arch/arm/events.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/events.c
extras/mini-os/arch/arm/events.c new file +31 -0
new file mode 100644
index 0000000..441010d
@@ -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)
+{
+}
Signature · 1 line
2.0.3
#14 lore raw

PATCH v7 9/13 mini-os: arm: time

In reply to Thomas Leonard

Based on an initial patch by Karim Raslan.

---

Addressed Julien Grall's comments:
- Remove wall-clock time support (doesn't work on ARM anyway)

---
 extras/mini-os/arch/arm/time.c | 141 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/time.c
extras/mini-os/arch/arm/time.c new file +141 -0
new file mode 100644
index 0000000..98e931f
@@ -0,0 +1,141 @@
+#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));
+}
+
+/* Wall-clock time is not currently available on ARM, so this is always zero for now:
+ * http://wiki.xenproject.org/wiki/Xen_ARM_TODO#Expose_Wallclock_time_to_guests
+ */
+static struct timespec shadow_ts;
+
+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;
+}
+
+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 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);
+}
+
+void fini_time(void)
+{
+}
Signature · 1 line
2.0.3
#15 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

Quoted 1 line

+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

Is the isb really necessary here?

extras/mini-os/arch/arm/time.c line 73

Quoted 11 lines
extras/mini-os/arch/arm/time.c new file +11 -0
+    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));

There's quite a few of these //printk(debug) statements in this patch...

Quoted 14 lines
extras/mini-os/arch/arm/time.c new file +14 -0
+    return time;
+}
+
+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;
+}

extras/mini-os/arch/arm/time.c line 97

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -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));

I think you can use

	"mcrr p15, 3, %0, %H0, c14" :: "r" (value)

here.

extras/mini-os/arch/arm/time.c line 101

Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+
+    __asm__ __volatile__("mov %0, #0x1\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+            "isb":"=r"(x));

x = 1 before this would avoid the mov inside the inline stuff as well as the strange looking use of an output register for a write.

extras/mini-os/arch/arm/time.c line 109

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +8 -0
+}
+
+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));

and again. You probably just want a write_timer_ctl(uiint.. val) type function.

extras/mini-os/arch/arm/time.c line 121

Quoted 12 lines
extras/mini-os/arch/arm/time.c new file +12 -0
+}
+
+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);

More left over debug.

extras/mini-os/arch/arm/time.c line 128

Quoted 7 lines
extras/mini-os/arch/arm/time.c new file +7 -0
+        unset_vtimer_compare();
+
+        /* Give the IRQ handler a chance to handle whatever woke us up. */
+        local_irq_enable();
+        local_irq_disable();
+    }
+}

Ian.

#16 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

Hi Ian,

I'm on holiday for a few weeks now. Please feel free to apply any minor changes if you don't want to wait. In any case, I'll take another look at the end of Sep.

Regards,

Quoted 3 lines
Quoted 1 line

+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

Is the isb really necessary here?

I don't think so.

Quoted 89 lines

extras/mini-os/arch/arm/time.c line 73

Quoted 11 lines
extras/mini-os/arch/arm/time.c new file +11 -0
+    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));

There's quite a few of these //printk(debug) statements in this patch...

Quoted 14 lines
extras/mini-os/arch/arm/time.c new file +14 -0
+    return time;
+}
+
+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;
+}

extras/mini-os/arch/arm/time.c line 97

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -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));

I think you can use

        "mcrr p15, 3, %0, %H0, c14" :: "r" (value)

here.

extras/mini-os/arch/arm/time.c line 101

Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+
+    __asm__ __volatile__("mov %0, #0x1\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+            "isb":"=r"(x));

x = 1 before this would avoid the mov inside the inline stuff as well as the strange looking use of an output register for a write.

extras/mini-os/arch/arm/time.c line 109

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +8 -0
+}
+
+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));

and again. You probably just want a write_timer_ctl(uiint.. val) type function.

extras/mini-os/arch/arm/time.c line 121

Quoted 12 lines
extras/mini-os/arch/arm/time.c new file +12 -0
+}
+
+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);

More left over debug.

extras/mini-os/arch/arm/time.c line 128

Quoted 7 lines
extras/mini-os/arch/arm/time.c new file +7 -0
+        unset_vtimer_compare();
+
+        /* Give the IRQ handler a chance to handle whatever woke us up. */
+        local_irq_enable();
+        local_irq_disable();
+    }
+}

Ian.

Signature · 3 lines
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
#17 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

Hi,

Quoted 12 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

Hi Ian,

I'm on holiday for a few weeks now. Please feel free to apply any minor changes if you don't want to wait. In any case, I'll take another look at the end of Sep.

Quoted 86 lines

Regards,

Quoted 3 lines
Quoted 1 line

+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

Is the isb really necessary here?

I don't think so.

Quoted 78 lines

extras/mini-os/arch/arm/time.c line 73

Quoted 11 lines
extras/mini-os/arch/arm/time.c new file +11 -0
+    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));

There's quite a few of these //printk(debug) statements in this patch...

Quoted 14 lines
extras/mini-os/arch/arm/time.c new file +14 -0
+    return time;
+}
+
+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;
+}

extras/mini-os/arch/arm/time.c line 97

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -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));

I think you can use

       "mcrr p15, 3, %0, %H0, c14" :: "r" (value)

here.

extras/mini-os/arch/arm/time.c line 101

Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+
+    __asm__ __volatile__("mov %0, #0x1\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+            "isb":"=r"(x));

x = 1 before this would avoid the mov inside the inline stuff as well as the strange looking use of an output register for a write.

extras/mini-os/arch/arm/time.c line 109

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +8 -0
+}
+
+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));

and again. You probably just want a write_timer_ctl(uiint.. val) type function.

extras/mini-os/arch/arm/time.c line 121

Quoted 12 lines
extras/mini-os/arch/arm/time.c new file +12 -0
+}
+
+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);

More left over debug.

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console). As far as I can tell the monotonic clock is giving me sensible values, and the ‘until’ value looked sensible. For now I can work around the problem by attaching a vif to a busy network :-)

Sorry for the vagueness of the bug report. I’ll try to make a more minimal repro example when I get the time.

Dave

Quoted 18 lines
Quoted 11 lines

extras/mini-os/arch/arm/time.c line 128

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +7 -0
+        unset_vtimer_compare();
+
+        /* Give the IRQ handler a chance to handle whatever woke us up. */
+        local_irq_enable();
+        local_irq_disable();
+    }
+}

Ian.

Signature · 3 lines
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
#18 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

Quoted 103 lines · Dave Scott

Hi,

Quoted 12 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

Hi Ian,

I'm on holiday for a few weeks now. Please feel free to apply any minor changes if you don't want to wait. In any case, I'll take another look at the end of Sep.

Quoted 86 lines

Regards,

Quoted 3 lines
Quoted 1 line

+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

Is the isb really necessary here?

I don't think so.

Quoted 78 lines

extras/mini-os/arch/arm/time.c line 73

Quoted 11 lines
extras/mini-os/arch/arm/time.c new file +11 -0
+    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));

There's quite a few of these //printk(debug) statements in this patch...

Quoted 14 lines
extras/mini-os/arch/arm/time.c new file +14 -0
+    return time;
+}
+
+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;
+}

extras/mini-os/arch/arm/time.c line 97

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -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));

I think you can use

       "mcrr p15, 3, %0, %H0, c14" :: "r" (value)

here.

extras/mini-os/arch/arm/time.c line 101

Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+
+    __asm__ __volatile__("mov %0, #0x1\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+            "isb":"=r"(x));

x = 1 before this would avoid the mov inside the inline stuff as well as the strange looking use of an output register for a write.

extras/mini-os/arch/arm/time.c line 109

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +8 -0
+}
+
+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));

and again. You probably just want a write_timer_ctl(uiint.. val) type function.

extras/mini-os/arch/arm/time.c line 121

Quoted 12 lines
extras/mini-os/arch/arm/time.c new file +12 -0
+}
+
+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);

More left over debug.

Quoted 3 lines

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console). As far as I can tell the monotonic clock is giving me sensible values, and the ‘until’ value looked sensible. For now I can work around the problem by attaching a vif to a busy network :-)

Sorry for the vagueness of the bug report. I’ll try to make a more minimal repro example when I get the time.

This reminds me of many fun memories about late debugging sessions.

What Xen version are you using?

WFI means wait-for-interrupt and it is trapped into Xen, see:

xen/arch/arm/traps.c:do_trap_hypervisor, label HSR_EC_WFI_WFE.

When the guest issues a WFI instruction, Xen blocks the vcpu on its behalf. Any interrupt for the vcpu in question should wake it up, see the vcpu_unblock call at the end of xen/arch/arm/vgic.c:vgic_vcpu_inject_irq. vgic_vcpu_inject_irq is called by the timer code, both vtimer.c (emulated time) and time.c (virtual timer).

If something goes wrong with the wake-up, the vcpu could remain blocked.

Have fun! ;-)

Quoted 22 lines

Dave

Quoted 18 lines
Quoted 11 lines

extras/mini-os/arch/arm/time.c line 128

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +7 -0
+        unset_vtimer_compare();
+
+        /* Give the IRQ handler a chance to handle whatever woke us up. */
+        local_irq_enable();
+        local_irq_disable();
+    }
+}

Ian.

Signature · 3 lines
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
[email protected]
http://lists.xen.org/xen-devel

#19 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

In reply to Dave Scott
Quoted 103 lines · Dave Scott

Hi,

Quoted 12 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

Hi Ian,

I'm on holiday for a few weeks now. Please feel free to apply any minor changes if you don't want to wait. In any case, I'll take another look at the end of Sep.

Quoted 86 lines

Regards,

Quoted 3 lines
Quoted 1 line

+ __asm__ __volatile__("isb;mrrc p15, 1, %0, %1, c14":"=r"(c_lo), "=r"(c_hi));

Is the isb really necessary here?

I don't think so.

Quoted 78 lines

extras/mini-os/arch/arm/time.c line 73

Quoted 11 lines
extras/mini-os/arch/arm/time.c new file +11 -0
+    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));

There's quite a few of these //printk(debug) statements in this patch...

Quoted 14 lines
extras/mini-os/arch/arm/time.c new file +14 -0
+    return time;
+}
+
+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;
+}

extras/mini-os/arch/arm/time.c line 97

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -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));

I think you can use

       "mcrr p15, 3, %0, %H0, c14" :: "r" (value)

here.

extras/mini-os/arch/arm/time.c line 101

Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+
+    __asm__ __volatile__("mov %0, #0x1\n"
+            "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the output signal */
+            "isb":"=r"(x));

x = 1 before this would avoid the mov inside the inline stuff as well as the strange looking use of an output register for a write.

extras/mini-os/arch/arm/time.c line 109

Quoted 8 lines
extras/mini-os/arch/arm/time.c new file +8 -0
+}
+
+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));

and again. You probably just want a write_timer_ctl(uiint.. val) type function.

extras/mini-os/arch/arm/time.c line 121

Quoted 12 lines
extras/mini-os/arch/arm/time.c new file +12 -0
+}
+
+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);

More left over debug.

Quoted 5 lines

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console). As far as I can tell the monotonic clock is giving me sensible values, and the ‘until’ value looked sensible. For now I can work around the problem by attaching a vif to a busy network :-)

Sorry for the vagueness of the bug report. I’ll try to make a more minimal repro example when I get the time.

Dave

After discussing this with Dave, it looks like this was a problem in a previous version of my patches*, which didn't enable the timer interrupt. This series (v7) does enable the timer and should work correctly.

* https://github.com/talex5/xen/releases/tag/minios-v0.3

Signature · 8 lines
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
[email protected]
http://lists.xen.org/xen-devel
#20 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

In reply to Dave Scott
Quoted 9 lines · Dave Scott

Hi,

Quoted 5 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

[...]

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines

extras/mini-os/arch/arm/time.c line 121

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -0
+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);

More left over debug.

[...]

Quoted 1 line

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console).

[...]

Given that at least one person has already made use of these debug lines, perhaps I should leave them in?

Signature · 8 lines
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
[email protected]
http://lists.xen.org/xen-devel
#21 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

Quoted 23 lines · Thomas Leonard
Quoted 9 lines · Dave Scott

Hi,

Quoted 5 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

[...]

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
extras/mini-os/arch/arm/time.c new file +4 -0
+void block_domain(s_time_t until)
+{
+    uint64_t until_count = ns_to_ticks(until) + cntvct_at_init;
+    ASSERT(irqs_disabled());
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

extras/mini-os/arch/arm/time.c line 121

Quoted 6 lines
extras/mini-os/arch/arm/time.c new file +6 -0
+    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);

More left over debug.

Quoted 7 lines

[...]

Quoted 1 line

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console).

[...]

Given that at least one person has already made use of these debug lines, perhaps I should leave them in?

If they are to stay they need to be done with a proper ifdef controlled debug option (perhaps a DPRINT macro, not inline #ifdefs), commented out as you have it isn't ok.

Ian.

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel

#22 lore raw

Re: [PATCH ARM v7 09/13] mini-os: arm: time

In reply to Dave Scott
Quoted 9 lines · Dave Scott

Hi,

Quoted 5 lines · Thomas Leonard
Quoted 4 lines · Ian Campbell

On Fri, 2014-08-08 at 16:47 +0100, Thomas Leonard wrote:

Sorry for how long I took to get to this, travel and the resulting backlog conspired against me.

[...]

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines

extras/mini-os/arch/arm/time.c line 121

Quoted 10 lines
extras/mini-os/arch/arm/time.c new file +10 -0
+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);

More left over debug.

[...]

Quoted 1 line

I had a play with this yesterday on my cubieboard with Mirage. Using network and vchan connections worked fine, so event channels are working ok. However when I had no external event channel input and my domain blocked on a timer, it seemed to block forever in the ‘wfi’ (as I could see by enabling these debug lines and then pressing ‘enter’ to trigger an interrupt on the console).

[...]

Given that at least one person has already made use of these debug lines, perhaps I should leave them in?

Signature · 8 lines
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
[email protected]
http://lists.xen.org/xen-devel
#23 lore raw

PATCH v7 10/13 mini-os: arm: interrupt controller

In reply to Thomas Leonard

Based on an initial patch by Karim Raslan.

---

Changes since v6:

Addressed Julien Grall's comments:
- converted ?: to if

---
 extras/mini-os/arch/arm/gic.c | 237 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 237 insertions(+)
 create mode 100644 extras/mini-os/arch/arm/gic.c
extras/mini-os/arch/arm/gic.c new file +237 -0
new file mode 100644
index 0000000..6283ed5
@@ -0,0 +1,237 @@
+// 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);
+    if (level_sensitive) {
+        clear_bit_non_atomic((irq_number * 2) + 1, cfg_reg);
+    } else {
+        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:
+        /* We need to get this event to wake us up from block_domain,
+         * but we don't need to do anything special with it. */
+        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 */);
+}
Signature · 1 line
2.0.3
#24 lore raw

Re: [PATCH ARM v7 10/13] mini-os: arm: interrupt controller

extras/mini-os/arch/arm/gic.c line 224

Quoted 5 lines · Thomas Leonard
extras/mini-os/arch/arm/gic.c new file +4 -0
+    /* 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.
+     */

You probably ought to not rely on that long term but it'll do for now.

I've not dug into this too deeply but I'm ok with it going in as is.

Ian.

#25 lore raw

PATCH v7 11/13 mini-os: arm: build system

In reply to Thomas Leonard

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

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

The change to fdt_ro.c is to avoid a compiler warning.

---

Changes since v6:

- Use Xen's existing copy of libfdt instead of including our own copy.
- Only build libfdt with read support, since that's all we need.

---
 .gitignore                          |  3 +++
 extras/mini-os/ARM-TODO.txt         |  5 +++++
 extras/mini-os/COPYING              | 27 ++++++++++++++++++++++
 extras/mini-os/Config.mk            |  2 ++
 extras/mini-os/Makefile             | 38 +++++++++++++++++++++++++++++--
 extras/mini-os/arch/arm/Makefile    | 32 ++++++++++++++++++++++++++
 extras/mini-os/arch/arm/arch.mk     |  7 ++++++
 extras/mini-os/include/lib.h        |  4 +++-
 extras/mini-os/include/libfdt_env.h | 29 ++++++++++++++++++++++++
 extras/mini-os/lib/memmove.c        | 45 +++++++++++++++++++++++++++++++++++++
 extras/mini-os/lib/string.c         | 12 ++++++++++
 11 files changed, 201 insertions(+), 3 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/include/libfdt_env.h
 create mode 100644 extras/mini-os/lib/memmove.c
.gitignore +3 -0
index f1d1b9c..a67d2d9 100644
@@ -50,6 +50,9 @@ extras/mini-os/include/mini-os
 extras/mini-os/include/x86/mini-os
 extras/mini-os/include/xen
 extras/mini-os/include/list.h
+extras/mini-os/include/fdt.h
+extras/mini-os/include/libfdt.h
+extras/mini-os/libfdt
 extras/mini-os/mini-os*
 install/*
 linux-[^/]*-paravirt/*
extras/mini-os/ARM-TODO.txt new file +5 -0
new file mode 100644
index 0000000..3226d39
@@ -0,0 +1,5 @@
+* 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
extras/mini-os/COPYING +27 -0
index 1d9df6c..b676bb6 100644
@@ -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.
extras/mini-os/Config.mk +2 -0
index d61877b..4ecde54 100644
@@ -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
extras/mini-os/Makefile +36 -2
index 6d6537e..77dc9aa 100644
@@ -51,7 +51,7 @@ flags-$(CONFIG_XENBUS) += -DCONFIG_XENBUS
 DEF_CFLAGS += $(flags-y)
 
 # Symlinks and headers that must be created before building the C files
-GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/xen include/$(TARGET_ARCH_FAM)/mini-os
+GENERATED_HEADERS := include/list.h $(ARCH_LINKS) include/mini-os include/xen include/$(TARGET_ARCH_FAM)/mini-os include/fdt.h include/libfdt.h
 
 EXTRA_DEPS += $(GENERATED_HEADERS)
 
@@ -75,7 +75,18 @@ EXTRA_OBJS =
 TARGET := mini-os
 
 # Subdirectories common to mini-os
-SUBDIRS := lib xenbus console
+SUBDIRS := lib xenbus console libfdt
+
+FDT_SRC :=
+ifeq ($(XEN_TARGET_ARCH),arm32)
+# Need libgcc.a for division helpers
+LDLIBS += `$(CC) -print-libgcc-file-name`
+
+# Device tree support
+FDT_SRC := libfdt/fdt.c libfdt/fdt_ro.c libfdt/fdt_strerror.c
+
+src-y += ${FDT_SRC}
+endif
 
 src-$(CONFIG_BLKFRONT) += blkfront.c
 src-$(CONFIG_TPMFRONT) += tpmfront.c
@@ -97,10 +108,13 @@ 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
+src-y += lib/memmove.c
 src-y += lib/sys.c
 src-y += lib/xmalloc.c
 src-$(CONFIG_XENBUS) += lib/xs.c
@@ -125,6 +139,21 @@ $(ARCH_LINKS):
 	$(arch_links)
 endif
 
+include/fdt.h:
+	cp $(XEN_ROOT)/xen/include/xen/libfdt/fdt.h $@
+
+include/libfdt.h:
+	sed 's!xen/libfdt/!!' $(XEN_ROOT)/xen/include/xen/libfdt/libfdt.h > $@
+
+libfdt:
+	mkdir $@
+
+libfdt/libfdt_internal.h: libfdt
+	cp $(XEN_ROOT)/xen/common/libfdt/libfdt_internal.h $@
+
+libfdt/%.c: libfdt libfdt/libfdt_internal.h
+	cp $(XEN_ROOT)/xen/common/libfdt/$*.c $@
+
 include/list.h: $(XEN_ROOT)/tools/include/xen-external/bsd-sys-queue-h-seddery $(XEN_ROOT)/tools/include/xen-external/bsd-sys-queue.h
 	perl $^ --prefix=minios  >[email protected]
 	$(call move-if-changed,[email protected],$@)
@@ -190,7 +219,11 @@ $(OBJ_DIR)/$(TARGET): $(OBJS) $(APP_O) arch_lib
 	$(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(APP_O) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o [email protected]
 	$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start [email protected] [email protected]
 	$(LD) $(LDFLAGS) $(LDFLAGS_FINAL) [email protected] $(EXTRA_OBJS) -o $@
+ifeq ($(XEN_TARGET_ARCH),arm32)
+	$(OBJCOPY) -O binary $@ [email protected]
+else
 	gzip -f -9 -c $@ >[email protected]
+endif
 
 .PHONY: clean arch_clean
 
@@ -202,6 +235,7 @@ clean:	arch_clean
 		rm -f $$dir/*.o; \
 	done
 	rm -f include/list.h
+	rm -f ${FDT_SRC} libfdt/libfdt_internal.h
 	rm -f $(OBJ_DIR)/*.o *~ $(OBJ_DIR)/core $(OBJ_DIR)/$(TARGET).elf $(OBJ_DIR)/$(TARGET).raw $(OBJ_DIR)/$(TARGET) $(OBJ_DIR)/$(TARGET).gz
 	find . $(OBJ_DIR) -type l | xargs rm -f
 	$(RM) $(OBJ_DIR)/lwip.a $(LWO)
extras/mini-os/arch/arm/Makefile new file +32 -0
new file mode 100755
index 0000000..8b78651
@@ -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)
+
extras/mini-os/arch/arm/arch.mk new file +7 -0
new file mode 100644
index 0000000..ad6e05f
@@ -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
+
extras/mini-os/include/lib.h +3 -1
index 62836c7..326e39f 100644
@@ -95,6 +95,7 @@ char	*strncpy(char * __restrict, const char * __restrict, size_t);
 
 char	*strstr(const char *, const char *);
 
+void *memmove(void *, const void *, size_t);
 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
extras/mini-os/include/libfdt_env.h new file +29 -0
new file mode 100644
index 0000000..9c5076e
@@ -0,0 +1,29 @@
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <lib.h>
+
+#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 */
extras/mini-os/lib/memmove.c new file +45 -0

45 lines not on this page · raw message

extras/mini-os/lib/string.c +12 -0
index 8b24146..c96ca41 100644
@@ -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
Signature · 1 line
2.0.3
#26 lore raw

Re: [PATCH ARM v7 11/13] mini-os: arm: build system

Quoted 5 lines · Thomas Leonard

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:

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

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

This is ~= 3-clause BSD which over the existing license has:

extras/mini-os/COPYING LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY · line 48

Quoted 3 lines
extras/mini-os/COPYING +3 -0
+    * 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.

I suppose this is somewhat tolerable but it might be nicer to avoid if we can. Does anyone know of (or fancy knocking up) a clean room memmove() under the 2-clause license used by the rest of minios?

Quoted 1 line

The change to fdt_ro.c is to avoid a compiler warning.

I was about to ask for it to be quoted, but I see that you don't actually touch fdt_ro.c, so maybe this comment is just stale?

Ian.

#27 lore raw

PATCH v7 12/13 mini-os: arm: show registers, stack and exception vector on fault

In reply to Thomas Leonard

---

- Exit with SHUTDOWN_crash on BUG or fault (suggested by Ian Campbell).
- Fixed printk format types.

---
 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
extras/mini-os/ARM-TODO.txt +0 -1
index 3226d39..1e40db1 100644
@@ -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 (?)
extras/mini-os/arch/arm/arm32.S +68 -7

89 lines not on this page · raw message

extras/mini-os/arch/arm/panic.c new file +98 -0

98 lines not on this page · raw message

Signature · 7 lines
2.0.3


_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel
#29 lore raw

PATCH v7 13/13 mini-os: fixed compiling with debug=n

In reply to Thomas Leonard

Without -fno-tree-loop-distribute-patterns, gcc -O3 recognises that our "memset" is doing a memset operation and tries to make it call the standard "memset", creating a loop.

The change to fdt_ro.c is to avoid a compiler warning.

---
 extras/mini-os/minios.mk   | 2 +-
 xen/common/libfdt/fdt_ro.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
extras/mini-os/minios.mk +1 -1
index 20ba64b..3e881e4 100644
@@ -23,7 +23,7 @@ DEF_CFLAGS += -g
 #DEF_CFLAGS += -DGNT_DEBUG
 #DEF_CFLAGS += -DGNTMAP_DEBUG
 else
-DEF_CFLAGS += -O3
+DEF_CFLAGS += -O3 -fno-tree-loop-distribute-patterns
 endif
 
 # Make the headers define our internal stuff
xen/common/libfdt/fdt_ro.c +1 -1
index 02b6d68..a34c6d6 100644
@@ -444,7 +444,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
 
 int fdt_node_depth(const void *fdt, int nodeoffset)
 {
-	int nodedepth;
+	int nodedepth = -1;
 	int err;
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
Signature · 1 line
2.0.3
#30 lore raw

Re: [PATCH ARM v7 13/13] mini-os: fixed compiling with debug=n

Quoted 3 lines · Thomas Leonard

Without -fno-tree-loop-distribute-patterns, gcc -O3 recognises that our "memset" is doing a memset operation and tries to make it call the standard "memset", creating a loop.

As in __builtin_memset or some such? Isn't there are -nostdthings we could/should use? -fno-tree-loop... seems a bit abstracted from the affect and it's not impossible that different gcc would still do this same thing in the future under some other optimisation.

Quoted 1 line

The change to fdt_ro.c is to avoid a compiler warning.

Ah, here it is for real ;-)

Quoted 33 lines
---
 extras/mini-os/minios.mk   | 2 +-
 xen/common/libfdt/fdt_ro.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
extras/mini-os/minios.mk +1 -1
index 20ba64b..3e881e4 100644
@@ -23,7 +23,7 @@ DEF_CFLAGS += -g
 #DEF_CFLAGS += -DGNT_DEBUG
 #DEF_CFLAGS += -DGNTMAP_DEBUG
 else
-DEF_CFLAGS += -O3
+DEF_CFLAGS += -O3 -fno-tree-loop-distribute-patterns
 endif
 
 # Make the headers define our internal stuff
xen/common/libfdt/fdt_ro.c +1 -1
index 02b6d68..a34c6d6 100644
@@ -444,7 +444,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
 
 int fdt_node_depth(const void *fdt, int nodeoffset)
 {
-	int nodedepth;
+	int nodedepth = -1;
 	int err;
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);