All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/33] Support multiple ARM platforms in Xen
@ 2013-05-08  2:33 Julien Grall
  2013-05-08  2:33 ` [PATCH V2 01/33] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
                   ` (33 more replies)
  0 siblings, 34 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Hi,

This is the second version of the patch series. It's rebased on Xen 4.3 rc-1
with Stefano's SMP patch series.

The majors changes:
    - Add platform_poweroff and platform_quirks
    - Rework early assembly printk to use macro instead of function
    - Use defines where it's possible in exynos UART code
    - Missing Signed-off-by from Anthony exynos UART code
    - Introduce request_dt_irq and setup_dt_irq. request_irq and setup_irq
    are deprecated for ARM. This part is divided in small patches (one to introduce
    new function and one to remove the old function) to avoid compilation breakage.

For all changes see in each patch.

Xen can boot on both Arndale Board and the Versatile Express without
recompilation. But there is still some hardcoded part, mainly in assembly.

Things to do:
    - Move secondary CPUs bring up code in platform specific
    - Move out of Xen the switch between secure mode and hypervisor mode
    - Rework dom0 device tree creation
    - Use everywhere the new device tree API
    - Add a support for SYS MMU
    - Convert vtimer to use non-hardcoded IRQ

For the moment the known bugs are:
    - Bash can sometimes crash with: segfault, memory corruption. It's
    seems it's due to a lack of VPF save/restore in Xen.

If you want to try this patch series you can clone:
    git clone -b arm-v2 git://xenbits.xen.org/people/julieng/xen-unstable.git

The command line to compile Xen is the same as before. You just need to
specify on Xen command line, via the device tree, which UART will be used
for the console.

Feel free to test this branch during Xen test day. The wiki has been updated
for the arndale board:
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Arndale

It's now based on:
  - this patch series for Xen
  - linux 3.9

Feel free to test this branch during the Xen test day on both the versatile
express and the arndale board.

Cheers,

Anthony PERARD (2):
  xen/arm: Add exynos 4210 UART support
  xen/arm: Add Exynos 4210 UART support for early printk

Julien Grall (31):
  xen/arm: lr must be included in range [0-nr_lr(
  xen/arm: don't allow dom0 to access to vpl011 UART0 memory range
  xen/arm: Remove duplicated GICD_ICPIDR2 definition
  xen/arm: Bump early printk internal buffer to 512
  xen/arm: Fix early_panic when EARLY_PRINTK is disabled
  xen/arm: Load dtb after dom0 kernel
  xen/arm: Create a hierarchical device tree
  xen/arm: Add helpers to use the device tree
  xen/arm: Add helpers to retrieve an address from the device tree
  xen/arm: Add helpers to retrieve an interrupt description from the
    device tree
  xen/arm: Introduce gic_route_dt_irq
  xen/arm: Introduce gic_irq_xlate
  xen/arm: Introduce setup_dt_irq
  xen/arm: Introduce request_dt_irq
  xen/arm: Use hierarchical device tree to retrieve GIC information
  xen/arm: Retrieve timer interrupts from the device tree
  xen/arm: Don't hardcode VGIC informations
  xen/arm: Introduce a generic way to use a device from the device tree
  xen/arm: New callback in uart_driver to get device tree interrupt
    structure
  xen/arm: Add generic UART to get the device in the device tree
  xen/arm: Use device tree API in pl011 UART driver
  xen/arm: Use the device tree to map the address range and IRQ to dom0
  xen/arm: Allow Xen to run on multiple platform without recompilation
  xen/arm: WORKAROUND 1:1 memory mapping for dom0
  xen/arm: Add versatile express platform
  xen/arm: remove request_irq
  xen/arm: remove setup_irq
  xen/arm: Don't use pl011 UART by default for early printk
  xen/arm: Add platform specific code for the exynos5
  xen/arm: WORKAROUND Support kick cpus and switch to hypervisor for
    the exynos5
  xen/arm64: Remove hardcoded value for gic in assembly code

 config/arm32.mk                          |    1 +
 docs/misc/arm/early-printk.txt           |   15 +
 xen/arch/arm/Makefile                    |    4 +-
 xen/arch/arm/Rules.mk                    |   19 +
 xen/arch/arm/arm32/Makefile              |    4 +-
 xen/arch/arm/arm32/debug-exynos4210.inc  |   77 ++
 xen/arch/arm/arm32/debug-pl011.inc       |   58 ++
 xen/arch/arm/arm32/debug.S               |   33 +
 xen/arch/arm/arm32/head.S                |   84 +-
 xen/arch/arm/arm32/mode_switch.S         |   75 +-
 xen/arch/arm/arm64/Makefile              |    2 +
 xen/arch/arm/arm64/debug-pl011.inc       |   59 ++
 xen/arch/arm/arm64/debug.S               |   33 +
 xen/arch/arm/arm64/head.S                |   71 +-
 xen/arch/arm/arm64/mode_switch.S         |    7 +-
 xen/arch/arm/device.c                    |   74 ++
 xen/arch/arm/domain_build.c              |  192 ++++-
 xen/arch/arm/early_printk.c              |   19 +-
 xen/arch/arm/gic.c                       |  160 +++-
 xen/arch/arm/irq.c                       |    8 +-
 xen/arch/arm/platform.c                  |  137 +++
 xen/arch/arm/platforms/Makefile          |    1 +
 xen/arch/arm/platforms/exynos5.c         |   86 ++
 xen/arch/arm/platforms/vexpress.c        |   30 +
 xen/arch/arm/setup.c                     |   14 +-
 xen/arch/arm/shutdown.c                  |   16 +-
 xen/arch/arm/time.c                      |   65 +-
 xen/arch/arm/vgic.c                      |   20 +-
 xen/arch/arm/vpl011.c                    |    4 +-
 xen/arch/arm/xen.lds.S                   |   14 +
 xen/common/device_tree.c                 | 1326 ++++++++++++++++++++++++++++--
 xen/drivers/char/Makefile                |    2 +
 xen/drivers/char/arm-uart.c              |   81 ++
 xen/drivers/char/exynos4210-uart.c       |  357 ++++++++
 xen/drivers/char/pl011.c                 |   64 +-
 xen/drivers/char/serial.c                |   16 +
 xen/include/asm-arm/config.h             |   15 +-
 xen/include/asm-arm/device.h             |   52 ++
 xen/include/asm-arm/domain.h             |    5 +-
 xen/include/asm-arm/early_printk.h       |    4 +-
 xen/include/asm-arm/exynos4210-uart.h    |  111 +++
 xen/include/asm-arm/gic.h                |   16 +-
 xen/include/asm-arm/irq.h                |    8 +
 xen/include/asm-arm/platform.h           |   87 ++
 xen/include/asm-arm/platforms/exynos5.h  |   40 +
 xen/include/asm-arm/platforms/vexpress.h |   14 +
 xen/include/asm-arm/time.h               |    3 +
 xen/include/xen/device_tree.h            |  378 ++++++++-
 xen/include/xen/serial.h                 |   13 +-
 49 files changed, 3682 insertions(+), 292 deletions(-)
 create mode 100644 docs/misc/arm/early-printk.txt
 create mode 100644 xen/arch/arm/arm32/debug-exynos4210.inc
 create mode 100644 xen/arch/arm/arm32/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm32/debug.S
 create mode 100644 xen/arch/arm/arm64/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm64/debug.S
 create mode 100644 xen/arch/arm/device.c
 create mode 100644 xen/arch/arm/platform.c
 create mode 100644 xen/arch/arm/platforms/exynos5.c
 create mode 100644 xen/drivers/char/arm-uart.c
 create mode 100644 xen/drivers/char/exynos4210-uart.c
 create mode 100644 xen/include/asm-arm/device.h
 create mode 100644 xen/include/asm-arm/exynos4210-uart.h
 create mode 100644 xen/include/asm-arm/platform.h
 create mode 100644 xen/include/asm-arm/platforms/exynos5.h

-- 
Julien Grall

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

* [PATCH V2 01/33] xen/arm: lr must be included in range [0-nr_lr(
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 02/33] xen/arm: don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
                   ` (32 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v2:
   - Typo in the commit message
---
 xen/arch/arm/gic.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 61de230..6d71aae 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -512,7 +512,9 @@ static inline void gic_set_lr(int lr, unsigned int virtual_irq,
 {
     int maintenance_int = GICH_LR_MAINTENANCE_IRQ;
 
-    BUG_ON(lr > nr_lrs);
+    BUG_ON(lr >= nr_lrs);
+    BUG_ON(lr < 0);
+    BUG_ON(state & ~(GICH_LR_STATE_MASK<<GICH_LR_STATE_SHIFT));
 
     GICH[GICH_LR + lr] = state |
         maintenance_int |
-- 
Julien Grall

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

* [PATCH V2 02/33] xen/arm: don't allow dom0 to access to vpl011 UART0 memory range
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
  2013-05-08  2:33 ` [PATCH V2 01/33] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 03/33] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
                   ` (31 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

As vpl011 UART is not initialized for dom 0, when the domain tries to access to
this range, a segfault will occur in Xen. The right behaviour should be a data
abort for the guest.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/vpl011.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
index 9472d0a..13ba623 100644
--- a/xen/arch/arm/vpl011.c
+++ b/xen/arch/arm/vpl011.c
@@ -85,7 +85,9 @@ static void uart0_print_char(char c)
 
 static int uart0_mmio_check(struct vcpu *v, paddr_t addr)
 {
-    return addr >= UART0_START && addr < UART0_END;
+    struct domain *d = v->domain;
+
+    return d->domain_id != 0 && addr >= UART0_START && addr < UART0_END;
 }
 
 static int uart0_mmio_read(struct vcpu *v, mmio_info_t *info)
-- 
Julien Grall

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

* [PATCH V2 03/33] xen/arm: Remove duplicated GICD_ICPIDR2 definition
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
  2013-05-08  2:33 ` [PATCH V2 01/33] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
  2013-05-08  2:33 ` [PATCH V2 02/33] xen/arm: don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512 Julien Grall
                   ` (30 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/include/asm-arm/gic.h |    1 -
 1 file changed, 1 deletion(-)

diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 84ebc83..3efb2b5 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -43,7 +43,6 @@
 #define GICD_ICFGRN     (0xCFC/4)
 #define GICD_NSACR      (0xE00/4)
 #define GICD_NSACRN     (0xEFC/4)
-#define GICD_ICPIDR2    (0xFE8/4)
 #define GICD_SGIR       (0xF00/4)
 #define GICD_CPENDSGIR  (0xF10/4)
 #define GICD_CPENDSGIRN (0xF1C/4)
-- 
Julien Grall

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

* [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (2 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 03/33] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:00   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 05/33] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
                   ` (29 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

When debug is enabled in device tree code, some lines
are bigger than 80 characters.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
 - Move buffer to a static variable
---
 xen/arch/arm/early_printk.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
index bdf4c0e..0f99a43 100644
--- a/xen/arch/arm/early_printk.c
+++ b/xen/arch/arm/early_printk.c
@@ -29,6 +29,9 @@ void __init early_putch(char c)
     *r = c;
 }
 
+/* Early printk buffer */
+static char __initdata buf[512];
+
 static void __init early_puts(const char *s)
 {
     while (*s != '\0') {
@@ -41,8 +44,6 @@ static void __init early_puts(const char *s)
 
 static void __init early_vprintk(const char *fmt, va_list args)
 {
-    char buf[80];
-
     vsnprintf(buf, sizeof(buf), fmt, args);
     early_puts(buf);
 }
-- 
Julien Grall

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

* [PATCH V2 05/33] xen/arm: Fix early_panic when EARLY_PRINTK is disabled
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (3 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512 Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 06/33] xen/arm: Load dtb after dom0 kernel Julien Grall
                   ` (28 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Even if EARLY_PRINTK is not enabled, early_panic must never return.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/include/asm-arm/early_printk.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/include/asm-arm/early_printk.h b/xen/include/asm-arm/early_printk.h
index a770d4a..a0297a7 100644
--- a/xen/include/asm-arm/early_printk.h
+++ b/xen/include/asm-arm/early_printk.h
@@ -20,7 +20,7 @@ void early_panic(const char *fmt, ...) __attribute__((noreturn));
 #else
 
 static inline void early_printk(const char *fmt, ...) {}
-static inline void early_panic(const char *fmt, ...) {}
+static inline void  __attribute__((noreturn)) early_panic(const char *fmt, ...) {while(1);}
 
 #endif
 
-- 
Julien Grall

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

* [PATCH V2 06/33] xen/arm: Load dtb after dom0 kernel
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (4 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 05/33] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 07/33] xen/arm: Create a hierarchical device tree Julien Grall
                   ` (27 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

On some setup, the first linux page table is at 0x40004000. Xen will load
dom0 device tree at 0x4000100. In case of the device tree is big, linux will
corrupt the device tree.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 xen/arch/arm/domain_build.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 8748272..6581492 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -407,8 +407,9 @@ int construct_dom0(struct domain *d)
     /* The following loads use the domain's p2m */
     p2m_load_VTTBR(d);
 
-    dtb_load(&kinfo);
+    kinfo.dtb_paddr = kinfo.zimage.load_addr + kinfo.zimage.len;
     kernel_load(&kinfo);
+    dtb_load(&kinfo);
 
     discard_initial_modules();
 
-- 
Julien Grall

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

* [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (5 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 06/33] xen/arm: Load dtb after dom0 kernel Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:11   ` Ian Campbell
  2013-05-08 13:52   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 08/33] xen/arm: Add helpers to use the " Julien Grall
                   ` (26 subsequent siblings)
  33 siblings, 2 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Add function to parse the device tree and create a hierarchical tree.

This code is based on drivers/of/base.c in linux source.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
  - s/dom0$/device/ in comment "By default dom0 owns the dom0"
  - Use DOMID_XEN instead of DOMID_INVALID for DT_USED_BY_XEN
---
 xen/arch/arm/setup.c          |    5 +
 xen/common/device_tree.c      |  452 ++++++++++++++++++++++++++++++++++++++++-
 xen/include/xen/device_tree.h |   98 +++++++++
 3 files changed, 551 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 59646d6..07c0444 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -429,12 +429,17 @@ void __init start_xen(unsigned long boot_phys_offset,
     setup_pagetables(boot_phys_offset, get_xen_paddr());
     setup_mm(fdt_paddr, fdt_size);
 
+    dt_unflatten_host_device_tree();
+
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
     pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
     console_init_preirq();
 #endif
 
+    /* FIXME: Do something smarter */
+    dt_switch_to_printk();
+
     processor_id();
 
     init_xen_time();
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 7997f41..bdf8871 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -2,6 +2,8 @@
  * Device Tree
  *
  * Copyright (C) 2012 Citrix Systems, Inc.
+ * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
+ * benh@kernel.crashing.org
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -19,15 +21,51 @@
 #include <xen/stdarg.h>
 #include <xen/string.h>
 #include <xen/cpumask.h>
+#include <xen/ctype.h>
+#include <xen/lib.h>
 #include <asm/early_printk.h>
 
 struct dt_early_info __initdata early_info;
 void *device_tree_flattened;
+/* Host device tree */
+struct dt_device_node *dt_host;
+
+/**
+ * struct dt_alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct dt_alias_prop {
+    struct list_head link;
+    const char *alias;
+    struct dt_device_node *np;
+    int id;
+    char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
 
 /* Some device tree functions may be called both before and after the
    console is initialized. */
 static void (*dt_printk)(const char *fmt, ...) = early_printk;
 
+#define ALIGN(x, a) ((x + (a) - 1) & ~((a) - 1));
+
+// #define DEBUG_DT
+
+#ifdef DEBUG_DT
+# define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
+#else
+# define dt_dprintk(fmt, args...) do {} while ( 0 )
+#endif
+
 bool_t device_tree_node_matches(const void *fdt, int node, const char *match)
 {
     const char *name;
@@ -263,7 +301,7 @@ static int dump_node(const void *fdt, int node, const char *name, int depth,
 
     if ( name[0] == '\0' )
         name = "/";
-    printk("%s%s:\n", prefix, name);
+    dt_printk("%s%s:\n", prefix, name);
 
     for ( prop = fdt_first_property_offset(fdt, node);
           prop >= 0;
@@ -273,7 +311,7 @@ static int dump_node(const void *fdt, int node, const char *name, int depth,
 
         p = fdt_get_property_by_offset(fdt, prop, NULL);
 
-        printk("%s  %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff)));
+        dt_printk("%s  %s\n", prefix, fdt_string(fdt, fdt32_to_cpu(p->nameoff)));
     }
 
     return 0;
@@ -488,11 +526,417 @@ size_t __init device_tree_early_init(const void *fdt)
     device_tree_for_each_node((void *)fdt, early_scan_node, NULL);
     early_print_info();
 
-    dt_printk = printk;
-
     return fdt_totalsize(fdt);
 }
 
+static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+                                       unsigned long align)
+{
+    void *res;
+
+    *mem = ALIGN(*mem, align);
+    res = (void *)*mem;
+    *mem += size;
+
+    return res;
+}
+
+/* Find a property with a given name for a given node and return it. */
+static const struct dt_property *
+dt_find_property(const struct dt_device_node *np,
+                 const char *name,
+                 u32 *lenp)
+{
+    const struct dt_property *pp;
+
+    if ( !np )
+        return NULL;
+
+    for ( pp = np->properties; pp; pp = pp->next )
+    {
+        if ( strcmp(pp->name, name) == 0 )
+        {
+            if ( lenp )
+                *lenp = pp->length;
+            break;
+        }
+    }
+
+    return pp;
+}
+
+const void *dt_get_property(const struct dt_device_node *np,
+                            const char *name, u32 *lenp)
+{
+    const struct dt_property *pp = dt_find_property(np, name, lenp);
+
+    return pp ? pp->value : NULL;
+}
+
+struct dt_device_node *dt_find_node_by_path(const char *path)
+{
+    struct dt_device_node *np;
+
+    for_each_device_node(dt_host, np)
+        if ( np->full_name && (dt_node_cmp(np->full_name, path) == 0) )
+            break;
+
+    return np;
+}
+
+/**
+ * unflatten_dt_node - Alloc and populate a device_node from the flat tree
+ * @fdt: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
+ * @p: pointer to node in flat tree
+ * @dad: Parent struct device_node
+ * @allnextpp: pointer to ->allnext from last allocated device_node
+ * @fpsize: Size of the node path up at the current depth.
+ */
+static unsigned long __init unflatten_dt_node(const void *fdt,
+                                              unsigned long mem,
+                                              unsigned long *p,
+                                              struct dt_device_node *dad,
+                                              struct dt_device_node ***allnextpp,
+                                              unsigned long fpsize)
+{
+    struct dt_device_node *np;
+    struct dt_property *pp, **prev_pp = NULL;
+    char *pathp;
+    u32 tag;
+    unsigned int l, allocl;
+    int has_name = 0;
+    int new_format = 0;
+
+    tag = be32_to_cpup((__be32 *)(*p));
+    if ( tag != FDT_BEGIN_NODE )
+    {
+        dt_printk(XENLOG_WARNING "Weird tag at start of node: %x\n", tag);
+        return mem;
+    }
+    *p += 4;
+    pathp = (char *)*p;
+    l = allocl = strlen(pathp) + 1;
+    *p = ALIGN(*p + l, 4);
+
+    /* version 0x10 has a more compact unit name here instead of the full
+     * path. we accumulate the full path size using "fpsize", we'll rebuild
+     * it later. We detect this because the first character of the name is
+     * not '/'.
+     */
+    if ( (*pathp) != '/' )
+    {
+        new_format = 1;
+        if ( fpsize == 0 )
+        {
+            /* root node: special case. fpsize accounts for path
+             * plus terminating zero. root node only has '/', so
+             * fpsize should be 2, but we want to avoid the first
+             * level nodes to have two '/' so we use fpsize 1 here
+             */
+            fpsize = 1;
+            allocl = 2;
+        }
+        else
+        {
+            /* account for '/' and path size minus terminal 0
+             * already in 'l'
+             */
+            fpsize += l;
+            allocl = fpsize;
+        }
+    }
+
+    np = unflatten_dt_alloc(&mem, sizeof(struct dt_device_node) + allocl,
+                            __alignof__(struct dt_device_node));
+    if ( allnextpp )
+    {
+        memset(np, 0, sizeof(*np));
+        np->full_name = ((char *)np) + sizeof(struct dt_device_node);
+        /* By default dom0 owns the device */
+        np->used_by = 0;
+        if ( new_format )
+        {
+            char *fn = np->full_name;
+            /* rebuild full path for new format */
+            if ( dad && dad->parent )
+            {
+                strlcpy(fn, dad->full_name, allocl);
+#ifdef DEBUG_DT
+                if ( (strlen(fn) + l + 1) != allocl )
+                {
+                    dt_dprintk("%s: p: %d, l: %d, a: %d\n",
+                               pathp, (int)strlen(fn),
+                               l, allocl);
+                }
+#endif
+                fn += strlen(fn);
+            }
+            *(fn++) = '/';
+            memcpy(fn, pathp, l);
+        }
+        else
+            memcpy(np->full_name, pathp, l);
+        prev_pp = &np->properties;
+        **allnextpp = np;
+        *allnextpp = &np->allnext;
+        if ( dad != NULL )
+        {
+            np->parent = dad;
+            /* we temporarily use the next field as `last_child'*/
+            if ( dad->next == NULL )
+                dad->child = np;
+            else
+                dad->next->sibling = np;
+            dad->next = np;
+        }
+    }
+    /* process properties */
+    while ( 1 )
+    {
+        u32 sz, noff;
+        const char *pname;
+
+        tag = be32_to_cpup((__be32 *)(*p));
+        if ( tag == FDT_NOP )
+        {
+            *p += 4;
+            continue;
+        }
+        if ( tag != FDT_PROP )
+            break;
+        *p += 4;
+        sz = be32_to_cpup((__be32 *)(*p));
+        noff = be32_to_cpup((__be32 *)((*p) + 4));
+        *p += 8;
+        if ( fdt_version(fdt) < 0x10 )
+            *p = ALIGN(*p, sz >= 8 ? 8 : 4);
+
+        pname = fdt_string(fdt, noff);
+        if ( pname == NULL )
+        {
+            dt_dprintk("Can't find property name in list!\n");
+            break;
+        }
+        if ( strcmp(pname, "name") == 0 )
+            has_name = 1;
+        l = strlen(pname) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property),
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            /* We accept flattened tree phandles either in
+             * ePAPR-style "phandle" properties, or the
+             * legacy "linux,phandle" properties.  If both
+             * appear and have different values, things
+             * will get weird.  Don't do that. */
+            if ( (strcmp(pname, "phandle") == 0) ||
+                 (strcmp(pname, "linux,phandle") == 0) )
+            {
+                if ( np->phandle == 0 )
+                    np->phandle = be32_to_cpup((__be32*)*p);
+            }
+            /* And we process the "ibm,phandle" property
+             * used in pSeries dynamic device tree
+             * stuff */
+            if ( strcmp(pname, "ibm,phandle") == 0 )
+                np->phandle = be32_to_cpup((__be32 *)*p);
+            pp->name = pname;
+            pp->length = sz;
+            pp->value = (void *)*p;
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+        }
+        *p = ALIGN((*p) + sz, 4);
+    }
+    /* with version 0x10 we may not have the name property, recreate
+     * it here from the unit name if absent
+     */
+    if ( !has_name )
+    {
+        char *p1 = pathp, *ps = pathp, *pa = NULL;
+        int sz;
+
+        while ( *p1 )
+        {
+            if ( (*p1) == '@' )
+                pa = p1;
+            if ( (*p1) == '/' )
+                ps = p1 + 1;
+            p1++;
+        }
+        if ( pa < ps )
+            pa = p1;
+        sz = (pa - ps) + 1;
+        pp = unflatten_dt_alloc(&mem, sizeof(struct dt_property) + sz,
+                                __alignof__(struct dt_property));
+        if ( allnextpp )
+        {
+            pp->name = "name";
+            pp->length = sz;
+            pp->value = pp + 1;
+            *prev_pp = pp;
+            prev_pp = &pp->next;
+            memcpy(pp->value, ps, sz - 1);
+            ((char *)pp->value)[sz - 1] = 0;
+            dt_dprintk("fixed up name for %s -> %s\n", pathp,
+                       (char *)pp->value);
+        }
+    }
+    if ( allnextpp )
+    {
+        *prev_pp = NULL;
+        np->name = dt_get_property(np, "name", NULL);
+        np->type = dt_get_property(np, "device_type", NULL);
+
+        if ( !np->name )
+            np->name = "<NULL>";
+        if ( !np->type )
+            np->type = "<NULL>";
+    }
+    while ( tag == FDT_BEGIN_NODE || tag == FDT_NOP )
+    {
+        if ( tag == FDT_NOP )
+            *p += 4;
+        else
+            mem = unflatten_dt_node(fdt, mem, p, np, allnextpp, fpsize);
+        tag = be32_to_cpup((__be32 *)(*p));
+    }
+    if ( tag != FDT_END_NODE )
+    {
+        dt_printk(XENLOG_WARNING "Weird tag at end of node: %x\n", tag);
+        return mem;
+    }
+
+    *p += 4;
+    return mem;
+}
+
+/**
+ * __unflatten_device_tree - create tree of device_nodes from flat blob
+ *
+ * unflattens a device-tree, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used.
+ * @fdt: The fdt to expand
+ * @mynodes: The device_node tree created by the call
+ */
+static void __init __unflatten_device_tree(const void *fdt,
+                                           struct dt_device_node **mynodes)
+{
+    unsigned long start, mem, size;
+    struct dt_device_node **allnextp = mynodes;
+
+    dt_dprintk(" -> unflatten_device_tree()\n");
+
+    dt_dprintk("Unflattening device tree:\n");
+    dt_dprintk("magic: %#08x\n", fdt_magic(fdt));
+    dt_dprintk("size: %#08x\n", fdt_totalsize(fdt));
+    dt_dprintk("version: %#08x\n", fdt_version(fdt));
+
+    /* First pass, scan for size */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    size = unflatten_dt_node(fdt, 0, &start, NULL, NULL, 0);
+    size = (size | 3) + 1;
+
+    dt_dprintk("  size is %#lx allocating...\n", size);
+
+    /* Allocate memory for the expanded device tree */
+    mem = (unsigned long)_xmalloc (size + 4, __alignof__(struct dt_device_node));
+
+    ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
+
+    dt_dprintk("  unflattening %lx...\n", mem);
+
+    /* Second pass, do actual unflattening */
+    start = ((unsigned long)fdt) + fdt_off_dt_struct(fdt);
+    unflatten_dt_node(fdt, mem, &start, NULL, &allnextp, 0);
+    if ( be32_to_cpup((__be32 *)start) != FDT_END )
+        dt_printk(XENLOG_WARNING "Weird tag at end of tree: %08x\n",
+                  *((u32 *)start));
+    if ( be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef )
+        dt_printk(XENLOG_WARNING "End of tree marker overwritten: %08x\n",
+                  be32_to_cpu(((__be32 *)mem)[size / 4]));
+    *allnextp = NULL;
+
+    dt_dprintk(" <- unflatten_device_tree()\n");
+}
+
+static void dt_alias_add(struct dt_alias_prop *ap,
+                         struct dt_device_node *np,
+                         int id, const char *stem, int stem_len)
+{
+    ap->np = np;
+    ap->id = id;
+    strlcpy(ap->stem, stem, stem_len + 1);
+    list_add_tail(&ap->link, &aliases_lookup);
+    dt_dprintk("adding DT alias:%s: stem=%s id=%d node=%s\n",
+               ap->alias, ap->stem, ap->id, dt_node_full_name(np));
+}
+
+/**
+ * dt_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties.  It returns the
+ * number of alias_prop found, or error code in error case.
+ */
+static void __init dt_alias_scan(void)
+{
+    const struct dt_property *pp;
+    const struct dt_device_node *aliases;
+
+    aliases = dt_find_node_by_path("/aliases");
+    if ( !aliases )
+        return;
+
+    for_each_property_of_node( aliases, pp )
+    {
+        const char *start = pp->name;
+        const char *end = start + strlen(start);
+        struct dt_device_node *np;
+        struct dt_alias_prop *ap;
+        int id, len;
+
+        /* Skip those we do not want to proceed */
+        if ( !strcmp(pp->name, "name") ||
+             !strcmp(pp->name, "phandle") ||
+             !strcmp(pp->name, "linux,phandle") )
+            continue;
+
+        np = dt_find_node_by_path(pp->value);
+        if ( !np )
+            continue;
+
+        /* walk the alias backwards to extract the id and work out
+         * the 'stem' string */
+        while ( isdigit(*(end-1)) && end > start )
+            end--;
+        len = end - start;
+
+        id = simple_strtoll(end, NULL, 10);
+
+        /* Allocate an alias_prop with enough space for the stem */
+        ap = _xmalloc(sizeof(*ap) + len + 1, 4);
+        if ( !ap )
+            continue;
+        ap->alias = start;
+        dt_alias_add(ap, np, id, start, len);
+    }
+}
+
+void __init dt_unflatten_host_device_tree(void)
+{
+    __unflatten_device_tree(device_tree_flattened, &dt_host);
+    dt_alias_scan();
+}
+
+void __init dt_switch_to_printk(void)
+{
+    dt_printk = printk;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 19bda98..8f526d1 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -10,6 +10,10 @@
 #ifndef __XEN_DEVICE_TREE_H__
 #define __XEN_DEVICE_TREE_H__
 
+#include <asm/byteorder.h>
+#include <public/xen.h>
+#include <xen/init.h>
+#include <xen/string.h>
 #include <xen/types.h>
 
 #define DEVICE_TREE_MAX_DEPTH 16
@@ -52,6 +56,51 @@ struct dt_early_info {
     struct dt_module_info modules;
 };
 
+typedef u32 dt_phandle;
+
+/**
+ * dt_property - describe a property for a device
+ * @name: name of the property
+ * @length: size of the value
+ * @value: pointer to data contained in the property
+ * @next: pointer to the next property of a specific node
+ */
+struct dt_property {
+    const char *name;
+    u32 length;
+    void *value;
+    struct dt_property *next;
+};
+
+#define DT_USED_BY_XEN DOMID_XEN
+
+/**
+ * dt_device_node - describe a node in the device tree
+ * @name: name of the node
+ * @type: type of the node (ie: memory, cpu, ...)
+ * @full_name: full name, it's composed of all the ascendant name separate by /
+ * @used_by: who owns the node? (ie: xen, dom0...)
+ * @properties: list of properties for the node
+ * @child: pointer to the first child
+ * @sibling: pointer to the next sibling
+ * @allnext: pointer to the next in list of all nodes
+ */
+struct dt_device_node {
+    const char *name;
+    const char *type;
+    dt_phandle phandle;
+    char *full_name;
+    domid_t used_by; /* By default it's used by dom0 */
+
+    struct dt_property *properties;
+    struct dt_device_node *parent;
+    struct dt_device_node *child;
+    struct dt_device_node *sibling;
+    struct dt_device_node *next; /* TODO: Remove it. Only use to know the last children */
+    struct dt_device_node *allnext;
+
+};
+
 typedef int (*device_tree_node_func)(const void *fdt,
                                      int node, const char *name, int depth,
                                      u32 address_cells, u32 size_cells,
@@ -77,4 +126,53 @@ int device_tree_for_each_node(const void *fdt,
 const char *device_tree_bootargs(const void *fdt);
 void device_tree_dump(const void *fdt);
 
+/**
+ * dt_unflatten_host_device_tree - Unflatten the host device tree
+ *
+ * Create a hierarchical device tree for the host DTB to be able
+ * to retrieve parents.
+ */
+void __init dt_unflatten_host_device_tree(void);
+
+/**
+ * Dump device tree message with printk
+ * TODO: Find another way to switch between early_printk and printk
+ * int the device tree code
+ */
+void __init dt_switch_to_printk(void);
+
+/**
+ * Host device tree
+ * DO NOT modify it!
+ */
+extern struct dt_device_node *dt_host;
+
+#define dt_node_cmp(s1, s2) strcmp((s1), (s2))
+#define dt_compat_cmp(s1, s2, l) strnicmp((s1), (s2), l)
+
+#define for_each_property_of_node(dn, pp)                   \
+    for ( pp = dn->properties; pp != NULL; pp = pp->next )
+
+#define for_each_device_node(dt, dn)                         \
+    for ( dn = dt; dn != NULL; dn = dn->allnext )
+
+static inline const char *dt_node_full_name(const struct dt_device_node *np)
+{
+    return (np && np->full_name) ? np->full_name : "<no-node>";
+}
+
+/**
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+const void *dt_get_property(const struct dt_device_node *np,
+                            const char *name, u32 *lenp);
+
+/**
+ * dt_find_node_by_path - Find a node matching a full DT path
+ * @path: The full path to match
+ *
+ * Returns a node pointer.
+ */
+struct dt_device_node *dt_find_node_by_path(const char *path);
 #endif
-- 
Julien Grall

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

* [PATCH V2 08/33] xen/arm: Add helpers to use the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (6 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 07/33] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:18   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from " Julien Grall
                   ` (25 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - use dt_node_cmp and dt_compat_cmp in early device tree code
---
 xen/common/device_tree.c      |  127 ++++++++++++++++++++++++++++++++++++++++-
 xen/include/xen/device_tree.h |  120 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 245 insertions(+), 2 deletions(-)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index bdf8871..449c332 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -88,20 +88,23 @@ bool_t device_tree_type_matches(const void *fdt, int node, const char *match)
     if ( prop == NULL )
         return 0;
 
-    return !strcmp(prop, match);
+    return !dt_node_cmp(prop, match);
 }
 
 bool_t device_tree_node_compatible(const void *fdt, int node, const char *match)
 {
     int len, l;
+    int mlen;
     const void *prop;
 
+    mlen = strlen(match);
+
     prop = fdt_getprop(fdt, node, "compatible", &len);
     if ( prop == NULL )
         return 0;
 
     while ( len > 0 ) {
-        if ( !strcmp(prop, match) )
+        if ( !dt_compat_cmp(prop, match, mlen) )
             return 1;
         l = strlen(prop) + 1;
         prop += l;
@@ -573,6 +576,54 @@ const void *dt_get_property(const struct dt_device_node *np,
     return pp ? pp->value : NULL;
 }
 
+bool_t dt_device_is_compatible(const struct dt_device_node *device,
+                               const char *compat)
+{
+    const char* cp;
+    u32 cplen, l;
+
+    cp = dt_get_property(device, "compatible", &cplen);
+    if ( cp == NULL )
+        return 0;
+    while ( cplen > 0 )
+    {
+        if ( dt_compat_cmp(cp, compat, strlen(compat)) == 0 )
+            return 1;
+        l = strlen(cp) + 1;
+        cp += l;
+        cplen -= l;
+    }
+
+    return 0;
+}
+
+bool_t dt_machine_is_compatible(const char *compat)
+{
+    const struct dt_device_node *root;
+    bool_t rc = 0;
+
+    root = dt_find_node_by_path("/");
+    if ( root )
+    {
+        rc = dt_device_is_compatible(root, compat);
+    }
+    return rc;
+}
+
+struct dt_device_node *dt_find_node_by_name(struct dt_device_node *from,
+                                            const char *name)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    for_each_device_node(dt, np)
+        if ( np->name && (dt_node_cmp(np->name, name) == 0) )
+            break;
+
+    return np;
+}
+
 struct dt_device_node *dt_find_node_by_path(const char *path)
 {
     struct dt_device_node *np;
@@ -584,6 +635,78 @@ struct dt_device_node *dt_find_node_by_path(const char *path)
     return np;
 }
 
+struct dt_device_node *dt_find_node_by_alias(const char *alias)
+{
+    const struct dt_alias_prop *app;
+
+    list_for_each_entry( app, &aliases_lookup, link )
+    {
+        if ( !strcmp(app->alias, alias) )
+            return app->np;
+    }
+
+    return NULL;
+}
+
+const struct dt_device_node *dt_get_parent(const struct dt_device_node *node)
+{
+    if ( !node )
+        return NULL;
+
+    return node->parent;
+}
+
+struct dt_device_node *
+dt_find_compatible_node(struct dt_device_node *from,
+                        const char *type,
+                        const char *compatible)
+{
+    struct dt_device_node *np;
+    struct dt_device_node *dt;
+
+    dt = from ? from->allnext : dt_host;
+    for_each_device_node(dt, np)
+    {
+        if ( type
+             && !(np->type && (dt_node_cmp(np->type, type) == 0)) )
+            continue;
+        if ( dt_device_is_compatible(np, compatible) )
+            break;
+    }
+
+    return np;
+}
+
+int dt_n_addr_cells(const struct dt_device_node *np)
+{
+    const __be32 *ip;
+
+    do {
+        if ( np->parent )
+            np = np->parent;
+        ip = dt_get_property(np, "#address-cells", NULL);
+        if ( ip )
+            return be32_to_cpup(ip);
+    } while ( np->parent );
+    /* No #address-cells property for the root node */
+    return DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
+}
+
+int dt_n_size_cells(const struct dt_device_node *np)
+{
+    const __be32 *ip;
+
+    do {
+        if ( np->parent )
+            np = np->parent;
+        ip = dt_get_property(np, "#size-cells", NULL);
+        if ( ip )
+            return be32_to_cpup(ip);
+    } while ( np->parent );
+    /* No #address-cells property for the root node */
+    return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
+}
+
 /**
  * unflatten_dt_node - Alloc and populate a device_node from the flat tree
  * @fdt: The parent device tree blob
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 8f526d1..879b75d 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -150,17 +150,72 @@ extern struct dt_device_node *dt_host;
 #define dt_node_cmp(s1, s2) strcmp((s1), (s2))
 #define dt_compat_cmp(s1, s2, l) strnicmp((s1), (s2), l)
 
+/* Default #address and #size cells */
+#define DT_ROOT_NODE_ADDR_CELLS_DEFAULT 1
+#define DT_ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
 #define for_each_property_of_node(dn, pp)                   \
     for ( pp = dn->properties; pp != NULL; pp = pp->next )
 
 #define for_each_device_node(dt, dn)                         \
     for ( dn = dt; dn != NULL; dn = dn->allnext )
 
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 dt_read_number(const __be32 *cell, int size)
+{
+    u64 r = 0;
+
+    while ( size-- )
+        r = (r << 32) | be32_to_cpu(*(cell++));
+    return r;
+}
+
 static inline const char *dt_node_full_name(const struct dt_device_node *np)
 {
     return (np && np->full_name) ? np->full_name : "<no-node>";
 }
 
+static inline const char *dt_node_name(const struct dt_device_node *np)
+{
+    return (np && np->name) ? np->name : "<no-node>";
+}
+
+static inline bool_t
+dt_device_type_is_equal(const struct dt_device_node *device,
+                        const char *type)
+{
+    return !dt_node_cmp(device->type, type);
+}
+
+static inline void dt_device_set_used_by(struct dt_device_node *device,
+                                         domid_t used_by)
+{
+    /* TODO: children must inherit to the used_by thing */
+    device->used_by = used_by;
+}
+
+static inline domid_t dt_device_used_by(const struct dt_device_node *device)
+{
+    return device->used_by;
+}
+
+/**
+ * dt_find_compatible_node - Find a node based on type and one of the
+ *                           tokens in its "compatible" property
+ * @from: The node to start searching from or NULL, the node
+ *          you pass will not be searched, only the next one
+ *          will; typically, you pass what the previous call
+ *          returned.
+ * @type: The type string to match "device_type" or NULL to ignore
+ * @compatible: The string to match to one of the tokens in the device
+ *          "compatible" list.
+ *
+ * Returns a node pointer.
+ */
+struct dt_device_node *dt_find_compatible_node(struct dt_device_node *from,
+                                               const char *type,
+                                               const char *compatible);
+
 /**
  * Find a property with a given name for a given node
  * and return the value.
@@ -169,10 +224,75 @@ const void *dt_get_property(const struct dt_device_node *np,
                             const char *name, u32 *lenp);
 
 /**
+ * Checks if the given "compat" string matches one of the strings in
+ * the device's "compatible" property
+ */
+bool_t dt_device_is_compatible(const struct dt_device_node *device,
+                               const char *compat);
+
+/**
+ * dt_machine_is_compatible - Test root of device tree for a given compatible value
+ * @compat: compatible string to look for in root node's compatible property.
+ *
+ * Returns true if the root node has the given value in its
+ * compatible property.
+ */
+bool_t dt_machine_is_compatible(const char *compat);
+
+/**
+ * dt_find_node_by_name - Find a node by its "name" property
+ * @from: The node to start searching from or NULL, the node
+ * you pass will not be searched, only the next one
+ *  will; typically, you pass what the previous call
+ *  returned. of_node_put() will be called on it
+ * @name: The name string to match against
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct dt_device_node *dt_find_node_by_name(struct dt_device_node *node,
+                                            const char *name);
+
+/**
+ * df_find_node_by_alias - Find a node matching an alias
+ * @alias: The alias to match
+ *
+ * Returns a node pointer.
+ */
+struct dt_device_node *dt_find_node_by_alias(const char *alias);
+
+/**
  * dt_find_node_by_path - Find a node matching a full DT path
  * @path: The full path to match
  *
  * Returns a node pointer.
  */
 struct dt_device_node *dt_find_node_by_path(const char *path);
+
+/**
+ * dt_get_parent - Get a node's parent if any
+ * @node: Node to get parent
+ *
+ * Returns a node pointer.
+ */
+const struct dt_device_node *dt_get_parent(const struct dt_device_node *node);
+
+/**
+ * dt_n_size_cells - Helper to retrieve the number of cell for the size
+ * @np: node to get the value
+ *
+ * This function retrieves for a give device-tree node the number of
+ * cell for the size field.
+ */
+int dt_n_size_cells(const struct dt_device_node *np);
+
+/**
+ * dt_n_addr_cells - Helper to retrieve the number of cell for the address
+ * @np: node to get the value
+ *
+ * This function retrieves for a give device-tree node the number of
+ * cell for the address field.
+ */
+int dt_n_addr_cells(const struct dt_device_node *np);
+
 #endif
-- 
Julien Grall

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

* [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (7 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 08/33] xen/arm: Add helpers to use the " Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:23   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
                   ` (24 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/common/device_tree.c      |  343 +++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/device_tree.h |   22 +++
 2 files changed, 365 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 449c332..8d37018 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -62,10 +62,38 @@ static void (*dt_printk)(const char *fmt, ...) = early_printk;
 
 #ifdef DEBUG_DT
 # define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
+static void dt_dump_addr(const char *s, const __be32 *addr, int na)
+{
+    dt_dprintk("%s", s);
+    while ( na-- )
+        dt_dprintk(" %08x", be32_to_cpu(*(addr++)));
+    dt_dprintk("\n");
+}
 #else
 # define dt_dprintk(fmt, args...) do {} while ( 0 )
+static void dt_dump_addr(const char *s, const __be32 *addr, int na) { }
 #endif
 
+#define DT_BAD_ADDR ((u64)-1)
+
+/* Max address size we deal with */
+#define DT_MAX_ADDR_CELLS 4
+#define DT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= DT_MAX_ADDR_CELLS)
+#define DT_CHECK_COUNTS(na, ns) (DT_CHECK_ADDR_COUNT(na) && (ns) > 0)
+
+/* Callbacks for bus specific translators */
+struct dt_bus
+{
+    const char *name;
+    const char *addresses;
+    int (*match)(const struct dt_device_node *parent);
+    void (*count_cells)(const struct dt_device_node *child,
+                        int *addrc, int *sizec);
+    u64	(*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
+	int (*translate)(__be32 *addr, u64 offset, int na);
+	unsigned int (*get_flags)(const __be32 *addr);
+};
+
 bool_t device_tree_node_matches(const void *fdt, int node, const char *match)
 {
     const char *name;
@@ -707,6 +735,321 @@ int dt_n_size_cells(const struct dt_device_node *np)
     return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
 }
 
+/*
+ * Default translator (generic bus)
+ */
+static void dt_bus_default_count_cells(const struct dt_device_node *dev,
+                                int *addrc, int *sizec)
+{
+    if ( addrc )
+        *addrc = dt_n_addr_cells(dev);
+    if ( sizec )
+        *sizec = dt_n_size_cells(dev);
+}
+
+static u64 dt_bus_default_map(__be32 *addr, const __be32 *range,
+                              int na, int ns, int pna)
+{
+    u64 cp, s, da;
+
+    cp = dt_read_number(range, na);
+    s = dt_read_number(range + na + pna, ns);
+    da = dt_read_number(addr, na);
+
+    dt_dprintk("DT: default map, cp=%llx, s=%llx, da=%llx\n",
+               (unsigned long long)cp, (unsigned long long)s,
+               (unsigned long long)da);
+
+    /*
+     * If the number of address cells is larger than 2 we assume the
+     * mapping doesn't specify a physical address. Rather, the address
+     * specifies an identifier that must match exactly.
+     */
+    if ( na > 2 && memcmp(range, addr, na * 4) != 0 )
+        return DT_BAD_ADDR;
+
+    if ( da < cp || da >= (cp + s) )
+        return DT_BAD_ADDR;
+    return da - cp;
+}
+
+static int dt_bus_default_translate(__be32 *addr, u64 offset, int na)
+{
+    u64 a = dt_read_number(addr, na);
+
+    memset(addr, 0, na * 4);
+    a += offset;
+    if ( na > 1 )
+        addr[na - 2] = cpu_to_be32(a >> 32);
+    addr[na - 1] = cpu_to_be32(a & 0xffffffffu);
+
+    return 0;
+}
+static unsigned int dt_bus_default_get_flags(const __be32 *addr)
+{
+    /* TODO: Return the type of memory (device, ...) for caching
+     * attribute during mapping */
+    return 0;
+}
+
+/*
+ * Array of bus specific translators
+ */
+static const struct dt_bus dt_busses[] =
+{
+    /* Default */
+    {
+        .name = "default",
+        .addresses = "reg",
+        .match = NULL,
+        .count_cells = dt_bus_default_count_cells,
+        .map = dt_bus_default_map,
+        .translate = dt_bus_default_translate,
+        .get_flags = dt_bus_default_get_flags,
+    },
+};
+
+static const struct dt_bus *dt_match_bus(const struct dt_device_node *np)
+{
+    int i;
+
+    for ( i = 0; i < ARRAY_SIZE(dt_busses); i++ )
+        if ( !dt_busses[i].match || dt_busses[i].match(np) )
+            return &dt_busses[i];
+    BUG();
+
+    return NULL;
+}
+
+static const __be32 *dt_get_address(const struct dt_device_node *dev,
+                                    int index, u64 *size,
+                                    unsigned int *flags)
+{
+    const __be32 *prop;
+    u32 psize;
+    const struct dt_device_node *parent;
+    const struct dt_bus *bus;
+    int onesize, i, na, ns;
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        return NULL;
+    bus = dt_match_bus(parent);
+    bus->count_cells(dev, &na, &ns);
+
+    if ( !DT_CHECK_ADDR_COUNT(na) )
+        return NULL;
+
+    /* Get "reg" or "assigned-addresses" property */
+    prop = dt_get_property(dev, bus->addresses, &psize);
+    if ( prop == NULL )
+        return NULL;
+    psize /= 4;
+
+    onesize = na + ns;
+    for ( i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++ )
+    {
+        if ( i == index )
+        {
+            if ( size )
+                *size = dt_read_number(prop + na, ns);
+            if ( flags )
+                *flags = bus->get_flags(prop);
+            return prop;
+        }
+    }
+    return NULL;
+}
+
+static int dt_translate_one(const struct dt_device_node *parent,
+                            const struct dt_bus *bus,
+                            const struct dt_bus *pbus,
+                            __be32 *addr, int na, int ns,
+                            int pna, const char *rprop)
+{
+    const __be32 *ranges;
+    unsigned int rlen;
+    int rone;
+    u64 offset = DT_BAD_ADDR;
+
+    ranges = dt_get_property(parent, rprop, &rlen);
+    if ( ranges == NULL )
+    {
+		dt_printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
+		return 1;
+	}
+    if ( ranges == NULL || rlen == 0 )
+    {
+        offset = dt_read_number(addr, na);
+        memset(addr, 0, pna * 4);
+        dt_dprintk("DT: empty ranges; 1:1 translation\n");
+        goto finish;
+    }
+
+    dt_dprintk("DT: walking ranges...\n");
+
+    /* Now walk through the ranges */
+    rlen /= 4;
+    rone = na + pna + ns;
+    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
+    {
+        offset = bus->map(addr, ranges, na, ns, pna);
+        if ( offset != DT_BAD_ADDR )
+            break;
+	}
+    if ( offset == DT_BAD_ADDR )
+    {
+        dt_dprintk("DT: not found !\n");
+        return 1;
+    }
+    memcpy(addr, ranges + na, 4 * pna);
+
+finish:
+    dt_dump_addr("DT: parent translation for:", addr, pna);
+    dt_dprintk("DT: with offset: %llx\n", (unsigned long long)offset);
+
+    /* Translate it into parent bus space */
+    return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+static u64 __dt_translate_address(const struct dt_device_node *dev,
+                                  const __be32 *in_addr, const char *rprop)
+{
+    const struct dt_device_node *parent = NULL;
+    const struct dt_bus *bus, *pbus;
+    __be32 addr[DT_MAX_ADDR_CELLS];
+    int na, ns, pna, pns;
+    u64 result = DT_BAD_ADDR;
+
+	dt_dprintk("DT: ** translation for device %s **\n", dev->full_name);
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        goto bail;
+    bus = dt_match_bus(parent);
+
+    /* Count address cells & copy address locally */
+    bus->count_cells(dev, &na, &ns);
+    if ( !DT_CHECK_COUNTS(na, ns) )
+    {
+        dt_printk(XENLOG_ERR "dt_parse: Bad cell count for %s\n",
+                  dev->full_name);
+        goto bail;
+    }
+    memcpy(addr, in_addr, na * 4);
+
+    dt_dprintk("DT: bus is %s (na=%d, ns=%d) on %s\n",
+               bus->name, na, ns, parent->full_name);
+	dt_dump_addr("DT: translating address:", addr, na);
+
+    /* Translate */
+    for ( ;; )
+    {
+		/* Switch to parent bus */
+        dev = parent;
+        parent = dt_get_parent(dev);
+
+        /* If root, we have finished */
+        if ( parent == NULL )
+        {
+            dt_dprintk("DT: reached root node\n");
+            result = dt_read_number(addr, na);
+            break;
+        }
+
+        /* Get new parent bus and counts */
+        pbus = dt_match_bus(parent);
+        pbus->count_cells(dev, &pna, &pns);
+        if ( !DT_CHECK_COUNTS(pna, pns) )
+        {
+            printk(XENLOG_ERR "dt_parse: Bad cell count for %s\n",
+                   dev->full_name);
+            break;
+        }
+
+        dt_dprintk("DT: parent bus is %s (na=%d, ns=%d) on %s\n",
+                   pbus->name, pna, pns, parent->full_name);
+
+        /* Apply bus translation */
+        if ( dt_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop) )
+            break;
+
+        /* Complete the move up one level */
+        na = pna;
+        ns = pns;
+        bus = pbus;
+
+        dt_dump_addr("DT: one level translation:", addr, na);
+	}
+
+bail:
+	return result;
+}
+
+/* dt_device_address - Translate device tree address and return it */
+int dt_device_get_address(const struct dt_device_node *dev, int index,
+                          u64 *addr, u64 *size)
+{
+    const __be32 *addrp;
+    unsigned int flags;
+
+    addrp = dt_get_address(dev, index, size, &flags);
+    if ( addrp == NULL )
+        return -EINVAL;
+
+    if ( !addr )
+        return -EINVAL;
+
+    *addr = __dt_translate_address(dev, addrp, "ranges");
+
+    if ( *addr == DT_BAD_ADDR )
+        return -EINVAL;
+
+    return 0;
+}
+
+unsigned int dt_number_of_address(const struct dt_device_node *dev)
+{
+    const __be32 *prop;
+    u32 psize;
+    const struct dt_device_node *parent;
+    const struct dt_bus *bus;
+    int onesize, na, ns;
+
+    /* Get parent & match bus type */
+    parent = dt_get_parent(dev);
+    if ( parent == NULL )
+        return 0;
+
+    bus = dt_match_bus(parent);
+    bus->count_cells(dev, &na, &ns);
+
+    if ( !DT_CHECK_COUNTS(na, ns) )
+        return 0;
+
+    /* Get "reg" or "assigned-addresses" property */
+    prop = dt_get_property(dev, bus->addresses, &psize);
+    if ( prop == NULL )
+        return 0;
+
+    psize /= 4;
+    onesize = na + ns;
+
+    return (psize / onesize);
+}
+
 /**
  * unflatten_dt_node - Alloc and populate a device_node from the flat tree
  * @fdt: The parent device tree blob
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 879b75d..ce34ba5 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -278,6 +278,28 @@ struct dt_device_node *dt_find_node_by_path(const char *path);
 const struct dt_device_node *dt_get_parent(const struct dt_device_node *node);
 
 /**
+ * dt_device_get_address - Resolve an address for a device
+ * @device: the device whose address is to be resolved
+ * @index: index of the addres to resolve
+ * @addr: address filled by this function
+ * @size: size filled by this function
+ *
+ * This function resolves an address, walking the tree, for a give
+ * device-tree node. It returns 0 on success.
+ */
+int dt_device_get_address(const struct dt_device_node *dev, int index,
+                          u64 *addr, u64 *size);
+
+/**
+ * dt_number_of_address - Get the number of addresse for a device
+ * @device: the device whose number of address is to be retrieved
+ *
+ * Return the number of address for this device or 0 if there is no
+ * address or an error occured/
+ */
+unsigned int dt_number_of_address(const struct dt_device_node *device);
+
+/**
  * dt_n_size_cells - Helper to retrieve the number of cell for the size
  * @np: node to get the value
  *
-- 
Julien Grall

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

* [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description from the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (8 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from " Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:30   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq Julien Grall
                   ` (23 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Move interrupt type from xen/irq.h to xen/device_tree.h
    - Prefix all defines by DT_
---
 xen/common/device_tree.c      |  362 +++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/device_tree.h |  130 +++++++++++++++
 2 files changed, 492 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 8d37018..e5ff779 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -27,8 +27,11 @@
 
 struct dt_early_info __initdata early_info;
 void *device_tree_flattened;
+dt_irq_xlate_func dt_irq_xlate;
 /* Host device tree */
 struct dt_device_node *dt_host;
+/* Interrupt controller node*/
+const struct dt_device_node *dt_interrupt_controller;
 
 /**
  * struct dt_alias_prop - Alias property in 'aliases' node
@@ -1020,6 +1023,81 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
     return 0;
 }
 
+/**
+ * dt_find_node_by_phandle - Find a node given a phandle
+ * @handle:	phandle of the node to find
+ *
+ * Returns a node pointer.
+ */
+static const struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
+{
+    const struct dt_device_node *np;
+
+    for_each_device_node(dt_host, np)
+        if ( np->phandle == handle )
+            break;
+
+    return np;
+}
+
+/**
+ * dt_irq_find_parent - Given a device node, find its interrupt parent node
+ * @child: pointer to device node
+ *
+ * Returns a pointer to the interrupt parent node, or NULL if the interrupt
+ * parent could not be determined.
+ */
+static const struct dt_device_node *
+dt_irq_find_parent(const struct dt_device_node *child)
+{
+    const struct dt_device_node *p;
+    const __be32 *parp;
+
+    do
+    {
+        parp = dt_get_property(child, "interrupt-parent", NULL);
+        if ( parp == NULL )
+            p = dt_get_parent(child);
+        else
+            p = dt_find_node_by_phandle(be32_to_cpup(parp));
+        child = p;
+    } while ( p && dt_get_property(p, "#interrupt-cells", NULL) == NULL );
+
+    return p;
+}
+
+unsigned int dt_number_of_irq(const struct dt_device_node *device)
+{
+    const struct dt_device_node *p;
+    const __be32 *intspec, *tmp;
+    u32 intsize, intlen;
+
+    dt_dprintk("dt_irq_number: dev=%s\n", device->full_name);
+
+    /* Get the interrupts property */
+    intspec = dt_get_property(device, "interrupts", &intlen);
+    if ( intspec == NULL )
+        return 0;
+    intlen /= sizeof(*intspec);
+
+    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+
+    /* Look for the interrupt parent. */
+    p = dt_irq_find_parent(device);
+    if ( p == NULL )
+        return 0;
+
+    /* Get size of interrupt specifier */
+    tmp = dt_get_property(p, "#interrupt-cells", NULL);
+    if ( tmp == NULL )
+        return 0;
+    intsize = be32_to_cpu(*tmp);
+
+    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
+
+    return (intlen / intsize);
+}
+
 unsigned int dt_number_of_address(const struct dt_device_node *dev)
 {
     const __be32 *prop;
@@ -1051,6 +1129,274 @@ unsigned int dt_number_of_address(const struct dt_device_node *dev)
 }
 
 /**
+ * dt_irq_map_raw - Low level interrupt tree parsing
+ * @parent:     the device interrupt parent
+ * @intspec:    interrupt specifier ("interrupts" property of the device)
+ * @ointsize:   size of the passed in interrupt specifier
+ * @addr:       address specifier (start of "reg" property of the device)
+ * @oirq:       structure dt_raw_irq filled by this function
+ *
+ * Returns 0 on success and a negative number on error
+ *
+ * This function is a low-level interrupt tree walking function. It
+ * can be used to do a partial walk with synthetized reg and interrupts
+ * properties, for example when resolving PCI interrupts when no device
+ * node exist for the parent.
+ */
+static int dt_irq_map_raw(const struct dt_device_node *parent,
+                          const __be32 *intspec, u32 ointsize,
+                          const __be32 *addr,
+                          struct dt_raw_irq *oirq)
+{
+    const struct dt_device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+    const __be32 *tmp, *imap, *imask;
+    u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+    u32 imaplen;
+    int match, i;
+
+    dt_dprintk("dt_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+               parent->full_name, be32_to_cpup(intspec),
+               be32_to_cpup(intspec + 1), ointsize);
+
+    ipar = parent;
+
+    /* First get the #interrupt-cells property of the current cursor
+     * that tells us how to interpret the passed-in intspec. If there
+     * is none, we are nice and just walk up the tree
+     */
+    do {
+        tmp = dt_get_property(ipar, "#interrupt-cells", NULL);
+        if ( tmp != NULL )
+        {
+            intsize = be32_to_cpu(*tmp);
+            break;
+        }
+        tnode = ipar;
+        ipar = dt_irq_find_parent(ipar);
+    } while ( ipar );
+    if ( ipar == NULL )
+    {
+        dt_dprintk(" -> no parent found !\n");
+        goto fail;
+    }
+
+    dt_dprintk("dt_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
+
+    if ( ointsize != intsize )
+        return -EINVAL;
+
+    /* Look for this #address-cells. We have to implement the old linux
+     * trick of looking for the parent here as some device-trees rely on it
+     */
+    old = ipar;
+    do {
+        tmp = dt_get_property(old, "#address-cells", NULL);
+        tnode = dt_get_parent(old);
+        old = tnode;
+    } while ( old && tmp == NULL );
+
+    old = NULL;
+    addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
+
+    dt_dprintk(" -> addrsize=%d\n", addrsize);
+
+    /* Now start the actual "proper" walk of the interrupt tree */
+    while ( ipar != NULL )
+    {
+        /* Now check if cursor is an interrupt-controller and if it is
+         * then we are done
+         */
+        if ( dt_get_property(ipar, "interrupt-controller", NULL) != NULL )
+        {
+            dt_dprintk(" -> got it !\n");
+            if ( intsize > DT_MAX_IRQ_SPEC )
+            {
+                dt_dprintk(" -> intsize(%u) greater than DT_MAX_IRQ_SPEC(%u)\n",
+                           intsize, DT_MAX_IRQ_SPEC);
+                goto fail;
+            }
+            for ( i = 0; i < intsize; i++ )
+                oirq->specifier[i] = dt_read_number(intspec + i, 1);
+            oirq->size = intsize;
+            oirq->controller = ipar;
+            return 0;
+        }
+
+        /* Now look for an interrupt-map */
+        imap = dt_get_property(ipar, "interrupt-map", &imaplen);
+        /* No interrupt map, check for an interrupt parent */
+        if ( imap == NULL )
+        {
+            dt_dprintk(" -> no map, getting parent\n");
+            newpar = dt_irq_find_parent(ipar);
+            goto skiplevel;
+        }
+        imaplen /= sizeof(u32);
+
+        /* Look for a mask */
+        imask = dt_get_property(ipar, "interrupt-map-mask", NULL);
+
+        /* If we were passed no "reg" property and we attempt to parse
+         * an interrupt-map, then #address-cells must be 0.
+         * Fail if it's not.
+         */
+        if ( addr == NULL && addrsize != 0 )
+        {
+            dt_dprintk(" -> no reg passed in when needed !\n");
+            goto fail;
+        }
+
+        /* Parse interrupt-map */
+        match = 0;
+        while ( imaplen > (addrsize + intsize + 1) && !match )
+        {
+            /* Compare specifiers */
+            match = 1;
+            for ( i = 0; i < addrsize && match; ++i )
+            {
+                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
+                match = ((addr[i] ^ imap[i]) & mask) == 0;
+            }
+            for ( ; i < (addrsize + intsize) && match; ++i )
+            {
+                __be32 mask = imask ? imask[i] : cpu_to_be32(0xffffffffu);
+                match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
+            }
+            imap += addrsize + intsize;
+            imaplen -= addrsize + intsize;
+
+            dt_dprintk(" -> match=%d (imaplen=%d)\n", match, imaplen);
+
+            /* Get the interrupt parent */
+            newpar = dt_find_node_by_phandle(be32_to_cpup(imap));
+            imap++;
+            --imaplen;
+
+            /* Check if not found */
+            if ( newpar == NULL )
+            {
+                dt_dprintk(" -> imap parent not found !\n");
+                goto fail;
+            }
+
+            /* Get #interrupt-cells and #address-cells of new
+             * parent
+             */
+            tmp = dt_get_property(newpar, "#interrupt-cells", NULL);
+            if ( tmp == NULL )
+            {
+                dt_dprintk(" -> parent lacks #interrupt-cells!\n");
+                goto fail;
+            }
+            newintsize = be32_to_cpu(*tmp);
+            tmp = dt_get_property(newpar, "#address-cells", NULL);
+            newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
+
+            dt_dprintk(" -> newintsize=%d, newaddrsize=%d\n",
+                       newintsize, newaddrsize);
+
+            /* Check for malformed properties */
+            if ( imaplen < (newaddrsize + newintsize) )
+                goto fail;
+
+            imap += newaddrsize + newintsize;
+            imaplen -= newaddrsize + newintsize;
+
+            dt_dprintk(" -> imaplen=%d\n", imaplen);
+        }
+        if ( !match )
+            goto fail;
+
+        old = newpar;
+        addrsize = newaddrsize;
+        intsize = newintsize;
+        intspec = imap - intsize;
+        addr = intspec - addrsize;
+
+    skiplevel:
+        /* Iterate again with new parent */
+        dt_dprintk(" -> new parent: %s\n", dt_node_full_name(newpar));
+        ipar = newpar;
+        newpar = NULL;
+    }
+fail:
+    return -EINVAL;
+}
+
+int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
+                          struct dt_raw_irq *out_irq)
+{
+    const struct dt_device_node *p;
+    const __be32 *intspec, *tmp, *addr;
+    u32 intsize, intlen;
+    int res = -EINVAL;
+
+    dt_dprintk("dt_device_get_raw_irq: dev=%s, index=%d\n",
+               device->full_name, index);
+
+    /* Get the interrupts property */
+    intspec = dt_get_property(device, "interrupts", &intlen);
+    if ( intspec == NULL )
+        return -EINVAL;
+    intlen /= sizeof(*intspec);
+
+    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+
+    /* Get the reg property (if any) */
+    addr = dt_get_property(device, "reg", NULL);
+
+    /* Look for the interrupt parent. */
+    p = dt_irq_find_parent(device);
+    if ( p == NULL )
+        return -EINVAL;
+
+    /* Get size of interrupt specifier */
+    tmp = dt_get_property(p, "#interrupt-cells", NULL);
+    if ( tmp == NULL )
+        goto out;
+    intsize = be32_to_cpu(*tmp);
+
+    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
+
+    /* Check index */
+    if ( (index + 1) * intsize > intlen )
+        goto out;
+
+    /* Get new specifier and map it */
+    res = dt_irq_map_raw(p, intspec + index * intsize, intsize,
+                         addr, out_irq);
+    if ( res )
+        goto out;
+out:
+    return res;
+}
+
+int dt_irq_translate(const struct dt_raw_irq *raw,
+                     struct dt_irq *out_irq)
+{
+    ASSERT(dt_irq_xlate != NULL);
+
+    /* TODO: Retrieve the right irq_xlate. This is only work for the gic */
+
+    return dt_irq_xlate(raw->specifier, raw->size,
+                        &out_irq->irq, &out_irq->type);
+}
+
+int dt_device_get_irq(const struct dt_device_node *device, int index,
+                      struct dt_irq *out_irq)
+{
+    struct dt_raw_irq raw;
+    int res;
+
+    res = dt_device_get_raw_irq(device, index, &raw);
+
+    if ( res )
+        return res;
+
+    return dt_irq_translate(&raw, out_irq);
+}
+
+/**
  * unflatten_dt_node - Alloc and populate a device_node from the flat tree
  * @fdt: The parent device tree blob
  * @mem: Memory chunk to use for allocating device nodes and properties
@@ -1392,6 +1738,22 @@ static void __init dt_alias_scan(void)
     }
 }
 
+struct dt_device_node * __init dt_find_interrupt_controller(const char *compat)
+{
+    struct dt_device_node *np = NULL;
+
+    while ( (np = dt_find_compatible_node(np, NULL, compat)) )
+    {
+        if ( !dt_find_property(np, "interrupt-controller", NULL) )
+            continue;
+
+        if ( dt_get_parent(np) )
+            break;
+    }
+
+    return np;
+}
+
 void __init dt_unflatten_host_device_tree(void)
 {
     __unflatten_device_tree(device_tree_flattened, &dt_host);
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index ce34ba5..bf873d9 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -101,6 +101,67 @@ struct dt_device_node {
 
 };
 
+/**
+ * IRQ line type.
+ *
+ * DT_IRQ_TYPE_NONE            - default, unspecified type
+ * DT_IRQ_TYPE_EDGE_RISING     - rising edge triggered
+ * DT_IRQ_TYPE_EDGE_FALLING    - falling edge triggered
+ * DT_IRQ_TYPE_EDGE_BOTH       - rising and falling edge triggered
+ * DT_IRQ_TYPE_LEVEL_HIGH      - high level triggered
+ * DT_IRQ_TYPE_LEVEL_LOW       - low level triggered
+ * DT_IRQ_TYPE_LEVEL_MASK      - Mask to filter out the level bits
+ * DT_IRQ_TYPE_SENSE_MASK      - Mask for all the above bits
+ */
+#define DT_IRQ_TYPE_NONE           0x00000000
+#define DT_IRQ_TYPE_EDGE_RISING    0x00000001
+#define DT_IRQ_TYPE_EDGE_FALLING   0x00000002
+#define DT_IRQ_TYPE_EDGE_BOTH                           \
+    (DT_IRQ_TYPE_EDGE_FALLING | DT_IRQ_TYPE_EDGE_RISING)
+#define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
+#define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
+#define DT_IRQ_TYPE_LEVEL_MASK                          \
+    (DT_IRQ_TYPE_LEVEL_LOW | DT_IRQ_TYPE_LEVEL_HIGH)
+#define DT_IRQ_TYPE_SENSE_MASK     0x0000000f
+
+/**
+ * dt_irq - describe an IRQ in the device tree
+ * @irq: IRQ number
+ * @type: IRQ type (see DT_IRQ_TYPE_*)
+ *
+ * This structure is returned when an interrupt is mapped.
+ */
+struct dt_irq {
+    unsigned int irq;
+    unsigned int type;
+};
+
+/* If type == DT_IRQ_TYPE_NONE, assume we use level triggered */
+static inline bool_t dt_irq_is_level_trigger(const struct dt_irq *irq)
+{
+    unsigned int type = irq->type;
+
+    return (type & DT_IRQ_TYPE_LEVEL_MASK) || (type == DT_IRQ_TYPE_NONE);
+}
+
+/**
+ * dt_raw_irq - container for device_node/irq_specifier for an irq controller
+ * @controller: pointer to interrupt controller deivce tree node
+ * @size: size of interrupt specifier
+ * @specifier: array of cells @size long specifing the specific interrupt
+ *
+ * This structure is returned when an interrupt is mapped but not translated.
+ */
+#define DT_MAX_IRQ_SPEC     4 /* We handle specifiers of at most 4 cells */
+struct dt_raw_irq {
+    const struct dt_device_node *controller;
+    u32 size;
+    u32 specifier[DT_MAX_IRQ_SPEC];
+};
+
+#define dt_irq(irq) ((irq)->irq)
+#define dt_irq_flags(irq) ((irq)->flags)
+
 typedef int (*device_tree_node_func)(const void *fdt,
                                      int node, const char *name, int depth,
                                      u32 address_cells, u32 size_cells,
@@ -142,11 +203,40 @@ void __init dt_unflatten_host_device_tree(void);
 void __init dt_switch_to_printk(void);
 
 /**
+ * IRQ translation callback
+ * TODO: For the moment we assume that we only have ONE
+ * interrupt-controller.
+ */
+typedef int (*dt_irq_xlate_func)(const u32 *intspec, unsigned int intsize,
+                                 unsigned int *out_hwirq,
+                                 unsigned int *out_type);
+extern dt_irq_xlate_func dt_irq_xlate;
+
+/**
  * Host device tree
  * DO NOT modify it!
  */
 extern struct dt_device_node *dt_host;
 
+/**
+ * Primary interrupt controller
+ * Exynos SOC has an interrupt combiner, interrupt has no physical
+ * meaning when it's not connected to the primary controller.
+ * We will only map interrupt whose parent controller is
+ * dt_interrupt_controller. It should always be a GIC.
+ * TODO: Handle multiple GIC
+ */
+extern const struct dt_device_node *dt_interrupt_controller;
+
+/**
+ * Find the interrupt controller
+ * For the moment we handle only one interrupt controller: the first
+ * one without parent and is compatible with the string "compat".
+ *
+ * If found, return the interrupt controller device node.
+ */
+struct dt_device_node * __init dt_find_interrupt_controller(const char *compat);
+
 #define dt_node_cmp(s1, s2) strcmp((s1), (s2))
 #define dt_compat_cmp(s1, s2, l) strnicmp((s1), (s2), l)
 
@@ -291,6 +381,15 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
                           u64 *addr, u64 *size);
 
 /**
+ * dt_number_of_irq - Get the number of IRQ for a device
+ * @device: the device whose number of interrupt is to be retrieved
+ *
+ * Return the number of irq for this device or 0 if there is no
+ * interrupt or an error occurred.
+ */
+unsigned int dt_number_of_irq(const struct dt_device_node *device);
+
+/**
  * dt_number_of_address - Get the number of addresse for a device
  * @device: the device whose number of address is to be retrieved
  *
@@ -300,6 +399,37 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
 unsigned int dt_number_of_address(const struct dt_device_node *device);
 
 /**
+ * dt_device_get_irq - Resolve an interrupt for a device
+ * @device: the device whose interrupt is to be resolved
+ * @index: index of the interrupt to resolve
+ * @out_irq: structure dt_irq filled by this function
+ *
+ * This function resolves an interrupt, walking the tree, for a given
+ * device-tree node. It's the high level pendant to dt_device_get_raw_irq().
+ */
+int dt_device_get_irq(const struct dt_device_node *device, int index,
+                      struct dt_irq *irq);
+
+/**
+ * dt_device_get_raw_irq - Resolve an interrupt for a device without translation
+ * @device: the device whose interrupt is to be resolved
+ * @index: index of the interrupt to resolve
+ * @out_irq: structure dt_raw_irq filled by this function
+ *
+ * This function resolves an interrupt for a device, no translation is
+ * made. dt_irq_translate can be called after.
+ */
+int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
+                          struct dt_raw_irq *irq);
+
+/**
+ * dt_irq_transalte - Translate an irq
+ * @raw: IRQ to translate (raw format)
+ * @out_irq: structure dt_irq filled by this function
+ */
+int dt_irq_translate(const struct dt_raw_irq *raw, struct dt_irq *out_irq);
+
+/**
  * dt_n_size_cells - Helper to retrieve the number of cell for the size
  * @np: node to get the value
  *
-- 
Julien Grall

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

* [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (9 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:31   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate Julien Grall
                   ` (22 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This function routes an IRQ to a specific cpu. The IRQ is retrieved via
the device tree.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use dt_irq_is_level_trigger instead of the old name irq_is_level_trigger
---
 xen/arch/arm/gic.c        |   11 +++++++++++
 xen/include/asm-arm/gic.h |    5 +++++
 2 files changed, 16 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 6d71aae..b9fbe3d 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -238,6 +238,17 @@ static int gic_route_irq(unsigned int irq, bool_t level,
     return 0;
 }
 
+/* Program the GIC to route an interrupt with a dt_irq */
+void gic_route_dt_irq(const struct dt_irq *irq, unsigned int cpu_mask,
+                      unsigned int priority)
+{
+    bool_t level;
+
+    level = dt_irq_is_level_trigger(irq);
+
+    gic_route_irq(irq->irq, level, cpu_mask, priority);
+}
+
 static void __init gic_dist_init(void)
 {
     uint32_t type;
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 3efb2b5..78dd21a 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -133,6 +133,8 @@
 #define VGIC_IRQ_EVTCHN_CALLBACK 31
 
 #ifndef __ASSEMBLY__
+#include <xen/device_tree.h>
+
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
 
@@ -142,6 +144,9 @@ extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq,int virtual);
 extern void vgic_clear_pending_irqs(struct vcpu *v);
 extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
 
+/* Program the GIC to route an interrupt with a dt_irq */
+extern void gic_route_dt_irq(const struct dt_irq *irq, unsigned int cpu_mask,
+                             unsigned int priority);
 extern void gic_route_ppis(void);
 extern void gic_route_spis(void);
 
-- 
Julien Grall

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

* [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (10 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:32   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq Julien Grall
                   ` (21 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This function translates an interrupt specifier to an IRQ number and IRQ
type (ie: level trigger, edge trigger,...). It's GIC specific.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use DT_IRQ_TYPE_SENSE_MASK instead of IRQ_TYPE_SENSE_MASK
---
 xen/arch/arm/gic.c        |   20 ++++++++++++++++++++
 xen/arch/arm/setup.c      |    1 +
 xen/include/asm-arm/gic.h |    4 ++++
 3 files changed, 25 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index b9fbe3d..78fc144 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -329,6 +329,26 @@ static void __cpuinit gic_hyp_disable(void)
     GICH[GICH_HCR] = 0;
 }
 
+int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
+                  unsigned int *out_hwirq,
+                  unsigned int *out_type)
+{
+    if ( intsize < 3 )
+        return -EINVAL;
+
+    /* Get the interrupt number and add 16 to skip over SGIs */
+    *out_hwirq = intspec[1] + 16;
+
+    /* For SPIs, we need to add 16 more to get the GIC irq ID number */
+    if ( !intspec[0] )
+        *out_hwirq += 16;
+
+    if ( out_type )
+        *out_type = intspec[2] & DT_IRQ_TYPE_SENSE_MASK;
+
+    return 0;
+}
+
 /* Set up the GIC */
 void __init gic_init(void)
 {
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 07c0444..e4228f7 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -430,6 +430,7 @@ void __init start_xen(unsigned long boot_phys_offset,
     setup_mm(fdt_paddr, fdt_size);
 
     dt_unflatten_host_device_tree();
+    dt_irq_xlate = gic_irq_xlate;
 
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 78dd21a..6ff217c 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -189,6 +189,10 @@ extern void send_SGI_allbutself(enum gic_sgi sgi);
 /* print useful debug info */
 extern void gic_dump_info(struct vcpu *v);
 
+/* IRQ translation function for the device tree */
+int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
+                  unsigned int *out_hwirq, unsigned int *out_type);
+
 #endif /* __ASSEMBLY__ */
 #endif
 
-- 
Julien Grall

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

* [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (11 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:35   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 14/33] xen/arm: Introduce request_dt_irq Julien Grall
                   ` (20 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This function will replace setup_irq in later patch. It takes a dt_irq
as first argument instead of an unsigned int.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/gic.c        |    5 +++++
 xen/include/asm-arm/irq.h |    4 ++++
 2 files changed, 9 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 78fc144..1efa9a3 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -521,6 +521,11 @@ static int __setup_irq(struct irq_desc *desc, unsigned int irq,
     return 0;
 }
 
+int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
+{
+    return setup_irq(irq->irq, new);
+}
+
 int __init setup_irq(unsigned int irq, struct irqaction *new)
 {
     int rc;
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 9fc008c..47399ca 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -2,6 +2,7 @@
 #define _ASM_HW_IRQ_H
 
 #include <xen/config.h>
+#include <xen/device_tree.h>
 
 #define NR_VECTORS 256 /* XXX */
 
@@ -25,6 +26,7 @@ struct irq_cfg {
 #define nr_static_irqs NR_IRQS
 
 struct irq_desc;
+struct irqaction;
 
 struct irq_desc *__irq_to_desc(int irq);
 
@@ -37,6 +39,8 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
 void init_IRQ(void);
 void init_secondary_IRQ(void);
 
+int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
+
 #endif /* _ASM_HW_IRQ_H */
 /*
  * Local variables:
-- 
Julien Grall

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

* [PATCH V2 14/33] xen/arm: Introduce request_dt_irq
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (12 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:41   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
                   ` (19 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This function will replace request_irq in a later patch. It takes a dt_irq
as first argument instead of an unsigned int.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/irq.c        |    7 +++++++
 xen/include/asm-arm/irq.h |    4 ++++
 2 files changed, 11 insertions(+)

diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 8c96a0a..0b7a75f 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -93,6 +93,13 @@ void __cpuinit init_secondary_IRQ(void)
     BUG_ON(init_local_irq_data() < 0);
 }
 
+int __init request_dt_irq(const struct dt_irq *irq,
+        void (*handler)(int, void *, struct cpu_user_regs *),
+        unsigned long irqflags, const char *devname, void *dev_id)
+{
+    return request_irq(irq->irq, handler, irqflags, devname, dev_id);
+}
+
 int __init request_irq(unsigned int irq,
         void (*handler)(int, void *, struct cpu_user_regs *),
         unsigned long irqflags, const char * devname, void *dev_id)
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 47399ca..248398d 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -39,6 +39,10 @@ void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
 void init_IRQ(void);
 void init_secondary_IRQ(void);
 
+int __init request_dt_irq(const struct dt_irq *irq,
+                          void (*handler)(int, void *, struct cpu_user_regs *),
+                          unsigned long irqflags, const char *devname,
+                          void *dev_id);
 int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
 
 #endif /* _ASM_HW_IRQ_H */
-- 
Julien Grall

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

* [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (13 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 14/33] xen/arm: Introduce request_dt_irq Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:46   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
                   ` (18 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

- Remove early parsing for GIC addresses
- Remove hard coded maintenance IRQ number

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - use the new function request_dt_irq
---
 xen/arch/arm/gic.c            |   63 ++++++++++++++++++++++++++++-------------
 xen/common/device_tree.c      |   42 ---------------------------
 xen/include/xen/device_tree.h |    8 ------
 3 files changed, 43 insertions(+), 70 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 1efa9a3..34304b3 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -45,6 +45,7 @@ static struct {
     paddr_t hbase;       /* Address of virtual interface registers */
     paddr_t vbase;       /* Address of virtual cpu interface registers */
     unsigned int lines;  /* Number of interrupts (SPIs + PPIs + SGIs) */
+    struct dt_irq maintenance; /* IRQ maintenance */
     unsigned int cpus;
     spinlock_t lock;
 } gic;
@@ -352,28 +353,49 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
 /* Set up the GIC */
 void __init gic_init(void)
 {
+    struct dt_device_node *node;
+    int res;
+
+    node = dt_find_interrupt_controller("arm,cortex-a15-gic");
+    if ( !node )
+        panic("Unable to find compatible GIC in the device tree\n");
+
+    dt_device_set_used_by(node, DT_USED_BY_XEN);
+
+    res = dt_device_get_address(node, 0, &gic.dbase, NULL);
+    if ( res || !gic.dbase || (gic.dbase & ~PAGE_MASK) )
+        panic("GIC: Cannot find a valid address for the distributor\n");
+
+    res = dt_device_get_address(node, 1, &gic.cbase, NULL);
+    if ( res || !gic.cbase || (gic.cbase & ~PAGE_MASK) )
+        panic("GIC: Cannot find a valid address for the CPU\n");
+
+    res = dt_device_get_address(node, 2, &gic.hbase, NULL);
+    if ( res || !gic.hbase || (gic.hbase & ~PAGE_MASK) )
+        panic("GIC: Cannot find a valid address for the hypervisor\n");
+
+    res = dt_device_get_address(node, 3, &gic.vbase, NULL);
+    if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
+        panic("GIC: Cannot find a valid address for the virtual CPU\n");
+
+    res = dt_device_get_irq(node, 0, &gic.maintenance);
+    if ( res )
+        panic("GIC: Cannot find the maintenance IRQ\n");
+
+    /* Set the GIC as the primary interrupt controller */
+    dt_interrupt_controller = node;
+
+    /* TODO: Add check on distributor, cpu size */
+
     printk("GIC initialization:\n"
               "        gic_dist_addr=%"PRIpaddr"\n"
               "        gic_cpu_addr=%"PRIpaddr"\n"
               "        gic_hyp_addr=%"PRIpaddr"\n"
-              "        gic_vcpu_addr=%"PRIpaddr"\n",
-              early_info.gic.gic_dist_addr, early_info.gic.gic_cpu_addr,
-              early_info.gic.gic_hyp_addr, early_info.gic.gic_vcpu_addr);
-    if ( !early_info.gic.gic_dist_addr ||
-         !early_info.gic.gic_cpu_addr ||
-         !early_info.gic.gic_hyp_addr ||
-         !early_info.gic.gic_vcpu_addr )
-        panic("the physical address of one of the GIC interfaces is missing\n");
-    if ( (early_info.gic.gic_dist_addr & ~PAGE_MASK) ||
-         (early_info.gic.gic_cpu_addr & ~PAGE_MASK) ||
-         (early_info.gic.gic_hyp_addr & ~PAGE_MASK) ||
-         (early_info.gic.gic_vcpu_addr & ~PAGE_MASK) )
-        panic("GIC interfaces not page aligned.\n");
-
-    gic.dbase = early_info.gic.gic_dist_addr;
-    gic.cbase = early_info.gic.gic_cpu_addr;
-    gic.hbase = early_info.gic.gic_hyp_addr;
-    gic.vbase = early_info.gic.gic_vcpu_addr;
+              "        gic_vcpu_addr=%"PRIpaddr"\n"
+              "        gic_maintenance_irq=%u\n",
+              gic.dbase, gic.cbase, gic.hbase, gic.vbase,
+              gic.maintenance.irq);
+
     set_fixmap(FIXMAP_GICD, gic.dbase >> PAGE_SHIFT, DEV_SHARED);
     BUILD_BUG_ON(FIXMAP_ADDR(FIXMAP_GICC1) !=
                  FIXMAP_ADDR(FIXMAP_GICC2)-PAGE_SIZE);
@@ -464,7 +486,7 @@ void gic_route_ppis(void)
 {
     /* XXX should get these from DT */
     /* GIC maintenance */
-    gic_route_irq(25, 1, 1u << smp_processor_id(), 0xa0);
+    gic_route_dt_irq(&gic.maintenance, 1u << smp_processor_id(), 0xa0);
     /* Hypervisor Timer */
     gic_route_irq(26, 1, 1u << smp_processor_id(), 0xa0);
     /* Virtual Timer */
@@ -830,7 +852,8 @@ void gic_dump_info(struct vcpu *v)
 
 void __cpuinit init_maintenance_interrupt(void)
 {
-    request_irq(25, maintenance_interrupt, 0, "irq-maintenance", NULL);
+    request_dt_irq(&gic.maintenance, maintenance_interrupt,
+                   0, "irq-maintenance", NULL);
 }
 
 /*
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index e5ff779..548d21b 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -425,46 +425,6 @@ static void __init process_cpu_node(const void *fdt, int node,
     cpumask_set_cpu(start, &cpu_possible_map);
 }
 
-static void __init process_gic_node(const void *fdt, int node,
-                                    const char *name,
-                                    u32 address_cells, u32 size_cells)
-{
-    const struct fdt_property *prop;
-    const u32 *cell;
-    paddr_t start, size;
-    int interfaces;
-
-    if ( address_cells < 1 || size_cells < 1 )
-    {
-        early_printk("fdt: node `%s': invalid #address-cells or #size-cells",
-                     name);
-        return;
-    }
-
-    prop = fdt_get_property(fdt, node, "reg", NULL);
-    if ( !prop )
-    {
-        early_printk("fdt: node `%s': missing `reg' property\n", name);
-        return;
-    }
-
-    cell = (const u32 *)prop->data;
-    interfaces = device_tree_nr_reg_ranges(prop, address_cells, size_cells);
-    if ( interfaces < 4 )
-    {
-        early_printk("fdt: node `%s': not enough ranges\n", name);
-        return;
-    }
-    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-    early_info.gic.gic_dist_addr = start;
-    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-    early_info.gic.gic_cpu_addr = start;
-    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-    early_info.gic.gic_hyp_addr = start;
-    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
-    early_info.gic.gic_vcpu_addr = start;
-}
-
 static void __init process_multiboot_node(const void *fdt, int node,
                                           const char *name,
                                           u32 address_cells, u32 size_cells)
@@ -516,8 +476,6 @@ static int __init early_scan_node(const void *fdt,
         process_memory_node(fdt, node, name, address_cells, size_cells);
     else if ( device_tree_type_matches(fdt, node, "cpu") )
         process_cpu_node(fdt, node, name, address_cells, size_cells);
-    else if ( device_tree_node_compatible(fdt, node, "arm,cortex-a15-gic") )
-        process_gic_node(fdt, node, name, address_cells, size_cells);
     else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) )
         process_multiboot_node(fdt, node, name, address_cells, size_cells);
 
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index bf873d9..deef5e7 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -31,13 +31,6 @@ struct dt_mem_info {
     struct membank bank[NR_MEM_BANKS];
 };
 
-struct dt_gic_info {
-    paddr_t gic_dist_addr;
-    paddr_t gic_cpu_addr;
-    paddr_t gic_hyp_addr;
-    paddr_t gic_vcpu_addr;
-};
-
 struct dt_mb_module {
     paddr_t start;
     paddr_t size;
@@ -52,7 +45,6 @@ struct dt_module_info {
 
 struct dt_early_info {
     struct dt_mem_info mem;
-    struct dt_gic_info gic;
     struct dt_module_info modules;
 };
 
-- 
Julien Grall

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

* [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (14 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:50   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 17/33] xen/arm: Don't hardcode VGIC informations Julien Grall
                   ` (17 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Hardcode ppi_nr value
    - Use the new function request_dt_irq
---
 xen/arch/arm/gic.c         |    9 ++-----
 xen/arch/arm/time.c        |   59 +++++++++++++++++++++++++++++++++++++++-----
 xen/include/asm-arm/time.h |    3 +++
 3 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 34304b3..91348b6 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -484,15 +484,10 @@ void gic_disable_cpu(void)
 
 void gic_route_ppis(void)
 {
-    /* XXX should get these from DT */
     /* GIC maintenance */
     gic_route_dt_irq(&gic.maintenance, 1u << smp_processor_id(), 0xa0);
-    /* Hypervisor Timer */
-    gic_route_irq(26, 1, 1u << smp_processor_id(), 0xa0);
-    /* Virtual Timer */
-    gic_route_irq(27, 1, 1u << smp_processor_id(), 0xa0);
-    /* Physical Timer */
-    gic_route_irq(30, 1, 1u << smp_processor_id(), 0xa0);
+    /* Route timer interrupt */
+    route_timer_interrupt();
 }
 
 void gic_route_spis(void)
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 82f69d2..bfc41c2 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -19,6 +19,7 @@
 
 #include <xen/config.h>
 #include <xen/console.h>
+#include <xen/device_tree.h>
 #include <xen/init.h>
 #include <xen/irq.h>
 #include <xen/lib.h>
@@ -46,6 +47,18 @@ uint64_t __read_mostly boot_count;
  * register-mapped time source in the SoC. */
 unsigned long __read_mostly cpu_khz;  /* CPU clock frequency in kHz. */
 
+/* List of timer's IRQ */
+enum ppi_nr
+{
+    PHYS_SECURE_PPI = 0,
+    PHYS_NONSECURE_PPI = 1,
+    VIRT_PPI = 2,
+    HYP_PPI = 3,
+    MAX_TIMER_PPI = 4,
+};
+
+static struct dt_irq timer_irq[MAX_TIMER_PPI];
+
 /*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
 {
     return muldiv64(ticks, SECONDS(1), 1000 * cpu_khz);
@@ -90,6 +103,28 @@ static uint32_t calibrate_timer(void)
 /* Set up the timer on the boot CPU */
 int __init init_xen_time(void)
 {
+    struct dt_device_node *dev;
+    int res;
+    unsigned int i;
+
+    dev = dt_find_compatible_node(NULL, NULL, "arm,armv7-timer");
+    if ( !dev )
+        panic("Unable to find a compatible timer in the device tree\n");
+
+    dt_device_set_used_by(dev, DT_USED_BY_XEN);
+
+    /* Retrieve all IRQs for the timer */
+    for ( i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
+    {
+        res = dt_device_get_irq(dev, i, &timer_irq[i]);
+        if ( res )
+            panic("Timer: Unable to retrieve IRQ %u from the device tree\n", i);
+    }
+
+    printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u\n",
+           timer_irq[PHYS_NONSECURE_PPI].irq, timer_irq[HYP_PPI].irq,
+           timer_irq[VIRT_PPI].irq);
+
     /* Check that this CPU supports the Generic Timer interface */
     if ( !cpu_has_gentimer )
         panic("CPU does not support the Generic Timer v1 interface.\n");
@@ -143,7 +178,8 @@ int reprogram_timer(s_time_t timeout)
 /* Handle the firing timer */
 static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
 {
-    if ( irq == 26 && READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
+    if ( irq == (timer_irq[HYP_PPI].irq) &&
+         READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
     {
         /* Signal the generic timer code to do its work */
         raise_softirq(TIMER_SOFTIRQ);
@@ -151,7 +187,8 @@ static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
         WRITE_SYSREG32(0, CNTHP_CTL_EL2);
     }
 
-    if (irq == 30 && READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
+    if ( irq == (timer_irq[PHYS_NONSECURE_PPI].irq) &&
+         READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
     {
         /* Signal the generic timer code to do its work */
         raise_softirq(TIMER_SOFTIRQ);
@@ -167,6 +204,15 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
     vgic_vcpu_inject_irq(current, irq, 1);
 }
 
+/* Route timer's IRQ on this CPU */
+void __cpuinit route_timer_interrupt(void)
+{
+    gic_route_dt_irq(&timer_irq[PHYS_NONSECURE_PPI],
+                     1u << smp_processor_id(), 0xa0);
+    gic_route_dt_irq(&timer_irq[HYP_PPI], 1u << smp_processor_id(), 0xa0);
+    gic_route_dt_irq(&timer_irq[VIRT_PPI], 1u << smp_processor_id(), 0xa0);
+}
+
 /* Set up the timer interrupt on this CPU */
 void __cpuinit init_timer_interrupt(void)
 {
@@ -184,10 +230,11 @@ void __cpuinit init_timer_interrupt(void)
     WRITE_SYSREG32(0, CNTHP_CTL_EL2);   /* Hypervisor's timer disabled */
     isb();
 
-    /* XXX Need to find this IRQ number from devicetree? */
-    request_irq(26, timer_interrupt, 0, "hyptimer", NULL);
-    request_irq(27, vtimer_interrupt, 0, "virtimer", NULL);
-    request_irq(30, timer_interrupt, 0, "phytimer", NULL);
+    request_dt_irq(&timer_irq[HYP_PPI], timer_interrupt, 0, "hyptimer", NULL);
+    request_dt_irq(&timer_irq[VIRT_PPI], vtimer_interrupt, 0,
+                   "virtimer", NULL);
+    request_dt_irq(&timer_irq[PHYS_NONSECURE_PPI], timer_interrupt, 2,
+                   "phytimer", NULL);
 }
 
 /* Wait a set number of microseconds */
diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
index c16bf08..467bf91 100644
--- a/xen/include/asm-arm/time.h
+++ b/xen/include/asm-arm/time.h
@@ -12,6 +12,9 @@ struct tm;
 struct tm wallclock_time(void);
 
 
+/* Route timer's IRQ on this CPU */
+extern void __cpuinit route_timer_interrupt(void);
+
 /* Set up the timer interrupt on this CPU */
 extern void __cpuinit init_timer_interrupt(void);
 
-- 
Julien Grall

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

* [PATCH V2 17/33] xen/arm: Don't hardcode VGIC informations
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (15 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
                   ` (16 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

- Define VGIC base address per domain. For the moment the base addresses
to dom0 base addresses.
- The number of interrupt lines (ie number of SPIs) is equal to:
    * 0 for guests
    * number of host SPIs for dom0

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v2:
    - Don't use javadoc style
---
 xen/arch/arm/gic.c           |   21 ++++++++++++++++++---
 xen/arch/arm/vgic.c          |   20 ++++++++++++++------
 xen/include/asm-arm/domain.h |    5 ++++-
 xen/include/asm-arm/gic.h    |    3 +++
 4 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 91348b6..715db60 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -56,6 +56,11 @@ static DEFINE_PER_CPU(uint64_t, lr_mask);
 
 static unsigned nr_lrs;
 
+unsigned int gic_number_lines(void)
+{
+    return gic.lines;
+}
+
 irq_desc_t *__irq_to_desc(int irq)
 {
     if (irq < NR_LOCAL_IRQS) return &this_cpu(local_irq_desc)[irq];
@@ -771,11 +776,21 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 
 int gicv_setup(struct domain *d)
 {
+    /* TODO: Retrieve distributor and CPU guest base address from the
+     * guest DTS
+     * For the moment we use dom0 DTS
+     */
+    d->arch.vgic.dbase = gic.dbase;
+    d->arch.vgic.cbase = gic.cbase;
+
+
+    d->arch.vgic.nr_lines = 0;
+
     /* map the gic virtual cpu interface in the gic cpu interface region of
      * the guest */
-    return map_mmio_regions(d, gic.cbase,
-                        gic.cbase + (2 * PAGE_SIZE) - 1,
-                        gic.vbase);
+    return map_mmio_regions(d, d->arch.vgic.cbase,
+                            d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
+                            gic.vbase);
 }
 
 static void maintenance_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index f9c1a6b..7eaccb7 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -30,8 +30,6 @@
 #include "io.h"
 #include <asm/gic.h>
 
-#define VGIC_DISTR_BASE_ADDRESS 0x000000002c001000
-
 #define REG(n) (n/4)
 
 /* Number of ranks of interrupt registers for a domain */
@@ -80,7 +78,15 @@ int domain_vgic_init(struct domain *d)
     int i;
 
     d->arch.vgic.ctlr = 0;
-    d->arch.vgic.nr_lines = 32;
+
+    /* Currently nr_lines in vgic and gic doesn't have the same meanings
+     * Here nr_lines = number of SPIs
+     */
+    if ( d->domain_id == 0 )
+        d->arch.vgic.nr_lines = gic_number_lines() - 32;
+    else
+        d->arch.vgic.nr_lines = 0; /* We don't need SPIs for the guest */
+
     d->arch.vgic.shared_irqs =
         xmalloc_array(struct vgic_irq_rank, DOMAIN_NR_RANKS(d));
     d->arch.vgic.pending_irqs =
@@ -163,7 +169,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     register_t *r = select_user_reg(regs, dabt.reg);
     struct vgic_irq_rank *rank;
-    int offset = (int)(info->gpa - VGIC_DISTR_BASE_ADDRESS);
+    int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
     int gicd_reg = REG(offset);
 
     switch ( gicd_reg )
@@ -440,7 +446,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info)
     struct cpu_user_regs *regs = guest_cpu_user_regs();
     register_t *r = select_user_reg(regs, dabt.reg);
     struct vgic_irq_rank *rank;
-    int offset = (int)(info->gpa - VGIC_DISTR_BASE_ADDRESS);
+    int offset = (int)(info->gpa - v->domain->arch.vgic.dbase);
     int gicd_reg = REG(offset);
     uint32_t tr;
 
@@ -620,7 +626,9 @@ write_ignore:
 
 static int vgic_distr_mmio_check(struct vcpu *v, paddr_t addr)
 {
-    return addr >= VGIC_DISTR_BASE_ADDRESS && addr < (VGIC_DISTR_BASE_ADDRESS+PAGE_SIZE);
+    struct domain *d = v->domain;
+
+    return (addr >= (d->arch.vgic.dbase)) && (addr < (d->arch.vgic.dbase + PAGE_SIZE));
 }
 
 const struct mmio_handler vgic_distr_mmio_handler = {
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index cca7416..cb251cc 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -88,13 +88,16 @@ struct arch_domain
          */
         spinlock_t lock;
         int ctlr;
-        int nr_lines;
+        int nr_lines; /* Number of SPIs */
         struct vgic_irq_rank *shared_irqs;
         /*
          * SPIs are domain global, SGIs and PPIs are per-VCPU and stored in
          * struct arch_vcpu.
          */
         struct pending_irq *pending_irqs;
+        /* Base address for guest GIC */
+        paddr_t dbase; /* Distributor base address */
+        paddr_t cbase; /* CPU base address */
     } vgic;
 
     struct vpl011 {
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 6ff217c..e7608dc 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -189,6 +189,9 @@ extern void send_SGI_allbutself(enum gic_sgi sgi);
 /* print useful debug info */
 extern void gic_dump_info(struct vcpu *v);
 
+/* Number of interrupt lines */
+extern unsigned int gic_number_lines(void);
+
 /* IRQ translation function for the device tree */
 int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
                   unsigned int *out_hwirq, unsigned int *out_type);
-- 
Julien Grall

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

* [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (16 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 17/33] xen/arm: Don't hardcode VGIC informations Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 13:52   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 19/33] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
                   ` (15 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Add missing ALIGN in xen.lds.S
---
 xen/arch/arm/Makefile        |    1 +
 xen/arch/arm/device.c        |   74 ++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/xen.lds.S       |    7 ++++
 xen/include/asm-arm/device.h |   52 +++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)
 create mode 100644 xen/arch/arm/device.c
 create mode 100644 xen/include/asm-arm/device.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 8f75044..4955a21 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -28,6 +28,7 @@ obj-y += vgic.o
 obj-y += vtimer.o
 obj-y += vpl011.o
 obj-y += hvm.o
+obj-y += device.o
 
 #obj-bin-y += ....o
 
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
new file mode 100644
index 0000000..dc751a9
--- /dev/null
+++ b/xen/arch/arm/device.c
@@ -0,0 +1,74 @@
+/*
+ * xen/arch/arm/device.c
+ *
+ * Helpers to use a device retrieved via the device tree.
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (C) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/device.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+
+extern const struct device_desc _sdevice[], _edevice[];
+
+static bool_t __init device_is_compatible(const struct device_desc *desc,
+                                          const struct dt_device_node *dev)
+{
+    const char *const *compat;
+
+    if ( !desc->compatible )
+        return 0;
+
+    for ( compat = desc->compatible; *compat; compat++ )
+    {
+        if ( dt_device_is_compatible(dev, *compat) )
+            return 1;
+    }
+
+    return 0;
+}
+
+int __init device_init(struct dt_device_node *dev, enum device_type type,
+                       const void *data)
+{
+    const struct device_desc *desc;
+
+    ASSERT(dev != NULL);
+
+    for ( desc = _sdevice; desc != _edevice; desc++ )
+    {
+        if ( desc->type != type )
+            continue;
+
+        if ( device_is_compatible(desc, dev) )
+        {
+            ASSERT(desc->init != NULL);
+
+            return desc->init(dev, data);
+        }
+
+    }
+
+    return -EBADF;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index fd755d7..deab040 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -76,6 +76,13 @@ SECTIONS
   __lock_profile_end = .;
 #endif
 
+  . = ALIGN(8);
+  .dev.info : {
+      _sdevice = .;
+      *(.dev.info)
+      _edevice = .;
+  } :text
+
   . = ALIGN(PAGE_SIZE);             /* Init code and data */
   __init_begin = .;
   .init.text : {
diff --git a/xen/include/asm-arm/device.h b/xen/include/asm-arm/device.h
new file mode 100644
index 0000000..9e47ca6
--- /dev/null
+++ b/xen/include/asm-arm/device.h
@@ -0,0 +1,52 @@
+#ifndef __ASM_ARM_DEVICE_H
+#define __ASM_ARM_DEVICE_H
+
+#include <xen/init.h>
+#include <xen/device_tree.h>
+
+enum device_type
+{
+    DEVICE_SERIAL
+};
+
+struct device_desc {
+    /* Device name */
+    const char *name;
+    /* Device type */
+    enum device_type type;
+    /* Array of device tree 'compatible' strings */
+    const char *const *compatible;
+    /* Device initialization */
+    int (*init)(struct dt_device_node *dev, const void *data);
+};
+
+/**
+ *  device_init - Initialize a device
+ *  @dev: device to initialize
+ *  @type: type of the device (serial, network...)
+ *  @data: specific data for initializing the device
+ *
+ *  Return 0 on success.
+ */
+int __init device_init(struct dt_device_node *dev, enum device_type type,
+                       const void *data);
+
+#define DT_DEVICE_START(_name, _namestr, _type)                     \
+static const struct device_desc __dev_desc_##_name __used           \
+__attribute__((__section__(".dev.info"))) = {                       \
+    .name = _namestr,                                               \
+    .type = _type,                                                  \
+
+#define DT_DEVICE_END                                               \
+};
+
+#endif /* __ASM_ARM_DEVICE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Julien Grall

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

* [PATCH V2 19/33] xen/arm: New callback in uart_driver to get device tree interrupt structure
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (17 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree Julien Grall
                   ` (14 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

The existing function serial_irq doesn't allow to retrieve if the interrupt
is edge or level trigger.

Use this function to routes IRQs for all serial ports which Xen is using
to Xen.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v2:
    - Improve commit message
---
 xen/arch/arm/gic.c        |   12 ++++++++++++
 xen/drivers/char/serial.c |   10 ++++++++++
 xen/include/xen/serial.h  |    5 +++++
 3 files changed, 27 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 715db60..d719229 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -24,6 +24,7 @@
 #include <xen/irq.h>
 #include <xen/sched.h>
 #include <xen/errno.h>
+#include <xen/serial.h>
 #include <xen/softirq.h>
 #include <xen/list.h>
 #include <xen/device_tree.h>
@@ -497,9 +498,20 @@ void gic_route_ppis(void)
 
 void gic_route_spis(void)
 {
+    int seridx;
+    const struct dt_irq *irq;
+
     /* XXX should get these from DT */
     /* UART */
     gic_route_irq(37, 0, 1u << smp_processor_id(), 0xa0);
+
+    for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
+    {
+        if ( (irq = serial_dt_irq(seridx)) == NULL )
+            continue;
+
+        gic_route_dt_irq(irq, 1u << smp_processor_id(), 0xa0);
+    }
 }
 
 void __init release_irq(unsigned int irq)
diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index a3d2b26..0ae7e4d 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -482,6 +482,16 @@ int __init serial_irq(int idx)
     return -1;
 }
 
+const struct dt_irq __init *serial_dt_irq(int idx)
+{
+    if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
+         com[idx].driver && com[idx].driver->dt_irq_get )
+        return com[idx].driver->dt_irq_get(&com[idx]);
+
+    return NULL;
+}
+
+
 void serial_suspend(void)
 {
     int i;
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index b932ed4..5de5171 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -71,6 +71,8 @@ struct uart_driver {
     int  (*getc)(struct serial_port *, char *);
     /* Get IRQ number for this port's serial line: returns -1 if none. */
     int  (*irq)(struct serial_port *);
+    /* Get IRQ device node for this port's serial line: returns NULL if none. */
+    const struct dt_irq *(*dt_irq_get)(struct serial_port *);
 };
 
 /* 'Serial handles' are composed from the following fields. */
@@ -120,6 +122,9 @@ void serial_end_log_everything(int handle);
 /* Return irq number for specified serial port (identified by index). */
 int serial_irq(int idx);
 
+/* Return irq device node for specified serial port (identified by index). */
+const struct dt_irq *serial_dt_irq(int idx);
+
 /* Serial suspend/resume. */
 void serial_suspend(void);
 void serial_resume(void);
-- 
Julien Grall

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

* [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (18 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 19/33] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 14:01   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver Julien Grall
                   ` (13 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This generic UART will find the right UART via xen command line
with dtuart=myserial.

"myserial" is the alias of the UART in the device tree. Xen will retrieve
the information via the device tree and call the initialization function for
this specific UART thanks to the device API.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use dtuart parameter instead of com1. The first one is more arm
    while the latter is more x86
---
 xen/arch/arm/setup.c         |    3 +-
 xen/drivers/char/Makefile    |    1 +
 xen/drivers/char/arm-uart.c  |   81 ++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/char/serial.c    |    6 ++++
 xen/include/asm-arm/config.h |    2 +-
 xen/include/xen/serial.h     |    7 ++++
 6 files changed, 98 insertions(+), 2 deletions(-)
 create mode 100644 xen/drivers/char/arm-uart.c

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e4228f7..7b2df8b 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -435,8 +435,9 @@ void __init start_xen(unsigned long boot_phys_offset,
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
     pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
-    console_init_preirq();
 #endif
+    arm_uart_init();
+    console_init_preirq();
 
     /* FIXME: Do something smarter */
     dt_switch_to_printk();
diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
index ab2246d..e68a54a 100644
--- a/xen/drivers/char/Makefile
+++ b/xen/drivers/char/Makefile
@@ -2,4 +2,5 @@ obj-y += console.o
 obj-$(HAS_NS16550) += ns16550.o
 obj-$(HAS_PL011) += pl011.o
 obj-$(HAS_EHCI) += ehci-dbgp.o
+obj-$(CONFIG_ARM) += arm-uart.o
 obj-y += serial.o
diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c
new file mode 100644
index 0000000..c76875e
--- /dev/null
+++ b/xen/drivers/char/arm-uart.c
@@ -0,0 +1,81 @@
+/*
+ * xen/drivers/char/arm-uart.c
+ *
+ * Generic ARM uart retrieved via the device tree
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/device.h>
+#include <asm/early_printk.h>
+#include <asm/types.h>
+#include <xen/console.h>
+#include <xen/device_tree.h>
+#include <xen/mm.h>
+#include <xen/serial.h>
+
+/*
+ * Configure UART port with a string:
+ * alias
+ *
+ * @alias: alias used in the device tree for the UART
+ * TODO: Implement config  in each UART driver.
+ */
+static char __initdata opt_dtuart[30] = "";
+string_param("dtuart", opt_dtuart);
+
+void __init arm_uart_init(void)
+{
+    struct dt_device_node *dev;
+    int ret;
+    u64 addr, size;
+    struct serial_arm_defaults defaults;
+    const char *devalias = opt_dtuart;
+
+    if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
+    {
+        early_printk("No console\n");
+        return;
+    }
+
+    early_printk("Looking for UART console %s\n", devalias);
+    dev = dt_find_node_by_alias(devalias);
+
+    if ( !dev )
+    {
+        early_printk("Unable to find device \"%s\"\n", devalias);
+        return;
+    }
+
+    /* TODO: Handle UART with 0 or multiple base address */
+    ret = dt_device_get_address(dev, 0, &addr, &size);
+    if ( ret )
+    {
+        early_printk("Unable to retrieve the base address of the serial\n");
+        return;
+    }
+
+    clear_fixmap(FIXMAP_CONSOLE);
+    set_fixmap(FIXMAP_CONSOLE, addr >> PAGE_SHIFT, DEV_SHARED);
+
+    addr = FIXMAP_ADDR(FIXMAP_CONSOLE) + (addr & (PAGE_SIZE - 1));
+
+    defaults.index = 0;
+    defaults.register_base_address = addr;
+
+    ret = device_init(dev, DEVICE_SERIAL, &defaults);
+
+    if ( ret )
+        early_printk("Unable to initialize serial: %d\n", ret);
+}
diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index 0ae7e4d..c4c4a84 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -271,6 +271,12 @@ int __init serial_parse_handle(char *conf)
         goto common;
     }
 
+    if ( !strncmp(conf, "dtuart", 5) )
+    {
+        handle = SERHND_COM1;
+        goto common;
+    }
+
     if ( strncmp(conf, "com", 3) )
         goto fail;
 
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 98a3a43..8ed72f5 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -39,7 +39,7 @@
 
 #define CONFIG_VIDEO 1
 
-#define OPT_CONSOLE_STR "com1"
+#define OPT_CONSOLE_STR "dtuart"
 
 #ifdef MAX_PHYS_CPUS
 #define NR_CPUS MAX_PHYS_CPUS
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index 5de5171..f548f8b 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -9,6 +9,7 @@
 #ifndef __XEN_SERIAL_H__
 #define __XEN_SERIAL_H__
 
+#include <xen/init.h>
 #include <xen/spinlock.h>
 
 struct cpu_user_regs;
@@ -156,6 +157,12 @@ void ns16550_init(int index, struct ns16550_defaults *defaults);
 void ehci_dbgp_init(void);
 
 void pl011_init(int index, unsigned long register_base_address);
+/* Default value for UART on ARM boards */
+struct serial_arm_defaults {
+    int index;                              /* Serial index */
+    unsigned long register_base_address;    /* Virtual base address */
+};
+void __init arm_uart_init(void);
 
 struct physdev_dbgp_op;
 int dbgp_op(const struct physdev_dbgp_op *);
-- 
Julien Grall

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

* [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (19 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 15:17   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
                   ` (12 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Allow UART driver to retrieve all its information in the device tree.
It's possible to choose the pl011 driver via the Xen command line.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Rework TODO
    - Use the new function setup_dt_irq
---
 xen/arch/arm/gic.c       |    4 ---
 xen/arch/arm/setup.c     |    4 ---
 xen/drivers/char/pl011.c |   64 ++++++++++++++++++++++++++++++++++++----------
 xen/include/xen/serial.h |    1 -
 4 files changed, 50 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index d719229..f7b9889 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -501,10 +501,6 @@ void gic_route_spis(void)
     int seridx;
     const struct dt_irq *irq;
 
-    /* XXX should get these from DT */
-    /* UART */
-    gic_route_irq(37, 0, 1u << smp_processor_id(), 0xa0);
-
     for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
     {
         if ( (irq = serial_dt_irq(seridx)) == NULL )
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 7b2df8b..d8a3578 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -432,10 +432,6 @@ void __init start_xen(unsigned long boot_phys_offset,
     dt_unflatten_host_device_tree();
     dt_irq_xlate = gic_irq_xlate;
 
-#ifdef EARLY_UART_ADDRESS
-    /* TODO Need to get device tree or command line for UART address */
-    pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
-#endif
     arm_uart_init();
     console_init_preirq();
 
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 8efd08e..03161c4 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -22,9 +22,14 @@
 #include <xen/serial.h>
 #include <xen/init.h>
 #include <xen/irq.h>
+#include <asm/early_printk.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <asm/device.h>
 
 static struct pl011 {
-    unsigned int baud, clock_hz, data_bits, parity, stop_bits, irq;
+    unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+    struct dt_irq irq;
     volatile uint32_t *regs;
     /* UART with IRQ line: interrupt-driven I/O. */
     struct irqaction irqaction;
@@ -163,13 +168,13 @@ static void __init pl011_init_postirq(struct serial_port *port)
     struct pl011 *uart = port->uart;
     int rc;
 
-    if ( uart->irq > 0 )
+    if ( uart->irq.irq > 0 )
     {
         uart->irqaction.handler = pl011_interrupt;
         uart->irqaction.name    = "pl011";
         uart->irqaction.dev_id  = port;
-        if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
-            printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
+        if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+            printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq.irq);
     }
 
     /* Clear pending error interrupts */
@@ -215,7 +220,14 @@ static int pl011_getc(struct serial_port *port, char *pc)
 static int __init pl011_irq(struct serial_port *port)
 {
     struct pl011 *uart = port->uart;
-    return ((uart->irq > 0) ? uart->irq : -1);
+    return ((uart->irq.irq > 0) ? uart->irq.irq : -1);
+}
+
+static const struct dt_irq __init *pl011_dt_irq(struct serial_port *port)
+{
+    struct pl011 *uart = port->uart;
+
+    return &uart->irq;
 }
 
 static struct uart_driver __read_mostly pl011_driver = {
@@ -227,32 +239,56 @@ static struct uart_driver __read_mostly pl011_driver = {
     .tx_ready     = pl011_tx_ready,
     .putc         = pl011_putc,
     .getc         = pl011_getc,
-    .irq          = pl011_irq
+    .irq          = pl011_irq,
+    .dt_irq_get   = pl011_dt_irq,
 };
 
-/* TODO: Parse UART config from device-tree or command-line */
-
-void __init pl011_init(int index, unsigned long register_base_address)
+/* TODO: Parse UART config from the command line */
+static int __init pl011_uart_init(struct dt_device_node *dev,
+                                  const void *data)
 {
+    const struct serial_arm_defaults *defaults = data;
     struct pl011 *uart;
+    int res;
 
-    if ( (index < 0) || (index > 1) )
-        return;
+    if ( (defaults->index < 0) || (defaults->index > 1) )
+        return -EINVAL;
 
-    uart = &pl011_com[index];
+    uart = &pl011_com[defaults->index];
 
     uart->clock_hz  = 0x16e3600;
     uart->baud      = 38400;
     uart->data_bits = 8;
     uart->parity    = PARITY_NONE;
     uart->stop_bits = 1;
-    uart->irq       = 37; /* TODO Need to find this from devicetree */
-    uart->regs      = (uint32_t *) register_base_address;
+    uart->regs      = (uint32_t *) defaults->register_base_address;
+
+    res = dt_device_get_irq(dev, 0, &uart->irq);
+    if ( res )
+    {
+        early_printk("pl011: Unable to retrieve the IRQ\n");
+        return res;
+    }
 
     /* Register with generic serial driver. */
     serial_register_uart(uart - pl011_com, &pl011_driver, uart);
+
+    dt_device_set_used_by(dev, DT_USED_BY_XEN);
+
+    return 0;
 }
 
+static const char const *pl011_dt_compat[] __initdata =
+{
+    "arm,pl011",
+    NULL
+};
+
+DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
+        .compatible = pl011_dt_compat,
+        .init = pl011_uart_init,
+DT_DEVICE_END
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
index f548f8b..16ed261 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -156,7 +156,6 @@ struct ns16550_defaults {
 void ns16550_init(int index, struct ns16550_defaults *defaults);
 void ehci_dbgp_init(void);
 
-void pl011_init(int index, unsigned long register_base_address);
 /* Default value for UART on ARM boards */
 struct serial_arm_defaults {
     int index;                              /* Serial index */
-- 
Julien Grall

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

* [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (20 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 15:28   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
                   ` (11 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

- gic_route_irq_to_guest takes a dt_irq instead of an IRQ number
- remove hardcoded address/IRQ

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use the new function dt_irq_is_level_trigger
    - Disable DEBUG_DT by default
    - Rename parse_device_tree to map_device_from_device_tree
---
 xen/arch/arm/domain_build.c |  144 +++++++++++++++++++++++++++++++++++++------
 xen/arch/arm/gic.c          |   12 ++--
 xen/include/asm-arm/gic.h   |    3 +-
 3 files changed, 136 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 6581492..0b762a9 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -14,6 +14,7 @@
 #include <asm/setup.h>
 
 #include <asm/gic.h>
+#include <xen/irq.h>
 #include "kernel.h"
 
 static unsigned int __initdata opt_dom0_max_vcpus;
@@ -30,6 +31,14 @@ static void __init parse_dom0_mem(const char *s)
 }
 custom_param("dom0_mem", parse_dom0_mem);
 
+//#define DEBUG_DT
+
+#ifdef DEBUG_DT
+# define DPRINT(fmt, args...) printk(XENLOG_DEBUG fmt, ##args)
+#else
+# define DPRINT(fmt, args...) do {} while ( 0 )
+#endif
+
 /*
  * Amount of extra space required to dom0's device tree.  No new nodes
  * are added (yet) but one terminating reserve map entry (16 bytes) is
@@ -303,6 +312,122 @@ static int write_nodes(struct domain *d, struct kernel_info *kinfo,
     return 0;
 }
 
+/* Map the device in the domain */
+static int map_device(struct domain *d, const struct dt_device_node *dev)
+{
+    unsigned int nirq;
+    unsigned int naddr;
+    unsigned int i;
+    int res;
+    struct dt_irq irq;
+    struct dt_raw_irq rirq;
+    u64 addr, size;
+
+    nirq = dt_number_of_irq(dev);
+    naddr = dt_number_of_address(dev);
+
+    DPRINT("%s nirq = %d naddr = %u\n", dt_node_full_name(dev), nirq, naddr);
+
+    /* Map IRQs */
+    for ( i = 0; i < nirq; i++ )
+    {
+        res = dt_device_get_raw_irq(dev, i, &rirq);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n",
+                   i, dt_node_full_name(dev));
+            return res;
+        }
+
+        /**
+         * Don't map IRQ that have no physical meaning
+         * ie: IRQ whose controller is not the GIC
+         */
+        if ( rirq.controller != dt_interrupt_controller )
+        {
+            DPRINT("irq %u skipped it controller (%s)\n",
+                   i, dt_node_full_name(rirq.controller));
+            continue;
+        }
+
+        res = dt_irq_translate(&rirq, &irq);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to translate irq %u for %s\n",
+                   i, dt_node_full_name(dev));
+            return res;
+        }
+
+        DPRINT("irq %u = %u type = %#x\n", i, irq.irq, irq.type);
+        /* Don't check return because the IRQ can be use by multiple device */
+        gic_route_irq_to_guest(d, &irq, dt_node_name(dev));
+    }
+
+    /* Map the address ranges */
+    for ( i = 0; i < naddr; i++ )
+    {
+        res = dt_device_get_address(dev, i, &addr, &size);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to retrieve address %u for %s\n",
+                   i, dt_node_full_name(dev));
+            return res;
+        }
+
+        DPRINT("addr %u = %#"PRIx64" - %#"PRIx64"\n", i, addr, addr + size - 1);
+
+        res = map_mmio_regions(d, addr & PAGE_MASK,
+                               PAGE_ALIGN(addr + size) - 1,
+                               addr & PAGE_MASK);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to map %#"PRIx64" - %#"PRIx64" in dom0\n",
+                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
+            return res;
+        }
+    }
+
+    return 0;
+}
+
+static int handle_node(struct domain *d, const struct dt_device_node *np)
+{
+    const struct dt_device_node *child;
+    int res;
+
+    DPRINT("handle %s\n", dt_node_full_name(np));
+
+    /* Skip theses nodes and the sub-nodes */
+    if ( dt_device_is_compatible(np, "xen,xen") ||
+         dt_device_type_is_equal(np, "memory") ||
+         !strcmp("/chosen", dt_node_full_name(np)) )
+        return 0;
+
+    if ( dt_device_used_by(np) != DT_USED_BY_XEN )
+    {
+        res = map_device(d, np);
+
+        if ( res )
+            return res;
+    }
+
+    for ( child = np->child; child != NULL; child = child->sibling )
+    {
+        res = handle_node(d, child);
+        if ( res )
+            return res;
+    }
+
+    return 0;
+}
+
+static int map_device_from_device_tree(struct domain *d)
+{
+    ASSERT(dt_host && (dt_host->sibling == NULL));
+
+    return handle_node(d, dt_host);
+}
+
 static int prepare_dtb(struct domain *d, struct kernel_info *kinfo)
 {
     void *fdt;
@@ -385,24 +510,7 @@ int construct_dom0(struct domain *d)
     if ( rc < 0 )
         return rc;
 
-    printk("Map CS2 MMIO regions 1:1 in the P2M %#llx->%#llx\n", 0x18000000ULL, 0x1BFFFFFFULL);
-    map_mmio_regions(d, 0x18000000, 0x1BFFFFFF, 0x18000000);
-    printk("Map CS3 MMIO regions 1:1 in the P2M %#llx->%#llx\n", 0x1C000000ULL, 0x1FFFFFFFULL);
-    map_mmio_regions(d, 0x1C000000, 0x1FFFFFFF, 0x1C000000);
-
-    printk("Routing peripheral interrupts to guest\n");
-    /* TODO Get from device tree */
-    gic_route_irq_to_guest(d, 34, "timer0");
-    /*gic_route_irq_to_guest(d, 37, "uart0"); -- XXX used by Xen*/
-    gic_route_irq_to_guest(d, 38, "uart1");
-    gic_route_irq_to_guest(d, 39, "uart2");
-    gic_route_irq_to_guest(d, 40, "uart3");
-    gic_route_irq_to_guest(d, 41, "mmc0-1");
-    gic_route_irq_to_guest(d, 42, "mmc0-2");
-    gic_route_irq_to_guest(d, 44, "keyboard");
-    gic_route_irq_to_guest(d, 45, "mouse");
-    gic_route_irq_to_guest(d, 46, "lcd");
-    gic_route_irq_to_guest(d, 47, "eth");
+    map_device_from_device_tree(d);
 
     /* The following loads use the domain's p2m */
     p2m_load_VTTBR(d);
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index f7b9889..ddad0c8 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -692,13 +692,14 @@ void gic_inject(void)
         gic_inject_irq_start();
 }
 
-int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
+int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
                            const char * devname)
 {
     struct irqaction *action;
-    struct irq_desc *desc = irq_to_desc(irq);
+    struct irq_desc *desc = irq_to_desc(irq->irq);
     unsigned long flags;
     int retval;
+    bool_t level;
 
     action = xmalloc(struct irqaction);
     if (!action)
@@ -706,6 +707,7 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
 
     action->dev_id = d;
     action->name = devname;
+    action->free_on_release = 1;
 
     spin_lock_irqsave(&desc->lock, flags);
     spin_lock(&gic.lock);
@@ -713,9 +715,11 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
     desc->handler = &gic_guest_irq_type;
     desc->status |= IRQ_GUEST;
 
-    gic_set_irq_properties(irq, 1, 1u << smp_processor_id(), 0xa0);
+    level = dt_irq_is_level_trigger(irq);
+
+    gic_set_irq_properties(irq->irq, level, 1u << smp_processor_id(), 0xa0);
 
-    retval = __setup_irq(desc, irq, action);
+    retval = __setup_irq(desc, irq->irq, action);
     if (retval) {
         xfree(action);
         goto out;
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index e7608dc..513c1fc 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -157,7 +157,8 @@ extern int gic_events_need_delivery(void);
 extern void __cpuinit init_maintenance_interrupt(void);
 extern void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
         unsigned int state, unsigned int priority);
-extern int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
+extern int gic_route_irq_to_guest(struct domain *d,
+                                  const struct dt_irq *irq,
                                   const char * devname);
 
 /* Accept an interrupt from the GIC and dispatch its handler */
-- 
Julien Grall

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

* [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (21 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 15:32   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
                   ` (10 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Xen can include various platform support (ie: exynos5, versatile express...)
and choose during boot time a set of callbacks for the current board.
These callbacks will be called in places where each board can have specific
code. For the moment the callbacks are:
    - platform_init: additional initialization for the platform
    - platform_init_time: some platform (ie: Exynos 5) needs to initialize
    the timer with an uncommon way
    - platform_specific_mapping: add mapping to dom0 which are not specified
    in the device tree
    - platform_reset: reset the platform
    - platform_poweroff: poweroff the platform
    - platform_quirks: list of quirks for a specific board.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - add platform_poweroff
    - add platform_quirks
---
 xen/arch/arm/Makefile          |    1 +
 xen/arch/arm/domain_build.c    |    4 ++
 xen/arch/arm/platform.c        |  137 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/setup.c           |    3 +
 xen/arch/arm/shutdown.c        |    2 +
 xen/arch/arm/time.c            |    6 ++
 xen/arch/arm/xen.lds.S         |    7 ++
 xen/include/asm-arm/platform.h |   81 ++++++++++++++++++++++++
 8 files changed, 241 insertions(+)
 create mode 100644 xen/arch/arm/platform.c
 create mode 100644 xen/include/asm-arm/platform.h

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 4955a21..2717f26 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -18,6 +18,7 @@ obj-y += p2m.o
 obj-y += percpu.o
 obj-y += guestcopy.o
 obj-y += physdev.o
+obj-y += platform.o
 obj-y += setup.o
 obj-y += time.o
 obj-y += smpboot.o
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 0b762a9..89e3ab3 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -12,6 +12,7 @@
 #include <xen/libfdt/libfdt.h>
 #include <xen/guest_access.h>
 #include <asm/setup.h>
+#include <asm/platform.h>
 
 #include <asm/gic.h>
 #include <xen/irq.h>
@@ -511,6 +512,9 @@ int construct_dom0(struct domain *d)
         return rc;
 
     map_device_from_device_tree(d);
+    rc = platform_specific_mapping(d);
+    if ( rc < 0 )
+        return rc;
 
     /* The following loads use the domain's p2m */
     p2m_load_VTTBR(d);
diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
new file mode 100644
index 0000000..b621f3a
--- /dev/null
+++ b/xen/arch/arm/platform.c
@@ -0,0 +1,137 @@
+/*
+ * xen/arch/arm/platform.c
+ *
+ * Helpers to execute platform specific code.
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (C) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/platform.h>
+#include <xen/device_tree.h>
+#include <xen/init.h>
+
+extern const struct platform_desc _splatform[], _eplatform[];
+
+/* Pointer to the current platform description */
+static const struct platform_desc *platform;
+
+
+static bool_t __init platform_is_compatible(const struct platform_desc *plat)
+{
+    const char *const *compat;
+
+    if ( !plat->compatible )
+        return 0;
+
+    for ( compat = plat->compatible; *compat; compat++ )
+    {
+        if ( dt_machine_is_compatible(*compat) )
+            return 1;
+    }
+
+    return 0;
+}
+
+/* List of possible platform */
+static void dump_platform_table(void)
+{
+    const struct platform_desc *p;
+
+    printk("Available platform support:\n");
+
+    for ( p = _splatform; p != _eplatform; p++ )
+        printk("    - %s\n", p->name);
+}
+
+int __init platform_init(void)
+{
+    int res = 0;
+
+    ASSERT(platform == NULL);
+
+    /* Looking for the platform description */
+    for ( platform = _splatform; platform != _eplatform; platform++ )
+    {
+        if ( platform_is_compatible(platform) )
+            break;
+    }
+
+    /* We don't have specific operations for this platform */
+    if ( platform == _eplatform )
+    {
+        /* TODO: List compatible */
+        printk(XENLOG_WARNING "WARNING: Unrecognized/unsupported device tree "
+              "compatible list\n");
+        dump_platform_table();
+        platform = NULL;
+    }
+    else
+        printk(XENLOG_INFO "Platform: %s\n", platform->name);
+
+    if ( platform && platform->init )
+        res = platform->init();
+
+    return res;
+}
+
+int __init platform_init_time(void)
+{
+    int res = 0;
+
+    if ( platform && platform->init_time )
+        res = platform->init_time();
+
+    return res;
+}
+
+int __init platform_specific_mapping(struct domain *d)
+{
+    int res = 0;
+
+    if ( platform && platform->specific_mapping )
+        res = platform->specific_mapping(d);
+
+    return res;
+}
+
+void platform_reset(void)
+{
+    if ( platform && platform->reset )
+        platform->reset();
+}
+
+void platform_poweroff(void)
+{
+    if ( platform && platform->poweroff )
+        platform->poweroff();
+}
+
+bool_t platform_has_quirk(uint32_t quirk)
+{
+    uint32_t quirks = 0;
+
+    if ( platform && platform->quirks )
+        quirks = platform->quirks();
+
+    return !!(quirks & quirk);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index d8a3578..a81b146 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -42,6 +42,7 @@
 #include <asm/early_printk.h>
 #include <asm/gic.h>
 #include <asm/cpufeature.h>
+#include <asm/platform.h>
 
 struct cpuinfo_arm __read_mostly boot_cpu_data;
 
@@ -440,6 +441,8 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     processor_id();
 
+    platform_init();
+
     init_xen_time();
 
     gic_init();
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index 61b5280..0903842 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -5,6 +5,7 @@
 #include <xen/lib.h>
 #include <xen/mm.h>
 #include <xen/smp.h>
+#include <asm/platform.h>
 
 static void raw_machine_reset(void)
 {
@@ -21,6 +22,7 @@ static void raw_machine_reset(void)
     dsb(); isb();
     clear_fixmap(FIXMAP_MISC);
 #endif
+    platform_reset();
 }
 
 static void halt_this_cpu(void *arg)
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index bfc41c2..1114fe7 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -33,6 +33,7 @@
 #include <asm/time.h>
 #include <asm/gic.h>
 #include <asm/cpufeature.h>
+#include <asm/platform.h>
 
 /*
  * Unfortunately the hypervisor timer interrupt appears to be buggy in
@@ -130,6 +131,11 @@ int __init init_xen_time(void)
         panic("CPU does not support the Generic Timer v1 interface.\n");
 
     cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
+
+    res = platform_init_time();
+    if ( res )
+        return res;
+
     boot_count = READ_SYSREG64(CNTPCT_EL0);
     printk("Using generic timer at %lu KHz\n", cpu_khz);
 
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index deab040..3b60668 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -77,6 +77,13 @@ SECTIONS
 #endif
 
   . = ALIGN(8);
+  .arch.info : {
+      _splatform = .;
+      *(.arch.info)
+      _eplatform = .;
+  } :text
+
+  . = ALIGN(8);
   .dev.info : {
       _sdevice = .;
       *(.dev.info)
diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
new file mode 100644
index 0000000..17e4bd5
--- /dev/null
+++ b/xen/include/asm-arm/platform.h
@@ -0,0 +1,81 @@
+#ifndef __ASM_ARM_PLATFORM_H
+#define __ASM_ARM_PLATFORM_H
+
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/mm.h>
+
+/* Describe specific operation for a board */
+struct platform_desc {
+    /* Platform name */
+    const char *name;
+    /* Array of device tree 'compatible' strings */
+    const char *const *compatible;
+    /* Platform initialization */
+    int (*init)(void);
+    int (*init_time)(void);
+    /* Specific mapping for dom0 */
+    int (*specific_mapping)(struct domain *d);
+    /* Platform reset */
+    void (*reset)(void);
+    /* Platform power-off */
+    void (*poweroff)(void);
+    /*
+     * Platform quirks
+     * Defined has a function because a platform can support multiple
+     * board with different quirk on each
+     */
+    uint32_t (*quirks)(void);
+};
+
+int __init platform_init(void);
+int __init platform_init_time(void);
+int __init platform_specific_mapping(struct domain *d);
+void platform_reset(void);
+void platform_poweroff(void);
+bool_t platform_has_quirk(uint32_t quirk);
+
+
+/* Helper to read/write a register */
+static inline uint32_t platform_read_register(uint32_t addr)
+{
+    volatile const uint32_t *reg;
+    uint32_t value;
+
+    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
+    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
+    value = *reg;
+    dsb(); isb();
+    clear_fixmap(FIXMAP_MISC);
+
+    return value;
+}
+
+static inline void platform_write_register(uint32_t addr, uint32_t value)
+{
+    volatile uint32_t *reg;
+
+    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
+    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
+    *reg = value;
+    clear_fixmap(FIXMAP_MISC);
+}
+
+#define PLATFORM_START(_name, _namestr)                         \
+static const struct platform_desc  __plat_desc_##_name __used   \
+__attribute__((__section__(".arch.info"))) = {                  \
+    .name = _namestr,
+
+#define PLATFORM_END                                            \
+};
+
+#endif /* __ASM_ARM_PLATFORM_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Julien Grall

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

* [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (22 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08 15:54   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 25/33] xen/arm: Add versatile express platform Julien Grall
                   ` (9 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Currently xen doesn't implement SYS MMU. When a device will talk with dom0
with DMA request the domain will use GFN instead of MFN.
For instance on the arndale board, without this patch the network doesn't
work.

The 1:1 mapping is a workaround and MUST be remove as soon as a SYS MMU is
implemented in XEN.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Add quirk in platform code to only enable 1:1 mapping if the
    board really need it to run (ie: SYS MMU is not yet implemented in Xen).
---
 xen/arch/arm/domain_build.c    |   41 ++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/platform.h |    6 ++++++
 2 files changed, 47 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 89e3ab3..6774033 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -62,6 +62,43 @@ struct vcpu *__init alloc_dom0_vcpu0(void)
     return alloc_vcpu(dom0, 0, 0);
 }
 
+static int set_memory_reg_11(struct domain *d, struct kernel_info *kinfo,
+                             const void *fdt, const u32 *cell, int len,
+                             int address_cells, int size_cells, u32 *new_cell)
+{
+    int reg_size = (address_cells + size_cells) * sizeof(*cell);
+    paddr_t start;
+    paddr_t size;
+    struct page_info *pg;
+    unsigned int order = get_order_from_bytes(dom0_mem);
+    int res;
+    paddr_t spfn;
+
+    pg = alloc_domheap_pages(d, order, 0);
+    if ( !pg )
+        panic("Failed to allocate contiguous memory for dom0\n");
+
+    spfn = page_to_mfn(pg);
+    start = spfn << PAGE_SHIFT;
+    size = (1 << order) << PAGE_SHIFT;
+
+    // 1:1 mapping
+    printk("Populate P2M %#"PRIx64"->%#"PRIx64" (1:1 mapping for dom0)\n",
+           start, start + size);
+    res = guest_physmap_add_page(d, spfn, spfn, order);
+
+    if ( res )
+        panic("Unable to add pages in DOM0: %d\n", res);
+
+    device_tree_set_reg(&new_cell, address_cells, size_cells, start, size);
+
+    kinfo->mem.bank[0].start = start;
+    kinfo->mem.bank[0].size = size;
+    kinfo->mem.nr_banks = 1;
+
+    return reg_size;
+}
+
 static int set_memory_reg(struct domain *d, struct kernel_info *kinfo,
                           const void *fdt, const u32 *cell, int len,
                           int address_cells, int size_cells, u32 *new_cell)
@@ -71,6 +108,10 @@ static int set_memory_reg(struct domain *d, struct kernel_info *kinfo,
     u64 start;
     u64 size;
 
+    if ( platform_has_quirk(PLATFORM_QUIRK_DOM0_MAPPING_11) )
+        return set_memory_reg_11(d, kinfo, fdt, cell, len, address_cells,
+                                 size_cells, new_cell);
+
     while ( kinfo->unassigned_mem > 0 && l + reg_size <= len
             && kinfo->mem.nr_banks < NR_MEM_BANKS )
     {
diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
index 17e4bd5..436bde1 100644
--- a/xen/include/asm-arm/platform.h
+++ b/xen/include/asm-arm/platform.h
@@ -28,6 +28,12 @@ struct platform_desc {
     uint32_t (*quirks)(void);
 };
 
+/*
+ * Quirk to map dom0 memory in 1:1
+ * Usefull on platform where System MMU is not yet implemented
+ */
+#define PLATFORM_QUIRK_DOM0_MAPPING_11 (1 << 0)
+
 int __init platform_init(void);
 int __init platform_init_time(void);
 int __init platform_specific_mapping(struct domain *d);
-- 
Julien Grall

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

* [PATCH V2 25/33] xen/arm: Add versatile express platform
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (23 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  2:33 ` [PATCH V2 26/33] xen/arm: remove request_irq Julien Grall
                   ` (8 subsequent siblings)
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

This platform contains nearly nothing specific except the reset function.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v2:
    - Add TODO to retrieve reset base address in the DT
---
 xen/arch/arm/platforms/vexpress.c        |   30 ++++++++++++++++++++++++++++++
 xen/arch/arm/shutdown.c                  |   14 --------------
 xen/include/asm-arm/config.h             |    3 ---
 xen/include/asm-arm/platforms/vexpress.h |    3 +++
 4 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/platforms/vexpress.c b/xen/arch/arm/platforms/vexpress.c
index fd4ce74..c51abf2 100644
--- a/xen/arch/arm/platforms/vexpress.c
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -18,6 +18,7 @@
  */
 
 #include <asm/platforms/vexpress.h>
+#include <asm/platform.h>
 #include <xen/mm.h>
 
 #define DCC_SHIFT      26
@@ -91,6 +92,35 @@ out:
 }
 
 /*
+ * TODO: Get base address from the device tree
+ * See arm,vexpress-reset node
+ */
+static void vexpress_reset(void)
+{
+    /* Use the SP810 system controller to force a reset */
+    volatile uint32_t *sp810;
+    set_fixmap(FIXMAP_MISC, SP810_ADDRESS >> PAGE_SHIFT, DEV_SHARED);
+    sp810 = ((uint32_t *)
+             (FIXMAP_ADDR(FIXMAP_MISC) + (SP810_ADDRESS & ~PAGE_MASK)));
+    sp810[0] = 0x3; /* switch to slow mode */
+    dsb(); isb();
+    sp810[1] = 0x1; /* writing any value to SCSYSSTAT reg will reset system */
+    dsb(); isb();
+    clear_fixmap(FIXMAP_MISC);
+}
+
+static const char const *vexpress_dt_compat[] __initdata =
+{
+    "arm,vexpress",
+    NULL
+};
+
+PLATFORM_START(vexpress, "VERSATILE EXPRESS")
+    .compatible = vexpress_dt_compat,
+    .reset = vexpress_reset,
+PLATFORM_END
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/arch/arm/shutdown.c b/xen/arch/arm/shutdown.c
index 0903842..767cc12 100644
--- a/xen/arch/arm/shutdown.c
+++ b/xen/arch/arm/shutdown.c
@@ -3,25 +3,11 @@
 #include <xen/cpu.h>
 #include <xen/delay.h>
 #include <xen/lib.h>
-#include <xen/mm.h>
 #include <xen/smp.h>
 #include <asm/platform.h>
 
 static void raw_machine_reset(void)
 {
-    /* XXX get this from device tree */
-#ifdef SP810_ADDRESS
-    /* Use the SP810 system controller to force a reset */
-    volatile uint32_t *sp810;
-    set_fixmap(FIXMAP_MISC, SP810_ADDRESS >> PAGE_SHIFT, DEV_SHARED);
-    sp810 = ((uint32_t *)
-             (FIXMAP_ADDR(FIXMAP_MISC) + (SP810_ADDRESS & ~PAGE_MASK)));
-    sp810[0] = 0x3; /* switch to slow mode */
-    dsb(); isb();
-    sp810[1] = 0x1; /* writing any value to SCSYSSTAT reg will reset system */
-    dsb(); isb();
-    clear_fixmap(FIXMAP_MISC);
-#endif
     platform_reset();
 }
 
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 8ed72f5..7599202 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -149,9 +149,6 @@ extern unsigned long frametable_virt_end;
 #define GIC_CR_OFFSET 0x2000
 #define GIC_HR_OFFSET 0x4000 /* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */
 #define GIC_VR_OFFSET 0x6000 /* Virtual Machine CPU interface) */
-/* Board-specific: base address of system controller */
-#define SP810_ADDRESS 0x1C020000
-
 
 #endif /* __ARM_CONFIG_H__ */
 /*
diff --git a/xen/include/asm-arm/platforms/vexpress.h b/xen/include/asm-arm/platforms/vexpress.h
index 67f8fef..5cf3aba 100644
--- a/xen/include/asm-arm/platforms/vexpress.h
+++ b/xen/include/asm-arm/platforms/vexpress.h
@@ -23,6 +23,9 @@
 #define V2M_SYS_CFG_OSC4      4
 #define V2M_SYS_CFG_OSC5      5
 
+/* Board-specific: base address of system controller */
+#define SP810_ADDRESS 0x1C020000
+
 #ifndef __ASSEMBLY__
 #include <xen/inttypes.h>
 
-- 
Julien Grall

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

* [PATCH V2 26/33] xen/arm: remove request_irq
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (24 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 25/33] xen/arm: Add versatile express platform Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09  9:59   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 27/33] xen/arm: remove setup_irq Julien Grall
                   ` (7 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

All calls to this function in ARM code have been removed. This function SHOULD
not be used. If someone calls this function, a linking error will occur.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/irq.c |   11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 0b7a75f..0fbd3d1 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -97,13 +97,6 @@ int __init request_dt_irq(const struct dt_irq *irq,
         void (*handler)(int, void *, struct cpu_user_regs *),
         unsigned long irqflags, const char *devname, void *dev_id)
 {
-    return request_irq(irq->irq, handler, irqflags, devname, dev_id);
-}
-
-int __init request_irq(unsigned int irq,
-        void (*handler)(int, void *, struct cpu_user_regs *),
-        unsigned long irqflags, const char * devname, void *dev_id)
-{
     struct irqaction *action;
     int retval;
 
@@ -113,7 +106,7 @@ int __init request_irq(unsigned int irq,
      * which interrupt is which (messes up the interrupt freeing
      * logic etc).
      */
-    if (irq >= nr_irqs)
+    if (irq->irq >= nr_irqs)
         return -EINVAL;
     if (!handler)
         return -EINVAL;
@@ -127,7 +120,7 @@ int __init request_irq(unsigned int irq,
     action->dev_id = dev_id;
     action->free_on_release = 1;
 
-    retval = setup_irq(irq, action);
+    retval = setup_dt_irq(irq, action);
     if (retval)
         xfree(action);
 
-- 
Julien Grall

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

* [PATCH V2 27/33] xen/arm: remove setup_irq
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (25 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 26/33] xen/arm: remove request_irq Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:00   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
                   ` (6 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

All calls to this function in ARM code have been removed. This function SHOULD
not be used. If someone calls this function, a linking error will occur.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/gic.c |    9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index ddad0c8..08602dd 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -553,20 +553,15 @@ static int __setup_irq(struct irq_desc *desc, unsigned int irq,
 
 int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
 {
-    return setup_irq(irq->irq, new);
-}
-
-int __init setup_irq(unsigned int irq, struct irqaction *new)
-{
     int rc;
     unsigned long flags;
     struct irq_desc *desc;
 
-    desc = irq_to_desc(irq);
+    desc = irq_to_desc(irq->irq);
 
     spin_lock_irqsave(&desc->lock, flags);
 
-    rc = __setup_irq(desc, irq, new);
+    rc = __setup_irq(desc, irq->irq, new);
 
     spin_unlock_irqrestore(&desc->lock, flags);
 
-- 
Julien Grall

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

* [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (26 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 27/33] xen/arm: remove setup_irq Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:10   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support Julien Grall
                   ` (5 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Add CONFIG_EARLY_PRINTK options in configs/arm{32,64}.mk to let the user
to choose if he wants to have early output, ie before the console is initialized.

This code is specific for each UART. When CONFIG_EARLY_PRINTK is enabled,
Xen will only be able to run on a board with this UART.

If a developper wants to add support for a new UART, he must implement the
following assembly macro/define:
   - EALY_UART_BASE_ADDRESS: variable which contains the physical base address
   for the UART
   - early_uart_init: initialize the UART
   - early_uart_ready: check and wait until the UART can transmit a new
   character
   - early_uart_transmit: transmit a character

For more details about the parameters of each function,
see arm{32,64}/debug-pl011.inc comments.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use macro instead of function for assembly early printk API
    - Add documentation for ARM early printk
---
 docs/misc/arm/early-printk.txt     |   14 +++++++
 xen/arch/arm/Makefile              |    2 +-
 xen/arch/arm/Rules.mk              |   15 ++++++++
 xen/arch/arm/arm32/Makefile        |    5 ++-
 xen/arch/arm/arm32/debug-pl011.inc |   58 +++++++++++++++++++++++++++++
 xen/arch/arm/arm32/debug.S         |   33 +++++++++++++++++
 xen/arch/arm/arm32/head.S          |   65 ++++++++++++++++-----------------
 xen/arch/arm/arm64/Makefile        |    2 +
 xen/arch/arm/arm64/debug-pl011.inc |   59 ++++++++++++++++++++++++++++++
 xen/arch/arm/arm64/debug.S         |   33 +++++++++++++++++
 xen/arch/arm/arm64/head.S          |   71 ++++++++++++++++--------------------
 xen/arch/arm/early_printk.c        |   16 +-------
 xen/include/asm-arm/config.h       |    2 -
 xen/include/asm-arm/early_printk.h |    2 +-
 14 files changed, 284 insertions(+), 93 deletions(-)
 create mode 100644 docs/misc/arm/early-printk.txt
 create mode 100644 xen/arch/arm/arm32/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm32/debug.S
 create mode 100644 xen/arch/arm/arm64/debug-pl011.inc
 create mode 100644 xen/arch/arm/arm64/debug.S

diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early-printk.txt
new file mode 100644
index 0000000..4065811
--- /dev/null
+++ b/docs/misc/arm/early-printk.txt
@@ -0,0 +1,14 @@
+How to enable early printk
+
+Early printk can only be enabled if debug=y. You may want to enable it if
+you are debbuging code that executes before the console is initialized.
+
+Note that selecting this option will limit Xen to a single UART definition.
+Attempting to boot Xen image on a different platform *will not work*, so this
+option should not be enable for Xens that are intended to be portable.
+
+CONFIG_EARLY_PRINTK=mach
+where mach is the name of the machine:
+  - vexpress: printk with pl011 for versatile express
+
+By default early printk is disabled.
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 2717f26..87fabe1 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -2,7 +2,7 @@ subdir-$(arm32) += arm32
 subdir-$(arm64) += arm64
 subdir-y += platforms
 
-obj-y += early_printk.o
+obj-$(EARLY_PRINTK) += early_printk.o
 obj-y += cpu.o
 obj-y += domain.o
 obj-y += psci.o
diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
index a0a14e0..4af052c 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -36,3 +36,18 @@ endif
 ifneq ($(call cc-option,$(CC),-fvisibility=hidden,n),n)
 CFLAGS += -DGCC_HAS_VISIBILITY_ATTRIBUTE
 endif
+
+EARLY_PRINTK := n
+
+ifeq ($(debug),y)
+
+# Early printk for versatile express
+# TODO handle UART base address from make command line
+ifeq ($(CONFIG_EARLY_PRINTK), vexpress)
+EARLY_PRINTK := y
+EARLY_PRINTK_INC := pl011
+endif
+
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_INC=\"debug-$(EARLY_PRINTK_INC).inc\"
+endif
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index 1ad3364..6af8ca3 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -5,4 +5,7 @@ obj-y += mode_switch.o
 obj-y += proc-ca15.o
 
 obj-y += traps.o
-obj-y += domain.o
\ No newline at end of file
+obj-y += domain.o
+
+obj-$(EARLY_PRINTK) += debug.o
+obj-$(CONFIG_EARLY_PL011) += debug-pl011.o
diff --git a/xen/arch/arm/arm32/debug-pl011.inc b/xen/arch/arm/arm32/debug-pl011.inc
new file mode 100644
index 0000000..6954aeb
--- /dev/null
+++ b/xen/arch/arm/arm32/debug-pl011.inc
@@ -0,0 +1,58 @@
+/*
+ * xen/arch/arm/arm32/debug-pl011.inc
+ *
+ * PL011 specific debug code
+ *
+ * Copyright (c) 2013 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define EARLY_UART_BASE_ADDRESS 0x1c090000
+
+/* PL011 UART initialization
+ * rb: register which contains the UART base address
+ * rc: scratch register 1
+ * rd: scratch register 2 (unused here) */
+.macro early_uart_init rb, rc, rd
+        mov   \rc, #0x0
+        str   \rc, [\rb, #0x28]     /* -> UARTFBRD (Baud divisor fraction) */
+        mov   \rc, #0x4             /* 7.3728MHz / 0x4 == 16 * 115200 */
+        str   \rc, [\rb, #0x24]     /* -> UARTIBRD (Baud divisor integer) */
+        mov   \rc, #0x60            /* 8n1 */
+        str   \rc, [\rb, #0x2C]     /* -> UARTLCR_H (Line control) */
+        ldr   \rc, =0x00000301      /* RXE | TXE | UARTEN */
+        str   \rc, [\rb, #0x30]     /* -> UARTCR (Control Register) */
+.endm
+
+/* PL011 UART wait UART to be ready to transmit
+ * rb: register which contains the UART base address
+ * rc: scratch register */
+.macro early_uart_ready rb, rc
+1:
+        ldr   \rc, [\rb, #0x18]     /* <- UARTFR (Flag register) */
+        tst   \rc, #0x8             /* Check BUSY bit */
+        bne   1b                    /* Wait for the UART to be ready */
+.endm
+
+/* PL011 UART transmit character
+ * rb: register which contains the UART base address
+ * rt: register which contains the character to transmit */
+.macro early_uart_transmit rb, rt
+        str   \rt, [\rb]            /* -> UARTDR (Data Register) */
+.endm
+
+/*
+ * Local variables:
+ * mode: ASM
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/arm32/debug.S b/xen/arch/arm/arm32/debug.S
new file mode 100644
index 0000000..09e5cae
--- /dev/null
+++ b/xen/arch/arm/arm32/debug.S
@@ -0,0 +1,33 @@
+/*
+ * xen/arch/arm/arm32/debug.S
+ *
+ * Wrapper for early printk
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/config.h>
+
+#ifdef EARLY_PRINTK_INC
+#include EARLY_PRINTK_INC
+#endif
+
+.globl early_putch
+/* Print a character on the UART - this function is called by C
+ * r0: character to print */
+early_putch:
+        ldr   r1, =FIXMAP_ADDR(FIXMAP_CONSOLE)  /* r1 := VA UART base address */
+        early_uart_ready r1, r2
+        early_uart_transmit r1, r0
+        mov   pc, lr
diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
index 0b4cfde..df71a31 100644
--- a/xen/arch/arm/arm32/head.S
+++ b/xen/arch/arm/arm32/head.S
@@ -32,9 +32,13 @@
 #define PT_UPPER(x) (PT_##x & 0xf00)
 #define PT_LOWER(x) (PT_##x & 0x0ff)
 
+#if (defined (EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
+#include EARLY_PRINTK_INC
+#endif
+
 /* Macro to print a string to the UART, if there is one.
  * Clobbers r0-r3. */
-#ifdef EARLY_UART_ADDRESS
+#ifdef EARLY_PRINTK
 #define PRINT(_s)       \
         adr   r0, 98f ; \
         bl    puts    ; \
@@ -42,9 +46,9 @@
 98:     .asciz _s     ; \
         .align 2      ; \
 99:
-#else
+#else /* EARLY_PRINTK */
 #define PRINT(s)
-#endif
+#endif /* !EARLY_PRINTK */
 
         .arm
 
@@ -106,8 +110,8 @@ past_zImage:
         bne   1b
 
 boot_cpu:
-#ifdef EARLY_UART_ADDRESS
-        ldr   r11, =EARLY_UART_ADDRESS  /* r11 := UART base address */
+#ifdef EARLY_PRINTK
+        ldr   r11, =EARLY_UART_BASE_ADDRESS  /* r11 := UART base address */
         teq   r12, #0                   /* CPU 0 sets up the UART too */
         bleq  init_uart
         PRINT("- CPU ")
@@ -216,7 +220,7 @@ skip_bss:
         bne   pt_ready
 
         /* console fixmap */
-#ifdef EARLY_UART_ADDRESS
+#if defined(EARLY_PRINTK)
         ldr   r1, =xen_fixmap
         add   r1, r1, r10            /* r1 := paddr (xen_fixmap) */
         mov   r3, #0
@@ -279,7 +283,7 @@ pt_ready:
 paging:
 
 
-#ifdef EARLY_UART_ADDRESS
+#ifdef EARLY_PRINTK
         /* Use a virtual address to access the UART. */
         ldr   r11, =FIXMAP_ADDR(FIXMAP_CONSOLE)
 #endif
@@ -345,49 +349,42 @@ fail:   PRINT("- Boot failed -\r\n")
 1:      wfe
         b     1b
 
-#ifdef EARLY_UART_ADDRESS
 
-/* Bring up the UART. Specific to the PL011 UART.
+#ifdef EARLY_PRINTK
+/* Bring up the UART.
+ * r11: Early UART base address
  * Clobbers r0-r2 */
 init_uart:
-        mov   r1, #0x0
-        str   r1, [r11, #0x28]       /* -> UARTFBRD (Baud divisor fraction) */
-        mov   r1, #0x4               /* 7.3728MHz / 0x4 == 16 * 115200 */
-        str   r1, [r11, #0x24]       /* -> UARTIBRD (Baud divisor integer) */
-        mov   r1, #0x60              /* 8n1 */
-        str   r1, [r11, #0x2C]       /* -> UARTLCR_H (Line control) */
-        ldr   r1, =0x00000301        /* RXE | TXE | UARTEN */
-        str   r1, [r11, #0x30]       /* -> UARTCR (Control Register) */
+        early_uart_init r11, r1, r2
         adr   r0, 1f
-        b     puts
+        b     puts                  /* Jump to puts */
 1:      .asciz "- UART enabled -\r\n"
         .align 4
 
-/* Print early debug messages.  Specific to the PL011 UART.
+/* Print early debug messages.
  * r0: Nul-terminated string to print.
- * Clobbers r0-r2 */
+ * r11: Early UART base address
+ * Clobber r1 */
 puts:
-        ldr   r2, [r11, #0x18]       /* <- UARTFR (Flag register) */
-        tst   r2, #0x8               /* Check BUSY bit */
-        bne   puts                   /* Wait for the UART to be ready */
-        ldrb  r2, [r0], #1           /* Load next char */
-        teq   r2, #0                 /* Exit on nul */
+        early_uart_ready r11, r1
+        ldrb  r1, [r0], #1           /* Load next char */
+        teq   r1, #0                 /* Exit on nul */
         moveq pc, lr
-        str   r2, [r11]              /* -> UARTDR (Data Register) */
-        b     puts
+        early_uart_transmit r11, r1
+        b puts
 
 /* Print a 32-bit number in hex.  Specific to the PL011 UART.
  * r0: Number to print.
- * clobbers r0-r3 */
+ * r11: Early UART base address
+ * clobbers r1-r3 */
 putn:
         adr   r1, hex
         mov   r3, #8
-1:      ldr   r2, [r11, #0x18]       /* <- UARTFR (Flag register) */
-        tst   r2, #0x8               /* Check BUSY bit */
-        bne   1b                     /* Wait for the UART to be ready */
+1:
+        early_uart_ready r11, r2
         and   r2, r0, #0xf0000000    /* Mask off the top nybble */
         ldrb  r2, [r1, r2, lsr #28]  /* Convert to a char */
-        str   r2, [r11]              /* -> UARTDR (Data Register) */
+        early_uart_transmit r11, r2
         lsl   r0, #4                 /* Roll it through one nybble at a time */
         subs  r3, r3, #1
         bne   1b
@@ -396,7 +393,7 @@ putn:
 hex:    .ascii "0123456789abcdef"
         .align 2
 
-#else  /* EARLY_UART_ADDRESS */
+#else  /* EARLY_PRINTK */
 
 init_uart:
 .global early_puts
@@ -404,7 +401,7 @@ early_puts:
 puts:
 putn:   mov   pc, lr
 
-#endif /* EARLY_UART_ADDRESS */
+#endif /* !EARLY_PRINTK */
 
 /*
  * Local variables:
diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index be41f43..9484548 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -5,3 +5,5 @@ obj-y += mode_switch.o
 
 obj-y += traps.o
 obj-y += domain.o
+
+obj-$(EARLY_PRINTK) += debug.o
diff --git a/xen/arch/arm/arm64/debug-pl011.inc b/xen/arch/arm/arm64/debug-pl011.inc
new file mode 100644
index 0000000..ee6e0e0
--- /dev/null
+++ b/xen/arch/arm/arm64/debug-pl011.inc
@@ -0,0 +1,59 @@
+/*
+ * xen/arch/arm/arm64/debug-pl011.S
+ *
+ * PL011 specific debug code
+ *
+ * Copyright (c) 2013 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/asm_defns.h>
+
+#define EARLY_UART_BASE_ADDRESS 0x1c090000
+
+/* PL011 UART initialization
+ * xb: register which containts the UART base address
+ * c: scratch register number */
+.macro early_uart_init xb, c
+        mov   x\c, #0x0
+        strh  w\c, [\xb, #0x28]      /* -> UARTFBRD (Baud divisor fraction) */
+        mov   x\c, #0x4              /* 7.3728MHz / 0x4 == 16 * 115200 */
+        strh  w\c, [\xb, #0x24]      /* -> UARTIBRD (Baud divisor integer) */
+        mov   x\c, #0x60             /* 8n1 */
+        str   w\c, [\xb, #0x2C]      /* -> UARTLCR_H (Line control) */
+        ldr   x\c, =0x00000301       /* RXE | TXE | UARTEN */
+        str   w\c, [\xb, #0x30]      /* -> UARTCR (Control Register) */
+.endm
+
+/* PL011 UART wait UART to be ready to transmit
+ * xb: register which contains the UART base address
+ * c: scratch register number */
+.macro early_uart_ready xb, c
+1:
+        ldrh  w\c, [\xb, #0x18]      /* <- UARTFR (Flag register) */
+        tst   w\c, #0x8              /* Check BUSY bit */
+        b.ne  1b                     /* Wait for the UART to be ready */
+.endm
+
+/* PL011 UART transmit character
+ * xb: register which contains the UART base address
+ * wt: register which contains the character to transmit */
+.macro early_uart_transmit xb, wt
+        strb  \wt, [\xb]             /* -> UARTDR (Data Register) */
+.endm
+
+/*
+ * Local variables:
+ * mode: ASM
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/arm64/debug.S b/xen/arch/arm/arm64/debug.S
new file mode 100644
index 0000000..48a6567
--- /dev/null
+++ b/xen/arch/arm/arm64/debug.S
@@ -0,0 +1,33 @@
+/*
+ * xen/arch/arm/arm64/debug.S
+ *
+ * Wrapper for early printk
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/config.h>
+
+#ifdef EARLY_PRINTK_INC
+#include EARLY_PRINTK_INC
+#endif
+
+.globl early_putch
+/* Print a character on the UART - this function is called by C
+ * x0: character to print */
+early_putch:
+        ldr   x23, =FIXMAP_ADDR(FIXMAP_CONSOLE)
+        early_uart_ready x23, 1
+        early_uart_transmit x23, w0
+        ret
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index ef02899..df58471 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -29,9 +29,13 @@
 #define PT_DEV    0xe71 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=0 P=1 */
 #define PT_DEV_L3 0xe73 /* nG=1 AF=1 SH=10 AP=01 NS=1 ATTR=100 T=1 P=1 */
 
+#if (defined (EARLY_PRINTK)) && (defined (EARLY_PRINTK_INC))
+#include EARLY_PRINTK_INC
+#endif
+
 /* Macro to print a string to the UART, if there is one.
- * Clobbers r0-r3. */
-#ifdef EARLY_UART_ADDRESS
+ * Clobbers x0-x3. */
+#ifdef EARLY_PRINTK
 #define PRINT(_s)       \
         adr   x0, 98f ; \
         bl    puts    ; \
@@ -39,9 +43,9 @@
 98:     .asciz _s     ; \
         .align 2      ; \
 99:
-#else
+#else /* EARLY_PRINTK */
 #define PRINT(s)
-#endif
+#endif /* !EARLY_PRINTK */
 
         /*.aarch64*/
 
@@ -109,8 +113,8 @@ real_start:
 2:
 
 boot_cpu:
-#ifdef EARLY_UART_ADDRESS
-        ldr   x23, =EARLY_UART_ADDRESS  /* x23 := UART base address */
+#ifdef EARLY_PRINTK
+        ldr   x23, =EARLY_UART_BASE_ADDRESS /* x23 := UART base address */
         cbnz  x22, 1f
         bl    init_uart                 /* CPU 0 sets up the UART too */
 1:      PRINT("- CPU ")
@@ -206,7 +210,6 @@ skip_bss:
         mov   x4, x1                 /* Next level into xen_first */
 
        /* console fixmap */
-#ifdef EARLY_UART_ADDRESS
         ldr   x1, =xen_fixmap
         add   x1, x1, x20            /* x1 := paddr (xen_fixmap) */
         lsr   x2, x23, #12
@@ -214,7 +217,6 @@ skip_bss:
         mov   x3, #PT_DEV_L3
         orr   x2, x2, x3             /* x2 := 4K dev map including UART */
         str   x2, [x1, #(FIXMAP_CONSOLE*8)] /* Map it in the first fixmap's slot */
-#endif
 
         /* Build the baseline idle pagetable's first-level entries */
         ldr   x1, =xen_second
@@ -266,10 +268,8 @@ pt_ready:
         br    x1                     /* Get a proper vaddr into PC */
 paging:
 
-#ifdef EARLY_UART_ADDRESS
         /* Use a virtual address to access the UART. */
         ldr   x23, =FIXMAP_ADDR(FIXMAP_CONSOLE)
-#endif
 
         PRINT("- Ready -\r\n")
 
@@ -329,51 +329,44 @@ fail:   PRINT("- Boot failed -\r\n")
 1:      wfe
         b     1b
 
-#ifdef EARLY_UART_ADDRESS
+#ifdef EARLY_PRINTK
 
-/* Bring up the UART. Specific to the PL011 UART.
- * Clobbers r0-r2 */
+/* Bring up the UART.
+ * x23: Early UART base address
+ * Clobbers x0-x1 */
 init_uart:
-        mov   x1, #0x0
-        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor fraction) */
-        mov   x1, #0x4               /* 7.3728MHz / 0x4 == 16 * 115200 */
-        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor integer) */
-        mov   x1, #0x60              /* 8n1 */
-        strh  w1, [x23, #0x24]       /* -> UARTLCR_H (Line control) */
-        ldr   x1, =0x00000301        /* RXE | TXE | UARTEN */
-        strh  w1, [x23, #0x30]       /* -> UARTCR (Control Register) */
+        early_uart_init x23, 0
         adr   x0, 1f
-        b     puts
+        b     puts                   /* Jump to puts */
 1:      .asciz "- UART enabled -\r\n"
         .align 4
 
-/* Print early debug messages.  Specific to the PL011 UART.
- * r0: Nul-terminated string to print.
- * Clobbers r0-r2 */
+/* Print early debug messages.
+ * x0: Nul-terminated string to print.
+ * x23: Early UART base address
+ * Clobber x1 */
 puts:
-        ldrh  w2, [x23, #0x18]       /* <- UARTFR (Flag register) */
-        tst   w2, #0x8               /* Check BUSY bit */
-        b.ne  puts                   /* Wait for the UART to be ready */
-        ldrb  w2, [x0], #1           /* Load next char */
-        cbz   w2, 1f                 /* Exit on nul */
-        str   w2, [x23]              /* -> UARTDR (Data Register) */
+        early_uart_ready x23, 1
+        ldrb  w1, [x0], #1           /* Load next char */
+        cbz   w1, 1f                 /* Exit on nul */
+        early_uart_transmit x23, w1
         b     puts
 1:
         ret
 
 /* Print a 32-bit number in hex.  Specific to the PL011 UART.
- * r0: Number to print.
- * clobbers r0-r3 */
+ * x0: Number to print.
+ * x23: Early UART base address
+ * clobbers x1-x3 */
 putn:
         adr   x1, hex
         mov   x3, #8
-1:      ldrh  w2, [x23, #0x18]       /* <- UARTFR (Flag register) */
-        tst   w2, #0x8               /* Check BUSY bit */
-        b.ne  1b                     /* Wait for the UART to be ready */
+1:
+        early_uart_ready x23, 2
         and   x2, x0, #0xf0000000    /* Mask off the top nybble */
         lsr   x2, x2, #28
         ldrb  w2, [x1, x2]           /* Convert to a char */
-        strb  w2, [x23]              /* -> UARTDR (Data Register) */
+        early_uart_transmit x23, w2
         lsl   x0, x0, #4             /* Roll it through one nybble at a time */
         subs  x3, x3, #1
         b.ne  1b
@@ -382,7 +375,7 @@ putn:
 hex:    .ascii "0123456789abcdef"
         .align 2
 
-#else  /* EARLY_UART_ADDRESS */
+#else  /* EARLY_PRINTK */
 
 init_uart:
 .global early_puts
@@ -390,4 +383,4 @@ early_puts:
 puts:
 putn:   ret
 
-#endif /* EARLY_UART_ADDRESS */
+#endif /* EARLY_PRINTK */
diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
index 0f99a43..5950323 100644
--- a/xen/arch/arm/early_printk.c
+++ b/xen/arch/arm/early_printk.c
@@ -15,19 +15,7 @@
 #include <xen/string.h>
 #include <asm/early_printk.h>
 
-#ifdef EARLY_UART_ADDRESS
-
-void __init early_putch(char c)
-{
-    volatile uint32_t *r;
-
-    r = (uint32_t *)(XEN_VIRT_START + (1 << 21));
-
-    /* XXX: assuming a PL011 UART. */
-    while(*(r + 0x6) & 0x8)
-        ;
-    *r = c;
-}
+void early_putch(char c);
 
 /* Early printk buffer */
 static char __initdata buf[512];
@@ -68,5 +56,3 @@ early_panic(const char *fmt, ...)
 
     while(1);
 }
-
-#endif /* #ifdef EARLY_UART_ADDRESS */
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 7599202..6414c89 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -141,8 +141,6 @@ extern unsigned long frametable_virt_end;
 #define watchdog_disable() ((void)0)
 #define watchdog_enable()  ((void)0)
 
-/* Board-specific: base address of PL011 UART */
-#define EARLY_UART_ADDRESS 0x1c090000
 /* Board-specific: base address of GIC + its regs */
 #define GIC_BASE_ADDRESS 0x2c000000
 #define GIC_DR_OFFSET 0x1000
diff --git a/xen/include/asm-arm/early_printk.h b/xen/include/asm-arm/early_printk.h
index a0297a7..b72fce7 100644
--- a/xen/include/asm-arm/early_printk.h
+++ b/xen/include/asm-arm/early_printk.h
@@ -12,7 +12,7 @@
 
 #include <xen/config.h>
 
-#ifdef EARLY_UART_ADDRESS
+#ifdef EARLY_PRINTK
 
 void early_printk(const char *fmt, ...);
 void early_panic(const char *fmt, ...) __attribute__((noreturn));
-- 
Julien Grall

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

* [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (27 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:13   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
                   ` (4 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel
  Cc: Anthony PERARD, patches, ian.campbell, Julien Grall, Stefano.Stabellini

From: Anthony PERARD <anthony.perard@citrix.com>

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use defines where it's possible
    - Move UART definition in a separate header. Will be used for early
    UART
    - Replace all  // by /* ... */
    - Add Anthony as first author
---
 config/arm32.mk                       |    1 +
 xen/drivers/char/Makefile             |    1 +
 xen/drivers/char/exynos4210-uart.c    |  357 +++++++++++++++++++++++++++++++++
 xen/include/asm-arm/exynos4210-uart.h |  111 ++++++++++
 4 files changed, 470 insertions(+)
 create mode 100644 xen/drivers/char/exynos4210-uart.c
 create mode 100644 xen/include/asm-arm/exynos4210-uart.h

diff --git a/config/arm32.mk b/config/arm32.mk
index f64f0c1..d8e958b 100644
--- a/config/arm32.mk
+++ b/config/arm32.mk
@@ -8,6 +8,7 @@ CONFIG_ARM_$(XEN_OS) := y
 CFLAGS += -marm
 
 HAS_PL011 := y
+HAS_EXYNOS4210 := y
 
 # Use only if calling $(LD) directly.
 #LDFLAGS_DIRECT_OpenBSD = _obsd
diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
index e68a54a..0edd103 100644
--- a/xen/drivers/char/Makefile
+++ b/xen/drivers/char/Makefile
@@ -1,6 +1,7 @@
 obj-y += console.o
 obj-$(HAS_NS16550) += ns16550.o
 obj-$(HAS_PL011) += pl011.o
+obj-$(HAS_EXYNOS4210) += exynos4210-uart.o
 obj-$(HAS_EHCI) += ehci-dbgp.o
 obj-$(CONFIG_ARM) += arm-uart.o
 obj-y += serial.o
diff --git a/xen/drivers/char/exynos4210-uart.c b/xen/drivers/char/exynos4210-uart.c
new file mode 100644
index 0000000..5cde0f6
--- /dev/null
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -0,0 +1,357 @@
+/*
+ * xen/drivers/char/exynos4210-uart.c
+ *
+ * Driver for Exynos 4210 UART.
+ *
+ * Anthony PERARD <anthony.perard@citrix.com>
+ * Copyright (c) 2012 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/console.h>
+#include <xen/errno.h>
+#include <xen/serial.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <asm/early_printk.h>
+#include <asm/device.h>
+#include <asm/exynos4210-uart.h>
+
+static struct exynos4210_uart {
+    unsigned int baud, clock_hz, data_bits, parity, stop_bits;
+    struct dt_irq irq;
+    volatile unsigned char *regs;
+    struct irqaction irqaction;
+} exynos4210_com[2] = {{0}};
+
+/* These parity settings can be ORed directly into the ULCON. */
+#define PARITY_NONE  (0)
+#define PARITY_ODD   (0x4)
+#define PARITY_EVEN  (0x5)
+#define FORCED_CHECKED_AS_ONE (0x6)
+#define FORCED_CHECKED_AS_ZERO (0x7)
+
+static inline uint32_t exynos4210_read(const struct exynos4210_uart *uart,
+                                       size_t offset)
+{
+    return *(uint32_t *)(uart->regs + offset);
+}
+
+static inline void exynos4210_write(const struct exynos4210_uart *uart,
+                                    size_t offset, uint32_t value)
+{
+    *(uint32_t *)(uart->regs + offset) = value;
+}
+
+static void exynos4210_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
+{
+    struct serial_port *port = data;
+    struct exynos4210_uart *uart = port->uart;
+    unsigned int status;
+
+    status = exynos4210_read(uart, UINTP);
+
+    while ( status != 0 )
+    {
+        /* Clear all pending interrupts
+         * but should take care of ERROR and MODEM
+         */
+
+        if ( status & UINTM_ERROR )
+        {
+            uint32_t error_bit;
+
+            error_bit = exynos4210_read(uart, UERSTAT);
+
+            if ( error_bit & UERSTAT_OVERRUN )
+                dprintk(XENLOG_ERR, "uart: overrun error\n");
+            if ( error_bit & UERSTAT_PARITY )
+                dprintk(XENLOG_ERR, "uart: parity error\n");
+            if ( error_bit & UERSTAT_FRAME )
+                dprintk(XENLOG_ERR, "uart: frame error\n");
+            if ( error_bit & UERSTAT_BREAK )
+                dprintk(XENLOG_ERR, "uart: break detected\n");
+            /* Clear error pending interrupt */
+            exynos4210_write(uart, UINTP, UINTM_ERROR);
+        }
+
+
+        if ( status & (UINTM_RXD | UINTM_ERROR) )
+        {
+            /* uart->regs[UINTM] |= RXD|ERROR; */
+            serial_rx_interrupt(port, regs);
+            /* uart->regs[UINTM] &= ~(RXD|ERROR); */
+            exynos4210_write(uart, UINTP, UINTM_RXD | UINTM_ERROR);
+        }
+
+        if ( status & (UINTM_TXD | UINTM_MODEM) )
+        {
+            /* uart->regs[UINTM] |= TXD|MODEM; */
+            serial_tx_interrupt(port, regs);
+            /* uart->regs[UINTM] &= ~(TXD|MODEM); */
+            exynos4210_write(uart, UINTP, UINTM_TXD | UINTM_MODEM);
+        }
+
+        status = exynos4210_read(uart, UINTP);
+    }
+}
+
+static void __init exynos4210_uart_init_preirq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+    unsigned int divisor;
+    uint32_t ulcon;
+
+    /* reset, TX/RX disables */
+    exynos4210_write(uart, UCON, 0);
+
+    /* No Interrupt, auto flow control */
+    exynos4210_write(uart, UMCON, 0);
+
+    /* Line control and baud-rate generator. */
+    if ( uart->baud != BAUD_AUTO )
+    {
+        /* Baud rate specified: program it into the divisor latch. */
+        divisor = ((uart->clock_hz) / (uart->baud)) - 1;
+        /* FIXME: will use a hacked divisor, assuming the src clock and bauds */
+        exynos4210_write(uart, UFRACVAL, 53);
+        exynos4210_write(uart, UBRDIV, 4);
+    }
+    else
+    {
+        /* TODO: should be updated */
+        /* Baud rate already set: read it out from the divisor latch. */
+#if 0
+        divisor = (uart->regs[IBRD] << 6) | uart->regs[FBRD];
+        uart->baud = (uart->clock_hz << 2) / divisor;
+#endif
+    }
+
+    /*
+     * Number of bits per character
+     * 0 => 5 bits
+     * 1 => 6 bits
+     * 2 => 7 bits
+     * 3 => 8 bits
+     */
+    ASSERT(uart->data_bits >= 5 && uart->data_bits <= 8);
+    ulcon = (uart->data_bits - 5);
+
+    /*
+     * Stop bits
+     * 0 => 1 stop bit per frame
+     * 1 => 2 stop bit per frame
+     */
+    ASSERT(uart->stop_bits >= 1 && uart->stop_bits <= 2);
+    ulcon |= (uart->stop_bits - 1) << ULCON_STOPB_SHIFT;
+
+
+    /* Parity */
+    ulcon |= uart->parity << ULCON_PARITY_SHIFT;
+
+    exynos4210_write(uart, ULCON, ulcon);
+
+    /* Mask and clear the interrupts */
+    exynos4210_write(uart, UINTM, UINTM_ALLI);
+    exynos4210_write(uart, UINTP, UINTM_ALLI);
+
+    /* reset FIFO */
+    exynos4210_write(uart, UFCON, UFCON_FIFO_RESET);
+
+    /* TODO: Add timeout to avoid infinite loop */
+    while ( exynos4210_read(uart, UFCON) & UFCON_FIFO_RESET )
+        ;
+
+    /*
+     * Enable FIFO and set the trigger level of Tx FIFO
+     * The trigger level is always set to b101, an interrupt will be
+     * generated when data count of Tx FIFO is less than or equal to the
+     * following value:
+     * UART0 => 160 bytes
+     * UART1 => 40 bytes
+     * UART2 => 10 bytes
+     * UART3 => 10 bytes
+     */
+    exynos4210_write(uart, UFCON, UFCON_FIFO_TX_TRIGGER | UFCON_FIFO_EN);
+
+    /*
+     * Enable the UART for Rx and Tx
+     *   - Use only interrupt request
+     *   - Interrupts are level trigger
+     *   - Enable Rx timeout
+     */
+    exynos4210_write(uart, UCON,
+                     UCON_RX_IRQ_LEVEL | UCON_TX_IRQ_LEVEL | UCON_RX_IRQ |
+                     UCON_TX_IRQ | UCON_RX_TIMEOUT);
+}
+
+static void __init exynos4210_uart_init_postirq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+    int rc;
+
+    uart->irqaction.handler = exynos4210_uart_interrupt;
+    uart->irqaction.name    = "exynos4210_uart";
+    uart->irqaction.dev_id  = port;
+
+    if ( (rc = setup_dt_irq(&uart->irq, &uart->irqaction)) != 0 )
+        dprintk(XENLOG_ERR, "Failed to allocated exynos4210_uart IRQ %d\n",
+                uart->irq.irq);
+
+    /* Unmask interrupts */
+    exynos4210_write(uart, UINTM, ~UINTM_ALLI);
+
+    /* Clear pending interrupts */
+    exynos4210_write(uart, UINTP, UINTM_ALLI);
+
+    /* Enable interrupts */
+    exynos4210_write(uart, UMCON, exynos4210_read(uart, UMCON) | UMCON_INT_EN);
+}
+
+static void exynos4210_uart_suspend(struct serial_port *port)
+{
+    BUG(); // XXX
+}
+
+static void exynos4210_uart_resume(struct serial_port *port)
+{
+    BUG(); // XXX
+}
+
+static unsigned int exynos4210_uart_tx_ready(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    /* Tx fifo full ? */
+    if ( exynos4210_read(uart, UFSTAT) & UFSTAT_TX_FULL )
+        return 0;
+    else
+    {
+        uint32_t val = exynos4210_read(uart, UFSTAT);
+
+        val = (val & UFSTAT_TX_COUNT_MASK) >> UFSTAT_TX_COUNT_SHIFT;
+
+        /* XXX: Here we assume that we use UART 2/3, on the others
+         * UART the buffer is bigger
+         */
+        ASSERT(val >= 0 && val <= FIFO_MAX_SIZE);
+
+        return (FIFO_MAX_SIZE - val);
+    }
+}
+
+static void exynos4210_uart_putc(struct serial_port *port, char c)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    exynos4210_write(uart, UTXH, (uint32_t)(unsigned char)c);
+}
+
+static int exynos4210_uart_getc(struct serial_port *port, char *pc)
+{
+    struct exynos4210_uart *uart = port->uart;
+    uint32_t ufstat = exynos4210_read(uart, UFSTAT);
+    uint32_t count;
+
+    count = (ufstat & UFSTAT_RX_COUNT_MASK) >> UFSTAT_RX_COUNT_SHIFT;
+
+    /* Check if Rx fifo is full or if the is something in it */
+    if ( ufstat & UFSTAT_RX_FULL || count )
+    {
+        *pc = exynos4210_read(uart, URXH) & URXH_DATA_MASK;
+        return 1;
+    }
+    else
+        return 0;
+}
+
+static int __init exynos4210_uart_irq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    return uart->irq.irq;
+}
+
+static const struct dt_irq __init *exynos4210_uart_dt_irq(struct serial_port *port)
+{
+    struct exynos4210_uart *uart = port->uart;
+
+    return &uart->irq;
+}
+
+static struct uart_driver __read_mostly exynos4210_uart_driver = {
+    .init_preirq  = exynos4210_uart_init_preirq,
+    .init_postirq = exynos4210_uart_init_postirq,
+    .endboot      = NULL,
+    .suspend      = exynos4210_uart_suspend,
+    .resume       = exynos4210_uart_resume,
+    .tx_ready     = exynos4210_uart_tx_ready,
+    .putc         = exynos4210_uart_putc,
+    .getc         = exynos4210_uart_getc,
+    .irq          = exynos4210_uart_irq,
+    .dt_irq_get   = exynos4210_uart_dt_irq,
+};
+
+static int __init exynos4210_uart_init(struct dt_device_node *dev,
+                                       const void *data)
+{
+    const struct serial_arm_defaults *defaults = data;
+    struct exynos4210_uart *uart;
+    int res;
+
+    if ( (defaults->index < 0) || (defaults->index > 1) )
+        return -EINVAL;
+
+    uart = &exynos4210_com[defaults->index];
+
+    /* uart->clock_hz  = 0x16e3600; */
+    uart->baud      = BAUD_AUTO;//115200;
+    uart->data_bits = 8;
+    uart->parity    = PARITY_NONE;
+    uart->stop_bits = 1;
+    uart->regs      = (unsigned char *)defaults->register_base_address;
+
+    res = dt_device_get_irq(dev, 0, &uart->irq);
+    if ( res )
+    {
+        early_printk("exynos4210: Unable to retrieve the IRQ\n");
+        return res;
+    }
+
+    /* Register with generic serial driver. */
+    serial_register_uart(uart - exynos4210_com, &exynos4210_uart_driver, uart);
+
+    dt_device_set_used_by(dev, DT_USED_BY_XEN);
+
+    return 0;
+}
+
+static const char const *exynos4210_dt_compat[] __initdata =
+{
+    "samsung,exynos4210-uart",
+    NULL
+};
+
+DT_DEVICE_START(exynos4210, "Exynos 4210 UART", DEVICE_SERIAL)
+        .compatible = exynos4210_dt_compat,
+        .init = exynos4210_uart_init,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/exynos4210-uart.h b/xen/include/asm-arm/exynos4210-uart.h
new file mode 100644
index 0000000..1527521
--- /dev/null
+++ b/xen/include/asm-arm/exynos4210-uart.h
@@ -0,0 +1,111 @@
+/*
+ * xen/include/asm-arm/exynos4210-uart.h
+ *
+ * Common constant definition between ealry printk and the UART driver
+ * for the exynos 4210 UART
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_EXYNOS4210_H
+#define __ASM_ARM_EXYNOS4210_H
+
+
+/*
+ * this value is only valid for UART 2 and UART 3
+ * XXX: define per UART
+ */
+#define FIFO_MAX_SIZE 16
+
+/* register addresses */
+#define ULCON     (0x00)
+#define UCON      (0x04)
+#define UFCON     (0x08)
+#define UMCON     (0x0c)
+#define UTRSTAT   (0x10)
+#define UERSTAT   (0x14)
+#define UFSTAT    (0x18)
+#define UMSTAT    (0x1c)
+#define UTXH      (0x20)
+#define URXH      (0x24)
+#define UBRDIV    (0x28)
+#define UFRACVAL  (0x2c)
+#define UINTP     (0x30)
+#define UINTS     (0x34)
+#define UINTM     (0x38)
+
+/* UCON */
+#define UCON_RX_IRQ         (1 << 0)
+#define UCON_TX_IRQ         (1 << 2)
+#define UCON_RX_TIMEOUT     (1 << 7)
+
+/*
+ * FIXME: IRQ_LEVEL should be 1 << n but with this value, the IRQ
+ * handler will never end...
+ */
+#define UCON_RX_IRQ_LEVEL   (0 << 8)
+#define UCON_TX_IRQ_LEVEL   (0 << 9)
+
+/* ULCON */
+#define ULCON_STOPB_SHIFT 2
+#define ULCON_PARITY_SHIFT 3
+
+/* UFCON */
+#define UFCON_FIFO_TX_RESET     (1 << 2)
+#define UFCON_FIFO_RX_RESET     (1 << 1)
+#define UFCON_FIFO_RESET        (UFCON_FIFO_TX_RESET | UFCON_FIFO_RX_RESET)
+#define UFCON_FIFO_EN           (1 << 0)
+
+#define UFCON_FIFO_TX_TRIGGER   (0x6 << 8)
+
+/* UMCON */
+#define UMCON_INT_EN            (1 << 3)
+
+/* UERSTAT */
+#define UERSTAT_OVERRUN (1 << 0)
+#define UERSTAT_PARITY  (1 << 1)
+#define UERSTAT_FRAME   (1 << 2)
+#define UERSTAT_BREAK   (1 << 3)
+
+/* UFSTAT */
+#define UFSTAT_TX_FULL          (1 << 24)
+#define UFSTAT_TX_COUNT_SHIFT   (16)
+#define UFSTAT_TX_COUNT_MASK    (0xff << UFSTAT_TX_COUNT_SHIFT)
+#define UFSTAT_RX_FULL          (1 << 8)
+#define UFSTAT_RX_COUNT_SHIFT   (0)
+#define UFSTAT_RX_COUNT_MASK    (0xff << UFSTAT_RX_COUNT_SHIFT)
+
+/* UTRSTAT */
+#define UTRSTAT_TX_EMPTY        (1 << 1)
+
+/* URHX */
+#define URXH_DATA_MASK  (0xff)
+
+/* Interrupt bits (UINTP, UINTS, UINTM) */
+#define UINTM_MODEM     (1 << 3)
+#define UINTM_TXD       (1 << 2)
+#define UINTM_ERROR     (1 << 1)
+#define UINTM_RXD       (1 << 0)
+#define UINTM_ALLI      (UINTM_MODEM | UINTM_TXD | UINTM_ERROR | UINTM_RXD)
+
+#endif /* __ASM_ARM_EXYNOS4210_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Julien Grall

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

* [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (28 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:16   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5 Julien Grall
                   ` (3 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel
  Cc: Anthony PERARD, patches, ian.campbell, Julien Grall, Stefano.Stabellini

From: Anthony PERARD <anthony.perard@citrix.com>

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Use assembly macro instead of function
    - Add Anthony as first author
---
 docs/misc/arm/early-printk.txt          |    1 +
 xen/arch/arm/Rules.mk                   |    4 ++
 xen/arch/arm/arm32/Makefile             |    1 -
 xen/arch/arm/arm32/debug-exynos4210.inc |   77 +++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/arm32/debug-exynos4210.inc

diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early-printk.txt
index 4065811..d5cae85 100644
--- a/docs/misc/arm/early-printk.txt
+++ b/docs/misc/arm/early-printk.txt
@@ -10,5 +10,6 @@ option should not be enable for Xens that are intended to be portable.
 CONFIG_EARLY_PRINTK=mach
 where mach is the name of the machine:
   - vexpress: printk with pl011 for versatile express
+  - exynos5250: printk with the second UART
 
 By default early printk is disabled.
diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
index 4af052c..cff834e 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -47,6 +47,10 @@ ifeq ($(CONFIG_EARLY_PRINTK), vexpress)
 EARLY_PRINTK := y
 EARLY_PRINTK_INC := pl011
 endif
+ifeq ($(CONFIG_EARLY_PRINTK), exynos5250)
+EARLY_PRINTK := y
+EARLY_PRINTK_INC := exynos4210
+endif
 
 CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK
 CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_INC=\"debug-$(EARLY_PRINTK_INC).inc\"
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index 6af8ca3..aaf277a 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -8,4 +8,3 @@ obj-y += traps.o
 obj-y += domain.o
 
 obj-$(EARLY_PRINTK) += debug.o
-obj-$(CONFIG_EARLY_PL011) += debug-pl011.o
diff --git a/xen/arch/arm/arm32/debug-exynos4210.inc b/xen/arch/arm/arm32/debug-exynos4210.inc
new file mode 100644
index 0000000..17ee5f1
--- /dev/null
+++ b/xen/arch/arm/arm32/debug-exynos4210.inc
@@ -0,0 +1,77 @@
+/*
+ * xen/arch/arm/arm32/debug-exynos4210.inc
+ *
+ * Exynos 5 specific debug code
+ *
+ * Copyright (c) 2013 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/exynos4210-uart.h>
+
+#define EARLY_UART_BASE_ADDRESS 0x12c20000
+
+/* Exynos 5 UART initialization
+ * rb: register which containts the UART base address
+ * rc: scratch register 1
+ * rd: scratch register 2 */
+.macro early_uart_init rb rc rd
+        /* init clock */
+        ldr   \rc, =0x10020000
+        /* select MPLL (800MHz) source clock */
+        ldr   \rd, [\rc, #0x250]
+        and   \rd, \rd, #(~(0xf<<8))
+        orr   \rd, \rd, #(0x6<<8)
+        str   \rd, [\rc, #0x250]
+        /* ratio 800/(7+1) */
+        ldr   \rd, [\rc, #0x558]
+        and   \rd, \rd, #(~(0xf<<8))
+        orr   \rd, \rd, #(0x7<<8)
+        str   \rd, [\rc, #0x558]
+
+        mov   \rc, #4
+        str   \rc, [\rb, #UFRACVAL]     /* -> UFRACVAL (Baud divisor fraction) */
+        mov   \rc, #53
+        str   \rc, [\rb, #UBRDIV]       /* -> UBRDIV (Baud divisor integer) */
+        mov   \rc, #3                   /* 8n1 */
+        str   \rc, [\rb, #ULCON]        /* -> (Line control) */
+        ldr   \rc, =UCON_TX_IRQ         /* TX IRQMODE */
+        str   \rc, [\rb, #UCON]         /* -> (Control Register) */
+        mov   \rc, #0x0
+        str   \rc, [\rb, #UFCON]        /* disable FIFO */
+        mov   \rc, #0x0
+        str   \rc, [\rb, #UMCON]        /* no auto flow control */
+.endm
+
+/* Exynos 5 UART wait UART to be ready to transmit
+ * rb: register which containts the UART base address
+ * rc: scratch register */
+.macro early_uart_ready rb rc
+1:
+        ldr   \rc, [\rb, #UTRSTAT]   /* <- UTRSTAT (Flag register) */
+        tst   \rc, #UTRSTAT_TX_EMPTY /* Check BUSY bit */
+        beq   1b                     /* Wait for the UART to be ready */
+.endm
+
+/* Exynos 5 UART transmit character
+ * rb: register which containts the UART base address
+ * rt: register which containts the character to transmit */
+.macro early_uart_transmit rb rt
+        str   \rt, [\rb, #UTXH]      /* -> UTXH (Data Register) */
+.endm
+
+/*
+ * Local variables:
+ * mode: ASM
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Julien Grall

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

* [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (29 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:19   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
                   ` (2 subsequent siblings)
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Add dom0 1:1 mapping quirk for the arndale board
    - s/mapping/mappings/ in comment
    - Remove debug trap (unnecessary with linux 3.9)
---
 xen/arch/arm/platforms/Makefile         |    1 +
 xen/arch/arm/platforms/exynos5.c        |   86 +++++++++++++++++++++++++++++++
 xen/include/asm-arm/platforms/exynos5.h |   40 ++++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 xen/arch/arm/platforms/exynos5.c
 create mode 100644 xen/include/asm-arm/platforms/exynos5.h

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 4313e95..ff2b65b 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -1 +1,2 @@
 obj-y += vexpress.o
+obj-y += exynos5.o
diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
new file mode 100644
index 0000000..8620390
--- /dev/null
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -0,0 +1,86 @@
+/*
+ * xen/arch/arm/platforms/exynos5.c
+ *
+ * Exynos5 specific settings
+ *
+ * Julien Grall <julien.grall@linaro.org>
+ * Copyright (c) 2013 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/p2m.h>
+#include <xen/config.h>
+#include <xen/device_tree.h>
+#include <xen/domain_page.h>
+#include <xen/mm.h>
+#include <asm/platforms/exynos5.h>
+#include <asm/platform.h>
+
+static int exynos5_init_time(void)
+{
+    uint32_t reg;
+
+    // enable timer on exynos5 arndale board
+    // should probably be done by u-boot
+    reg = platform_read_register(EXYNOS5_MCT_G_TCON);
+    platform_write_register(EXYNOS5_MCT_G_TCON, reg | EXYNOS5_MCT_G_TCON_START);
+
+    return 0;
+}
+
+/* Additionnal mappings for dom0 (Not in the DTS) */
+static int exynos5_specific_mapping(struct domain *d)
+{
+    /* Map the chip ID */
+    map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
+                     EXYNOS5_PA_CHIPID);
+
+    /* Map the PWM region */
+    map_mmio_regions(d, EXYNOS5_PA_TIMER,
+                     EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
+                     EXYNOS5_PA_TIMER);
+
+    return 0;
+}
+
+static void exynos5_reset(void)
+{
+    platform_write_register(EXYNOS5_SWRESET, 1);
+}
+
+static uint32_t exynos5_quirks(void)
+{
+    return PLATFORM_QUIRK_DOM0_MAPPING_11;
+}
+
+static const char const *exynos5_dt_compat[] __initdata =
+{
+    "samsung,exynos5250",
+    NULL
+};
+
+PLATFORM_START(exynos5, "SAMSUNG EXYNOS5")
+    .compatible = exynos5_dt_compat,
+    .init_time = exynos5_init_time,
+    .specific_mapping = exynos5_specific_mapping,
+    .reset = exynos5_reset,
+    .quirks = exynos5_quirks,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/platforms/exynos5.h b/xen/include/asm-arm/platforms/exynos5.h
new file mode 100644
index 0000000..d77623c
--- /dev/null
+++ b/xen/include/asm-arm/platforms/exynos5.h
@@ -0,0 +1,40 @@
+#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
+#define __ASM_ASM_PLATFORMS_EXYSNO5_H
+
+#define EXYNOS5_MCT_BASE            0x101c0000
+#define EXYNOS5_MCTREG(x)           (EXYNOS5_MCT_BASE + (x))
+#define EXYNOS5_MCT_G_TCON		    EXYNOS5_MCTREG(0x240)
+#define EXYNOS5_MCT_G_TCON_START	(1 << 8)
+
+#define EXYNOS5_PA_CHIPID           0x10000000
+#define EXYNOS5_PA_TIMER            0x12dd0000
+/* Base address of system controller */
+#define EXYNOS5_PA_PMU              0x10040000
+
+#define EXYNOS5_SWRESET             (EXYNOS5_PA_PMU + 0x0400)
+
+#define S5P_PA_SYSRAM   0x02020000
+
+/* Constants below is only used in assembly because the DTS is not yet parsed */
+#ifdef __ASSEMBLY__
+
+/* GIC Base Address */
+#define EXYNOS5_GIC_BASE_ADDRESS    0x10480000
+
+/* Timer's frequency */
+#define EXYNOS5_TIMER_FREQUENCY     (24 * 1000 * 1000) /* 24 MHz */
+
+/* Arndale machine ID */
+#define MACH_TYPE_SMDK5250          3774
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_PLATFORMS_EXYNOS5_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Julien Grall

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

* [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor for the exynos5
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (30 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5 Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-09 10:24   ` Ian Campbell
  2013-05-08  2:33 ` [PATCH V2 33/33] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
  2013-05-08  7:03 ` [PATCH V2 00/33] Support multiple ARM platforms in Xen Gihun Jung
  33 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Use machine ID to know what is the current board. This value is only given
to the first CPU by the bootloader.

When the exynos 5 starts, there is only one CPU up. Xen needs to start the
secondary cpu. The latter boots in secure mode.

Theses modifications aim to be removed as soon as possible. It should
be moved either in a platform specific boot-wrapper (which will be start
before Xen), or in the bootloader (assuming U-Boot/Grub will support SMP).

Signed-off-by: Julien Grall <julien.grall@linaro.org>

Changes in v2:
    - Add WORKAROUND keyword in the title
    - Add fall-through comment when it's needed
    - setup the spis with a while loop instead of a do-while loop
---
 xen/arch/arm/arm32/head.S                |   19 +++++++-
 xen/arch/arm/arm32/mode_switch.S         |   75 +++++++++++++++++++++++-------
 xen/include/asm-arm/platforms/vexpress.h |   11 +++++
 3 files changed, 86 insertions(+), 19 deletions(-)

diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
index df71a31..0996a6d 100644
--- a/xen/arch/arm/arm32/head.S
+++ b/xen/arch/arm/arm32/head.S
@@ -76,7 +76,7 @@ past_zImage:
         cpsid aif                    /* Disable all interrupts */
 
         /* Save the bootloader arguments in less-clobberable registers */
-        /* No need to save r1 == Unused ARM-linux machine type */
+        mov   r5, r1                 /* r5: ARM-linux machine type */
         mov   r8, r2                 /* r8 := DTB base address */
 
         /* Find out where we are */
@@ -119,11 +119,25 @@ boot_cpu:
         bl    putn
         PRINT(" booting -\r\n")
 #endif
+        /* Secondary CPUs doesn't have machine ID
+         *  - Store machine ID on boot CPU
+         *  - Load machine ID on secondary CPUs
+         * Machine ID is needed in kick_cpus and enter_hyp_mode */
+        ldr   r0, =machine_id           /* VA of machine_id */
+        add   r0, r0, r10               /* PA of machine_id */
+        teq   r12, #0
+        streq r5, [r0]                  /* On boot CPU save machine ID */
+        ldrne r5, [r0]                  /* If non boot cpu r5 := machine ID */
 
         /* Wake up secondary cpus */
         teq   r12, #0
         bleq  kick_cpus
 
+        PRINT("- Machine ID ")
+        mov   r0, r5
+        bl    putn
+        PRINT(" -\r\n")
+
         /* Check that this CPU has Hyp mode */
         mrc   CP32(r0, ID_PFR1)
         and   r0, r0, #0xf000        /* Bits 12-15 define virt extensions */
@@ -403,6 +417,9 @@ putn:   mov   pc, lr
 
 #endif /* !EARLY_PRINTK */
 
+/* Place holder for machine ID */
+machine_id: .word 0x0
+
 /*
  * Local variables:
  * mode: ASM
diff --git a/xen/arch/arm/arm32/mode_switch.S b/xen/arch/arm/arm32/mode_switch.S
index d6741d0..c92a1cf 100644
--- a/xen/arch/arm/arm32/mode_switch.S
+++ b/xen/arch/arm/arm32/mode_switch.S
@@ -20,14 +20,21 @@
 #include <asm/config.h>
 #include <asm/page.h>
 #include <asm/platforms/vexpress.h>
+#include <asm/platforms/exynos5.h>
 #include <asm/asm_defns.h>
 #include <asm/gic.h>
 
-
-/* XXX: Versatile Express specific code */
-/* wake up secondary cpus */
+/* Wake up secondary cpus
+ * This code relies on Machine ID and only works for Vexpress and the Arndale
+ * TODO: Move this code either later (via platform specific desc) or in a bootwrapper
+ * r5: Machine ID
+ * Clobber r0 r2 */
 .globl kick_cpus
 kick_cpus:
+        ldr   r0, =MACH_TYPE_SMDK5250
+        teq   r5, r0                          /* Are we running on the arndale? */
+        beq   kick_cpus_arndale
+        /* otherwise versatile express */
         /* write start paddr to v2m sysreg FLAGSSET register */
         ldr   r0, =(V2M_SYS_MMIO_BASE)        /* base V2M sysreg MMIO address */
         dsb
@@ -38,8 +45,20 @@ kick_cpus:
         add   r2, r2, r10
         str   r2, [r0, #(V2M_SYS_FLAGSSET)]
         dsb
+        ldr   r2, =V2M_GIC_BASE_ADDRESS       /* r2 := VE gic base address */
+        b     kick_cpus_sgi
+kick_cpus_arndale:
+        /* write start paddr to CPU 1 sysreg register */
+        ldr   r0, =(S5P_PA_SYSRAM)
+        ldr   r2, =start
+        add   r2, r2, r10
+        str   r2, [r0]
+        dsb
+        ldr   r2, =EXYNOS5_GIC_BASE_ADDRESS   /* r2 := Exynos5 gic base address */
+kick_cpus_sgi:
         /* send an interrupt */
-        ldr   r0, =(GIC_BASE_ADDRESS + GIC_DR_OFFSET) /* base GICD MMIO address */
+        ldr   r0, =GIC_DR_OFFSET              /* GIC distributor offset */
+        add   r0, r2                          /* r0 := r0 + gic base address */
         mov   r2, #0x1
         str   r2, [r0, #(GICD_CTLR * 4)]      /* enable distributor */
         mov   r2, #0xfe0000
@@ -51,13 +70,15 @@ kick_cpus:
 
 /* Get up a CPU into Hyp mode.  Clobbers r0-r3.
  *
- * Expects r12 == CPU number
+ * r5: Machine ID
+ * r12: CPU number
  *
- * This code is specific to the VE model, and not intended to be used
+ * This code is specific to the VE model/Arndale, and not intended to be used
  * on production systems.  As such it's a bit hackier than the main
  * boot code in head.S.  In future it will be replaced by better
  * integration with the bootloader/firmware so that Xen always starts
- * in Hyp mode. */
+ * in Hyp mode.
+ * Clobber r0 - r4 */
 
 .globl enter_hyp_mode
 enter_hyp_mode:
@@ -68,33 +89,51 @@ enter_hyp_mode:
         orr   r0, r0, #0xb1          /* Set SCD, AW, FW and NS */
         bic   r0, r0, #0xe           /* Clear EA, FIQ and IRQ */
         mcr   CP32(r0, SCR)
+
+        ldr   r2, =MACH_TYPE_SMDK5250   /* r4 := Arndale machine ID */
+        /* By default load Arndale defaults values */
+        ldr   r0, =EXYNOS5_TIMER_FREQUENCY  /* r0 := timer's frequency */
+        ldr   r1, =EXYNOS5_GIC_BASE_ADDRESS /* r1 := GIC base address */
+        /* If it's not the Arndale machine ID, load VE values */
+        teq   r5, r2
+        ldrne r0, =V2M_TIMER_FREQUENCY
+        ldrne r1, =V2M_GIC_BASE_ADDRESS
+
         /* Ugly: the system timer's frequency register is only
          * programmable in Secure state.  Since we don't know where its
          * memory-mapped control registers live, we can't find out the
-         * right frequency.  Use the VE model's default frequency here. */
-        ldr   r0, =0x5f5e100         /* 100 MHz */
+         * right frequency. */
         mcr   CP32(r0, CNTFRQ)
         ldr   r0, =0x40c00           /* SMP, c11, c10 in non-secure mode */
         mcr   CP32(r0, NSACR)
-        mov   r0, #GIC_BASE_ADDRESS
-        add   r0, r0, #GIC_DR_OFFSET
+
+        add   r0, r1, #GIC_DR_OFFSET
         /* Disable the GIC distributor, on the boot CPU only */
-        mov   r1, #0
+        mov   r4, #0
         teq   r12, #0                /* Is this the boot CPU? */
-        streq r1, [r0]
+        streq r4, [r0]
         /* Continuing ugliness: Set up the GIC so NS state owns interrupts,
          * The first 32 interrupts (SGIs & PPIs) must be configured on all
          * CPUs while the remainder are SPIs and only need to be done one, on
          * the boot CPU. */
         add   r0, r0, #0x80          /* GICD_IGROUP0 */
         mov   r2, #0xffffffff        /* All interrupts to group 1 */
-        teq   r12, #0                /* Boot CPU? */
         str   r2, [r0]               /* Interrupts  0-31 (SGI & PPI) */
-        streq r2, [r0, #4]           /* Interrupts 32-63 (SPI) */
-        streq r2, [r0, #8]           /* Interrupts 64-95 (SPI) */
+        teq   r12, #0                /* Boot CPU? */
+        bne   skip_spis              /* Don't route SPIs on secondary CPUs */
+
+        add   r4, r1, #GIC_DR_OFFSET
+        ldr   r4, [r4, #4]            /* r4 := Interrupt Controller Type Reg */
+        and   r4, r4, #GICD_TYPE_LINES /* r4 := number of SPIs */
+1:      teq   r4, #0
+        beq   skip_spis
+        add   r0, r0, #4             /* Go to the new group */
+        str   r2, [r0]               /* Update the group */
+        sub  r4, r4, #1
+        b     1b
+skip_spis:
         /* Disable the GIC CPU interface on all processors */
-        mov   r0, #GIC_BASE_ADDRESS
-        add   r0, r0, #GIC_CR_OFFSET
+        add   r0, r1, #GIC_CR_OFFSET
         mov   r1, #0
         str   r1, [r0]
         /* Must drop priority mask below 0x80 before entering NS state */
diff --git a/xen/include/asm-arm/platforms/vexpress.h b/xen/include/asm-arm/platforms/vexpress.h
index 5cf3aba..982a293 100644
--- a/xen/include/asm-arm/platforms/vexpress.h
+++ b/xen/include/asm-arm/platforms/vexpress.h
@@ -32,6 +32,17 @@
 int vexpress_syscfg(int write, int function, int device, uint32_t *data);
 #endif
 
+/* Constants below is only used in assembly because the DTS is not yet parsed */
+#ifdef __ASSEMBLY__
+
+/* GIC base address */
+#define V2M_GIC_BASE_ADDRESS        0x2c000000
+
+/* Timer's frequency */
+#define V2M_TIMER_FREQUENCY         0x5f5e100 /* 100 Mhz */
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_ARM_PLATFORMS_VEXPRESS_H */
 /*
  * Local variables:
-- 
Julien Grall

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

* [PATCH V2 33/33] xen/arm64: Remove hardcoded value for gic in assembly code
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (31 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
@ 2013-05-08  2:33 ` Julien Grall
  2013-05-08  7:03 ` [PATCH V2 00/33] Support multiple ARM platforms in Xen Gihun Jung
  33 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08  2:33 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

- arm64: use V2M_GIC_BASE_ADDRESS
- only expose GIC_*_ADDRESS to assembly. The C code uses base addresses
provide by the device tree

Signed-off-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v2:
    - Remove stray gi"t diff"
---
 xen/arch/arm/arm64/mode_switch.S |    7 ++++---
 xen/include/asm-arm/config.h     |    8 ++++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/xen/arch/arm/arm64/mode_switch.S b/xen/arch/arm/arm64/mode_switch.S
index 4c38181..d115706 100644
--- a/xen/arch/arm/arm64/mode_switch.S
+++ b/xen/arch/arm/arm64/mode_switch.S
@@ -21,6 +21,7 @@
 #include <asm/config.h>
 #include <asm/page.h>
 #include <asm/asm_defns.h>
+#include <asm/platforms/vexpress.h>
 
 /* Get up a CPU into EL2.  Clobbers x0-x3.
  *
@@ -53,18 +54,18 @@ enter_el2_mode:
          */
         cbnz    x22, 1f
 
-        ldr     x1, =(GIC_BASE_ADDRESS+GIC_DR_OFFSET) // GICD_CTLR
+        ldr     x1, =(V2M_GIC_BASE_ADDRESS+GIC_DR_OFFSET) // GICD_CTLR
         mov     w0, #3                          // EnableGrp0 | EnableGrp1
         str     w0, [x1]
 
-1:      ldr     x1, =(GIC_BASE_ADDRESS+GIC_DR_OFFSET+0x80) // GICD_IGROUPR
+1:      ldr     x1, =(V2M_GIC_BASE_ADDRESS+GIC_DR_OFFSET+0x80) // GICD_IGROUPR
         mov     w0, #~0                         // Grp1 interrupts
         str     w0, [x1], #4
         b.ne    2f                              // Only local interrupts for secondary CPUs
         str     w0, [x1], #4
         str     w0, [x1], #4
 
-2:      ldr     x1, =(GIC_BASE_ADDRESS+GIC_CR_OFFSET) // GICC_CTLR
+2:      ldr     x1, =(V2M_GIC_BASE_ADDRESS+GIC_CR_OFFSET) // GICC_CTLR
         ldr     w0, [x1]
         mov     w0, #3                          // EnableGrp0 | EnableGrp1
         str     w0, [x1]
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 6414c89..e3cfaf1 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -141,12 +141,16 @@ extern unsigned long frametable_virt_end;
 #define watchdog_disable() ((void)0)
 #define watchdog_enable()  ((void)0)
 
-/* Board-specific: base address of GIC + its regs */
-#define GIC_BASE_ADDRESS 0x2c000000
+#ifdef __ASSEMBLY__
+/* Board-specific: regs base address for the GIC
+ * Theses constants are only intend to be used in assembly file
+ * because the DT is not yet parsed.
+ */
 #define GIC_DR_OFFSET 0x1000
 #define GIC_CR_OFFSET 0x2000
 #define GIC_HR_OFFSET 0x4000 /* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */
 #define GIC_VR_OFFSET 0x6000 /* Virtual Machine CPU interface) */
+#endif /* __ASSEMBLY__ */
 
 #endif /* __ARM_CONFIG_H__ */
 /*
-- 
Julien Grall

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

* Re: [PATCH V2 00/33] Support multiple ARM platforms in Xen
  2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
                   ` (32 preceding siblings ...)
  2013-05-08  2:33 ` [PATCH V2 33/33] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
@ 2013-05-08  7:03 ` Gihun Jung
  2013-05-08 11:01   ` Julien Grall
  33 siblings, 1 reply; 88+ messages in thread
From: Gihun Jung @ 2013-05-08  7:03 UTC (permalink / raw)
  To: Julien Grall, xen-devel

> If you want to try this patch series you can clone:
>     git clone -b arm-v2 git://xenbits.xen.org/people/julieng/xen-unstable.git
>
> The command line to compile Xen is the same as before. You just need to
> specify on Xen command line, via the device tree, which UART will be used
> for the console.
>
> Feel free to test this branch during Xen test day. The wiki has been updated
> for the arndale board:
> http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Arndale
>
> It's now based on:
>   - this patch series for Xen
>   - linux 3.9
>
Hello,

While I am testing on your new patch series on the Arndale Board, I
have found some mismatching items between wiki and source code.

1. dts path problem:
 from kernel 3.9 ( my guessing.. :) ), dtb file will be created in the
same directory with dts file: arch/arm/boot/dts/*.dtb.
 However, in the wiki, it still describe dtb path is in arch/arm/boot/*.dtb.

2. early_printk uart:
 In the branch name "arndale" from your linux tree
(git://xenbits.xen.org/people/julieng/linux-arm.git),
exynos5250-arndale.dts describes "console=com1,dbgp com1=serial0" as a
boot argument for early_printk.
 However, in your newer patch series for XenARM,
${xensrc}/drivers/char/arm-uart.c try to find console that has node
name as "dtuart". So, I think it is required to modify
"exynos5250-arndale.dts" file like:
 - console=com1,dbgp com1=serial0
 +console=dtuart dtuart=serial0

Please consider this matters.

> Feel free to test this branch during the Xen test day on both the versatile
> express and the arndale board.
>
> Cheers,

I am really enjoying to testing with your newly release patch series
on the arndale board.
But, I am still facing some problems :( I will post the problem to the
mailing list later.

Sincerely yours,
Gihun Jung

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

* Re: [PATCH V2 00/33] Support multiple ARM platforms in Xen
  2013-05-08  7:03 ` [PATCH V2 00/33] Support multiple ARM platforms in Xen Gihun Jung
@ 2013-05-08 11:01   ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 11:01 UTC (permalink / raw)
  To: Gihun Jung; +Cc: xen-devel

On 8 May 2013 08:03, Gihun Jung <gihun.jung@gmail.com> wrote:
>
> > If you want to try this patch series you can clone:
> >     git clone -b arm-v2 git://xenbits.xen.org/people/julieng/xen-unstable.git
> >
> > The command line to compile Xen is the same as before. You just need to
> > specify on Xen command line, via the device tree, which UART will be used
> > for the console.
> >
> > Feel free to test this branch during Xen test day. The wiki has been updated
> > for the arndale board:
> > http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Arndale
> >
> > It's now based on:
> >   - this patch series for Xen
> >   - linux 3.9
> >
> Hello,
>
> While I am testing on your new patch series on the Arndale Board, I
> have found some mismatching items between wiki and source code.

Hi,

Thansk for testing the arndale board with Xen!

> 1. dts path problem:
>  from kernel 3.9 ( my guessing.. :) ), dtb file will be created in the
> same directory with dts file: arch/arm/boot/dts/*.dtb.
>  However, in the wiki, it still describe dtb path is in arch/arm/boot/*.dtb.

The wiki page has been updated.

> 2. early_printk uart:
>  In the branch name "arndale" from your linux tree
> (git://xenbits.xen.org/people/julieng/linux-arm.git),
> exynos5250-arndale.dts describes "console=com1,dbgp com1=serial0" as a
> boot argument for early_printk.
>  However, in your newer patch series for XenARM,
> ${xensrc}/drivers/char/arm-uart.c try to find console that has node
> name as "dtuart". So, I think it is required to modify
> "exynos5250-arndale.dts" file like:
>  - console=com1,dbgp com1=serial0
>  +console=dtuart dtuart=serial0

I have pushed a fix in the linux's tree commit "08d452d".

Cheers,

--
Julien Grall

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

* Re: [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512
  2013-05-08  2:33 ` [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512 Julien Grall
@ 2013-05-08 13:00   ` Ian Campbell
  2013-05-09 14:32     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:00 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> When debug is enabled in device tree code, some lines
> are bigger than 80 characters.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

Although if we can also take steps to not let the line length get too
long that would be valuable, I can see 80-100 being tolerable but if we
are actually seeing lines with 512 characters that is an issue in its
own right. I appreciate you've just picked a "big enough" number and we
hopefully aren't seeing anything like 512 in practice.

> Changes in v2:
>  - Move buffer to a static variable
> ---
>  xen/arch/arm/early_printk.c |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
> index bdf4c0e..0f99a43 100644
> --- a/xen/arch/arm/early_printk.c
> +++ b/xen/arch/arm/early_printk.c
> @@ -29,6 +29,9 @@ void __init early_putch(char c)
>      *r = c;
>  }
>  
> +/* Early printk buffer */
> +static char __initdata buf[512];
> +
>  static void __init early_puts(const char *s)
>  {
>      while (*s != '\0') {
> @@ -41,8 +44,6 @@ static void __init early_puts(const char *s)
>  
>  static void __init early_vprintk(const char *fmt, va_list args)
>  {
> -    char buf[80];
> -
>      vsnprintf(buf, sizeof(buf), fmt, args);
>      early_puts(buf);
>  }

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08  2:33 ` [PATCH V2 07/33] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-08 13:11   ` Ian Campbell
  2013-05-08 13:34     ` Julien Grall
  2013-05-08 13:52   ` Ian Campbell
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:11 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:

> +/**
> + * Dump device tree message with printk
> + * TODO: Find another way to switch between early_printk and printk
> + * int the device tree code
> + */
> +void __init dt_switch_to_printk(void);

The issue here is that there is code which wants to log which can be
called either via dt_unflatten_host_device_tree or later on?

There seems to be at least some calls to dt_dprintk which are only
called via dt_unfla..., I think these can and should just use
early_printk (or a macro to make them a debug thing). Likewise if there
are functions which are only called later then they should just use
printk direct (or a macro..)

Which only leaves ones which are both? How many are these? I'm inclined
towards suggesting that if they are debug prints which are disabled by
default and require a recompile to enable then the person doing the
debugging can select whether they care about early or late messages by 
#define-ing DEBUG or EARLY_DEBUG or both as required.

> +/**
> + * Host device tree
> + * DO NOT modify it!

Can it be const?

> + */
> +extern struct dt_device_node *dt_host;
> +
> +#define dt_node_cmp(s1, s2) strcmp((s1), (s2))
> +#define dt_compat_cmp(s1, s2, l) strnicmp((s1), (s2), l)
> +
> +#define for_each_property_of_node(dn, pp)                   \
> +    for ( pp = dn->properties; pp != NULL; pp = pp->next )
> +
> +#define for_each_device_node(dt, dn)                         \
> +    for ( dn = dt; dn != NULL; dn = dn->allnext )
> +
> +static inline const char *dt_node_full_name(const struct dt_device_node *np)
> +{
> +    return (np && np->full_name) ? np->full_name : "<no-node>";
> +}
> +
> +/**
> + * Find a property with a given name for a given node
> + * and return the value.
> + */
> +const void *dt_get_property(const struct dt_device_node *np,
> +                            const char *name, u32 *lenp);
> +
> +/**
> + * dt_find_node_by_path - Find a node matching a full DT path
> + * @path: The full path to match
> + *
> + * Returns a node pointer.
> + */
> +struct dt_device_node *dt_find_node_by_path(const char *path);
>  #endif
> --
> Julien Grall
> 

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

* Re: [PATCH V2 08/33] xen/arm: Add helpers to use the device tree
  2013-05-08  2:33 ` [PATCH V2 08/33] xen/arm: Add helpers to use the " Julien Grall
@ 2013-05-08 13:18   ` Ian Campbell
  2013-05-08 15:31     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:18 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - use dt_node_cmp and dt_compat_cmp in early device tree code
> ---
>  xen/common/device_tree.c      |  127 ++++++++++++++++++++++++++++++++++++++++-
>  xen/include/xen/device_tree.h |  120 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 245 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index bdf8871..449c332 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -88,20 +88,23 @@ bool_t device_tree_type_matches(const void *fdt, int node, const char *match)
>      if ( prop == NULL )
>          return 0;
>  
> -    return !strcmp(prop, match);
> +    return !dt_node_cmp(prop, match);
>  }
>  
>  bool_t device_tree_node_compatible(const void *fdt, int node, const char *match)

Aside: I wonder if any of these should be __init...

>  {
>      int len, l;
> +    int mlen;
>      const void *prop;
>  
> +    mlen = strlen(match);
> +
>      prop = fdt_getprop(fdt, node, "compatible", &len);
>      if ( prop == NULL )
>          return 0;
>  
>      while ( len > 0 ) {
> -        if ( !strcmp(prop, match) )
> +        if ( !dt_compat_cmp(prop, match, mlen) )

Is there a change in behaviour here where strlen(match) < strlen(prop)?

I may be mistaken but I think match=="foo" would be compatible with a
node "foobar" now whereas it wasn't before.

On the otherhand this is the same behaviour as dt_device_is_compatible
so maybe it is expected. I seem to recall some name matching code which
explicitly wanted to handle foo@0 as matching foo and things, not sure
that applies here though.

>              return 1;
>          l = strlen(prop) + 1;
>          prop += l;
> @@ -573,6 +576,54 @@ const void *dt_get_property(const struct dt_device_node *np,
>      return pp ? pp->value : NULL;
>  }
>  
> +bool_t dt_device_is_compatible(const struct dt_device_node *device,
> +                               const char *compat)
> +{
> +    const char* cp;
> +    u32 cplen, l;
> +
> +    cp = dt_get_property(device, "compatible", &cplen);
> +    if ( cp == NULL )
> +        return 0;
> +    while ( cplen > 0 )
> +    {
> +        if ( dt_compat_cmp(cp, compat, strlen(compat)) == 0 )
> +            return 1;
> +        l = strlen(cp) + 1;
> +        cp += l;
> +        cplen -= l;
> +    }
> +
> +    return 0;
> +}
> +
> +bool_t dt_machine_is_compatible(const char *compat)
> +{
> +    const struct dt_device_node *root;
> +    bool_t rc = 0;
> +
> +    root = dt_find_node_by_path("/");
> +    if ( root )
> +    {
> +        rc = dt_device_is_compatible(root, compat);
> +    }
> +    return rc;
> +}
> +
> +struct dt_device_node *dt_find_node_by_name(struct dt_device_node *from,
> +                                            const char *name)
> +{
> +    struct dt_device_node *np;
> +    struct dt_device_node *dt;
> +
> +    dt = from ? from->allnext : dt_host;
> +    for_each_device_node(dt, np)
> +        if ( np->name && (dt_node_cmp(np->name, name) == 0) )
> +            break;
> +
> +    return np;
> +}
> +
>  struct dt_device_node *dt_find_node_by_path(const char *path)
>  {
>      struct dt_device_node *np;

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

* Re: [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from the device tree
  2013-05-08  2:33 ` [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from " Julien Grall
@ 2013-05-08 13:23   ` Ian Campbell
  2013-05-08 15:32     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:23 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> ---
>  xen/common/device_tree.c      |  343 +++++++++++++++++++++++++++++++++++++++++
>  xen/include/xen/device_tree.h |   22 +++
>  2 files changed, 365 insertions(+)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 449c332..8d37018 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -62,10 +62,38 @@ static void (*dt_printk)(const char *fmt, ...) = early_printk;
> 
>  #ifdef DEBUG_DT
>  # define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
> +static void dt_dump_addr(const char *s, const __be32 *addr, int na)
> +{
> +    dt_dprintk("%s", s);
> +    while ( na-- )
> +        dt_dprintk(" %08x", be32_to_cpu(*(addr++)));
> +    dt_dprintk("\n");
> +}
>  #else
>  # define dt_dprintk(fmt, args...) do {} while ( 0 )
> +static void dt_dump_addr(const char *s, const __be32 *addr, int na) { }
>  #endif
> 
> +#define DT_BAD_ADDR ((u64)-1)
> +
> +/* Max address size we deal with */
> +#define DT_MAX_ADDR_CELLS 4
> +#define DT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= DT_MAX_ADDR_CELLS)
> +#define DT_CHECK_COUNTS(na, ns) (DT_CHECK_ADDR_COUNT(na) && (ns) > 0)
> +
> +/* Callbacks for bus specific translators */
> +struct dt_bus
> +{
> +    const char *name;
> +    const char *addresses;
> +    int (*match)(const struct dt_device_node *parent);
> +    void (*count_cells)(const struct dt_device_node *child,
> +                        int *addrc, int *sizec);
> +    u64        (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
> +       int (*translate)(__be32 *addr, u64 offset, int na);
> +       unsigned int (*get_flags)(const __be32 *addr);

Spacing is weird here. Hard tabs perhaps?

> +static int dt_translate_one(const struct dt_device_node *parent,
> +                            const struct dt_bus *bus,
> +                            const struct dt_bus *pbus,
> +                            __be32 *addr, int na, int ns,
> +                            int pna, const char *rprop)
> +{
> +    const __be32 *ranges;
> +    unsigned int rlen;
> +    int rone;
> +    u64 offset = DT_BAD_ADDR;
> +
> +    ranges = dt_get_property(parent, rprop, &rlen);
> +    if ( ranges == NULL )
> +    {
> +               dt_printk(XENLOG_ERR "DT: no ranges; cannot translate\n");
> +               return 1;
> +       }

Indentation.

> +    if ( ranges == NULL || rlen == 0 )
> +    {
> +        offset = dt_read_number(addr, na);
> +        memset(addr, 0, pna * 4);
> +        dt_dprintk("DT: empty ranges; 1:1 translation\n");
> +        goto finish;
> +    }
> +
> +    dt_dprintk("DT: walking ranges...\n");
> +
> +    /* Now walk through the ranges */
> +    rlen /= 4;
> +    rone = na + pna + ns;
> +    for ( ; rlen >= rone; rlen -= rone, ranges += rone )
> +    {
> +        offset = bus->map(addr, ranges, na, ns, pna);
> +        if ( offset != DT_BAD_ADDR )
> +            break;
> +       }

Indentation.

> +    if ( offset == DT_BAD_ADDR )
> +    {
> +        dt_dprintk("DT: not found !\n");
> +        return 1;
> +    }
> +    memcpy(addr, ranges + na, 4 * pna);
> +
> +finish:
> +    dt_dump_addr("DT: parent translation for:", addr, pna);
> +    dt_dprintk("DT: with offset: %llx\n", (unsigned long long)offset);
> +
> +    /* Translate it into parent bus space */
> +    return pbus->translate(addr, offset, pna);
> +}
> +
> +/*
> + * Translate an address from the device-tree into a CPU physical address,
> + * this walks up the tree and applies the various bus mappings on the
> + * way.
> + *
> + * Note: We consider that crossing any level with #size-cells == 0 to mean
> + * that translation is impossible (that is we are not dealing with a value
> + * that can be mapped to a cpu physical address). This is not really specified
> + * that way, but this is traditionally the way IBM at least do things
> + */
> +static u64 __dt_translate_address(const struct dt_device_node *dev,
> +                                  const __be32 *in_addr, const char *rprop)
> +{
> +    const struct dt_device_node *parent = NULL;
> +    const struct dt_bus *bus, *pbus;
> +    __be32 addr[DT_MAX_ADDR_CELLS];
> +    int na, ns, pna, pns;
> +    u64 result = DT_BAD_ADDR;
> +
> +       dt_dprintk("DT: ** translation for device %s **\n", dev->full_name);

Ide...

> +
> +    /* Get parent & match bus type */
> +    parent = dt_get_parent(dev);
> +    if ( parent == NULL )
> +        goto bail;
> +    bus = dt_match_bus(parent);
> +
> +    /* Count address cells & copy address locally */
> +    bus->count_cells(dev, &na, &ns);
> +    if ( !DT_CHECK_COUNTS(na, ns) )
> +    {
> +        dt_printk(XENLOG_ERR "dt_parse: Bad cell count for %s\n",
> +                  dev->full_name);
> +        goto bail;
> +    }
> +    memcpy(addr, in_addr, na * 4);
> +
> +    dt_dprintk("DT: bus is %s (na=%d, ns=%d) on %s\n",
> +               bus->name, na, ns, parent->full_name);
> +       dt_dump_addr("DT: translating address:", addr, na);

Inde...

> diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
> index 879b75d..ce34ba5 100644
> --- a/xen/include/xen/device_tree.h
> +++ b/xen/include/xen/device_tree.h
> @@ -278,6 +278,28 @@ struct dt_device_node *dt_find_node_by_path(const char *path);
>  const struct dt_device_node *dt_get_parent(const struct dt_device_node *node);
> 
>  /**
> + * dt_device_get_address - Resolve an address for a device
> + * @device: the device whose address is to be resolved
> + * @index: index of the addres to resolve

address

> + * @addr: address filled by this function
> + * @size: size filled by this function
> + *
> + * This function resolves an address, walking the tree, for a give
> + * device-tree node. It returns 0 on success.
> + */
> +int dt_device_get_address(const struct dt_device_node *dev, int index,
> +                          u64 *addr, u64 *size);
> +
> +/**
> + * dt_number_of_address - Get the number of addresse for a device

addresses

> + * @device: the device whose number of address is to be retrieved
> + *
> + * Return the number of address for this device or 0 if there is no
> + * address or an error occured/

occurred

Apart from the indentation and the spelling errors I'm inclined to trust
that the actual logic is ok. So if you fix the above (and any
indentation I missed):
Acked-by: Ian Campbell <ian.campbell@citrix.com>

> + */
> +unsigned int dt_number_of_address(const struct dt_device_node *device);
> +
> +/**
>   * dt_n_size_cells - Helper to retrieve the number of cell for the size
>   * @np: node to get the value
>   *
> --
> Julien Grall
> 

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

* Re: [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description from the device tree
  2013-05-08  2:33 ` [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
@ 2013-05-08 13:30   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:30 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - Move interrupt type from xen/irq.h to xen/device_tree.h
>     - Prefix all defines by DT_
> ---
>  xen/common/device_tree.c      |  362 +++++++++++++++++++++++++++++++++++++++++
>  xen/include/xen/device_tree.h |  130 +++++++++++++++
>  2 files changed, 492 insertions(+)
> 
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 8d37018..e5ff779 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -27,8 +27,11 @@
> 
>  struct dt_early_info __initdata early_info;
>  void *device_tree_flattened;
> +dt_irq_xlate_func dt_irq_xlate;
>  /* Host device tree */
>  struct dt_device_node *dt_host;
> +/* Interrupt controller node*/
> +const struct dt_device_node *dt_interrupt_controller;
> 
>  /**
>   * struct dt_alias_prop - Alias property in 'aliases' node
> @@ -1020,6 +1023,81 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
>      return 0;
>  }
> 
> +/**
> + * dt_find_node_by_phandle - Find a node given a phandle
> + * @handle:    phandle of the node to find
> + *
> + * Returns a node pointer.
> + */
> +static const struct dt_device_node *dt_find_node_by_phandle(dt_phandle handle)
> +{
> +    const struct dt_device_node *np;
> +
> +    for_each_device_node(dt_host, np)
> +        if ( np->phandle == handle )
> +            break;
> +
> +    return np;
> +}
> +
> +/**
> + * dt_irq_find_parent - Given a device node, find its interrupt parent node
> + * @child: pointer to device node
> + *
> + * Returns a pointer to the interrupt parent node, or NULL if the interrupt
> + * parent could not be determined.
> + */
> +static const struct dt_device_node *
> +dt_irq_find_parent(const struct dt_device_node *child)
> +{
> +    const struct dt_device_node *p;
> +    const __be32 *parp;
> +
> +    do
> +    {
> +        parp = dt_get_property(child, "interrupt-parent", NULL);
> +        if ( parp == NULL )
> +            p = dt_get_parent(child);
> +        else
> +            p = dt_find_node_by_phandle(be32_to_cpup(parp));
> +        child = p;
> +    } while ( p && dt_get_property(p, "#interrupt-cells", NULL) == NULL );
> +
> +    return p;
> +}
> +
> +unsigned int dt_number_of_irq(const struct dt_device_node *device)
> +{
> +    const struct dt_device_node *p;
> +    const __be32 *intspec, *tmp;
> +    u32 intsize, intlen;
> +
> +    dt_dprintk("dt_irq_number: dev=%s\n", device->full_name);
> +
> +    /* Get the interrupts property */
> +    intspec = dt_get_property(device, "interrupts", &intlen);
> +    if ( intspec == NULL )
> +        return 0;
> +    intlen /= sizeof(*intspec);
> +
> +    dt_dprintk(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
> +
> +    /* Look for the interrupt parent. */
> +    p = dt_irq_find_parent(device);
> +    if ( p == NULL )
> +        return 0;
> +
> +    /* Get size of interrupt specifier */
> +    tmp = dt_get_property(p, "#interrupt-cells", NULL);
> +    if ( tmp == NULL )
> +        return 0;
> +    intsize = be32_to_cpu(*tmp);
> +
> +    dt_dprintk(" intsize=%d intlen=%d\n", intsize, intlen);
> +
> +    return (intlen / intsize);
> +}
> +
>  unsigned int dt_number_of_address(const struct dt_device_node *dev)
>  {
>      const __be32 *prop;
> @@ -1051,6 +1129,274 @@ unsigned int dt_number_of_address(const struct dt_device_node *dev)
>  }
> 
>  /**
> + * dt_irq_map_raw - Low level interrupt tree parsing
> + * @parent:     the device interrupt parent
> + * @intspec:    interrupt specifier ("interrupts" property of the device)
> + * @ointsize:   size of the passed in interrupt specifier
> + * @addr:       address specifier (start of "reg" property of the device)
> + * @oirq:       structure dt_raw_irq filled by this function
> + *
> + * Returns 0 on success and a negative number on error
> + *
> + * This function is a low-level interrupt tree walking function. It
> + * can be used to do a partial walk with synthetized reg and interrupts

synthesized

> +/**
> + * dt_raw_irq - container for device_node/irq_specifier for an irq controller
> + * @controller: pointer to interrupt controller deivce tree node
> + * @size: size of interrupt specifier
> + * @specifier: array of cells @size long specifing the specific interrupt

specifying

>   * DO NOT modify it!
>   */
>  extern struct dt_device_node *dt_host;
> 
> +/**
> + * Primary interrupt controller
> + * Exynos SOC has an interrupt combiner, interrupt has no physical
                                           ^an 

> + * meaning when it's not connected to the primary controller.
> + * We will only map interrupt whose parent controller is
> + * dt_interrupt_controller. It should always be a GIC.
> + * TODO: Handle multiple GIC
> + */
> +extern const struct dt_device_node *dt_interrupt_controller;
> +
> +/**
> + * Find the interrupt controller
> + * For the moment we handle only one interrupt controller: the first
> + * one without parent and is compatible with the string "compat".
             ... parent which is ...

> +/**
>   * dt_number_of_address - Get the number of addresse for a device

addresses

>   * @device: the device whose number of address is to be retrieved
>   *
> @@ -300,6 +399,37 @@ int dt_device_get_address(const struct dt_device_node *dev, int index,
>  unsigned int dt_number_of_address(const struct dt_device_node *device);
> 
>  /**
> + * dt_device_get_irq - Resolve an interrupt for a device
> + * @device: the device whose interrupt is to be resolved
> + * @index: index of the interrupt to resolve
> + * @out_irq: structure dt_irq filled by this function
> + *
> + * This function resolves an interrupt, walking the tree, for a given
> + * device-tree node. It's the high level pendant to dt_device_get_raw_irq().
> + */
> +int dt_device_get_irq(const struct dt_device_node *device, int index,
> +                      struct dt_irq *irq);
> +
> +/**
> + * dt_device_get_raw_irq - Resolve an interrupt for a device without translation
> + * @device: the device whose interrupt is to be resolved
> + * @index: index of the interrupt to resolve
> + * @out_irq: structure dt_raw_irq filled by this function
> + *
> + * This function resolves an interrupt for a device, no translation is
> + * made. dt_irq_translate can be called after.
> + */
> +int dt_device_get_raw_irq(const struct dt_device_node *device, int index,
> +                          struct dt_raw_irq *irq);
> +
> +/**
> + * dt_irq_transalte - Translate an irq

translate

Like with the previous patch I'm inclined to trust the logic is correct.
So if you fix the typoes:

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

Ian.

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

* Re: [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq
  2013-05-08  2:33 ` [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq Julien Grall
@ 2013-05-08 13:31   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:31 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> This function routes an IRQ to a specific cpu. The IRQ is retrieved via
> the device tree.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - Use dt_irq_is_level_trigger instead of the old name irq_is_level_trigger

Should be ...is_level_triggered().

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

Ian.

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

* Re: [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate
  2013-05-08  2:33 ` [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate Julien Grall
@ 2013-05-08 13:32   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:32 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> This function translates an interrupt specifier to an IRQ number and IRQ
> type (ie: level trigger, edge trigger,...). It's GIC specific.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 13:11   ` Ian Campbell
@ 2013-05-08 13:34     ` Julien Grall
  2013-05-08 13:41       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08 13:34 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:11 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> 
>> +/**
>> + * Dump device tree message with printk
>> + * TODO: Find another way to switch between early_printk and printk
>> + * int the device tree code
>> + */
>> +void __init dt_switch_to_printk(void);
> 
> The issue here is that there is code which wants to log which can be
> called either via dt_unflatten_host_device_tree or later on?


Right.


> There seems to be at least some calls to dt_dprintk which are only
> called via dt_unfla..., I think these can and should just use
> early_printk (or a macro to make them a debug thing). Likewise if there
> are functions which are only called later then they should just use
> printk direct (or a macro..)

There are lots of dt_dprintk in functions to retrieve an IRQ and an address.

> Which only leaves ones which are both? How many are these? I'm inclined
> towards suggesting that if they are debug prints which are disabled by
> default and require a recompile to enable then the person doing the
> debugging can select whether they care about early or late messages by 
> #define-ing DEBUG or EARLY_DEBUG or both as required.

We can't choose at compile time. Early printk function is in init code
section. So at the end of boot the function will disappear.
Device tree function could be called after the end of the boot. For the
moment it's not the case.

The best solution would be: early_printk is directly handled in console
as linux does.

>> +/**
>> + * Host device tree
>> + * DO NOT modify it!
> 
> Can it be const?

No :/. I choose to runtime information in the device tree. It's usefull
to know if a device is used by Xen or someone else.

I have just notice that dt_host is only used in domain_build.c to browse
all the nodes. I can either provide a helper which return the host DT or
add a function to call a function and recurse on each node.

-- 
Julien Grall

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

* Re: [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq
  2013-05-08  2:33 ` [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq Julien Grall
@ 2013-05-08 13:35   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:35 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> This function will replace setup_irq in later patch. It takes a dt_irq
> as first argument instead of an unsigned int.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 13:34     ` Julien Grall
@ 2013-05-08 13:41       ` Ian Campbell
  2013-05-08 15:15         ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
> > Which only leaves ones which are both? How many are these? I'm inclined
> > towards suggesting that if they are debug prints which are disabled by
> > default and require a recompile to enable then the person doing the
> > debugging can select whether they care about early or late messages by 
> > #define-ing DEBUG or EARLY_DEBUG or both as required.
> 
> We can't choose at compile time. Early printk function is in init code
> section. So at the end of boot the function will disappear.

Oh, right.

Perhaps something could be conditional on system_state =
SYS_STATE_active, this happens not long before we discard the initial
sections.

> Device tree function could be called after the end of the boot. For the
> moment it's not the case.
> 
> The best solution would be: early_printk is directly handled in console
> as linux does.

That does sound best.

> >> +/**
> >> + * Host device tree
> >> + * DO NOT modify it!
> > 
> > Can it be const?
> 
> No :/. I choose to runtime information in the device tree. It's usefull
> to know if a device is used by Xen or someone else.
> 
> I have just notice that dt_host is only used in domain_build.c to browse
> all the nodes. I can either provide a helper which return the host DT or
> add a function to call a function and recurse on each node.

I think it is OK, I was only wondering if it could be const.

Ian.

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

* Re: [PATCH V2 14/33] xen/arm: Introduce request_dt_irq
  2013-05-08  2:33 ` [PATCH V2 14/33] xen/arm: Introduce request_dt_irq Julien Grall
@ 2013-05-08 13:41   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> This function will replace request_irq in a later patch. It takes a dt_irq
> as first argument instead of an unsigned int.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-08  2:33 ` [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
@ 2013-05-08 13:46   ` Ian Campbell
  2013-05-08 15:49     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:46 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> - Remove early parsing for GIC addresses
> - Remove hard coded maintenance IRQ number
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - use the new function request_dt_irq
> ---
>  xen/arch/arm/gic.c            |   63 ++++++++++++++++++++++++++++-------------
>  xen/common/device_tree.c      |   42 ---------------------------
>  xen/include/xen/device_tree.h |    8 ------
>  3 files changed, 43 insertions(+), 70 deletions(-)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 1efa9a3..34304b3 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -45,6 +45,7 @@ static struct {
>      paddr_t hbase;       /* Address of virtual interface registers */
>      paddr_t vbase;       /* Address of virtual cpu interface registers */
>      unsigned int lines;  /* Number of interrupts (SPIs + PPIs + SGIs) */
> +    struct dt_irq maintenance; /* IRQ maintenance */
>      unsigned int cpus;
>      spinlock_t lock;
>  } gic;
> @@ -352,28 +353,49 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
>  /* Set up the GIC */
>  void __init gic_init(void)
>  {
> +    struct dt_device_node *node;
> +    int res;
> +
> +    node = dt_find_interrupt_controller("arm,cortex-a15-gic");
> +    if ( !node )
> +        panic("Unable to find compatible GIC in the device tree\n");
> +
> +    dt_device_set_used_by(node, DT_USED_BY_XEN);
> +
> +    res = dt_device_get_address(node, 0, &gic.dbase, NULL);
> +    if ( res || !gic.dbase || (gic.dbase & ~PAGE_MASK) )
> +        panic("GIC: Cannot find a valid address for the distributor\n");
> +
> +    res = dt_device_get_address(node, 1, &gic.cbase, NULL);
> +    if ( res || !gic.cbase || (gic.cbase & ~PAGE_MASK) )
> +        panic("GIC: Cannot find a valid address for the CPU\n");
> +
> +    res = dt_device_get_address(node, 2, &gic.hbase, NULL);
> +    if ( res || !gic.hbase || (gic.hbase & ~PAGE_MASK) )
> +        panic("GIC: Cannot find a valid address for the hypervisor\n");
> +
> +    res = dt_device_get_address(node, 3, &gic.vbase, NULL);
> +    if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
> +        panic("GIC: Cannot find a valid address for the virtual CPU\n");
> +
> +    res = dt_device_get_irq(node, 0, &gic.maintenance);
> +    if ( res )
> +        panic("GIC: Cannot find the maintenance IRQ\n");
> +
> +    /* Set the GIC as the primary interrupt controller */
> +    dt_interrupt_controller = node;
> +
> +    /* TODO: Add check on distributor, cpu size */
> +
>      printk("GIC initialization:\n"
>                "        gic_dist_addr=%"PRIpaddr"\n"
>                "        gic_cpu_addr=%"PRIpaddr"\n"
>                "        gic_hyp_addr=%"PRIpaddr"\n"
> -              "        gic_vcpu_addr=%"PRIpaddr"\n",
> -              early_info.gic.gic_dist_addr, early_info.gic.gic_cpu_addr,
> -              early_info.gic.gic_hyp_addr, early_info.gic.gic_vcpu_addr);
> -    if ( !early_info.gic.gic_dist_addr ||
> -         !early_info.gic.gic_cpu_addr ||
> -         !early_info.gic.gic_hyp_addr ||
> -         !early_info.gic.gic_vcpu_addr )
> -        panic("the physical address of one of the GIC interfaces is missing\n");
> -    if ( (early_info.gic.gic_dist_addr & ~PAGE_MASK) ||
> -         (early_info.gic.gic_cpu_addr & ~PAGE_MASK) ||
> -         (early_info.gic.gic_hyp_addr & ~PAGE_MASK) ||
> -         (early_info.gic.gic_vcpu_addr & ~PAGE_MASK) )
> -        panic("GIC interfaces not page aligned.\n");

Please can we keep this last check separate and after the print, this
way we get to see why it failed (not present vs invalid).

I'm ambivalent about keeping the !gic.Xbase separate or including it in
the res check.

Ian.

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

* Re: [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree
  2013-05-08  2:33 ` [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
@ 2013-05-08 13:50   ` Ian Campbell
  2013-05-08 15:53     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:50 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

> @@ -167,6 +204,15 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
>      vgic_vcpu_inject_irq(current, irq, 1);
>  }
>  
> +/* Route timer's IRQ on this CPU */
> +void __cpuinit route_timer_interrupt(void)
> +{
> +    gic_route_dt_irq(&timer_irq[PHYS_NONSECURE_PPI],
> +                     1u << smp_processor_id(), 0xa0);
> +    gic_route_dt_irq(&timer_irq[HYP_PPI], 1u << smp_processor_id(), 0xa0);
> +    gic_route_dt_irq(&timer_irq[VIRT_PPI], 1u << smp_processor_id(), 0xa0);

It occurs to me that this guy (and the underlying function) should
probably take a cpumask_t. Not now though.

> +}
> +
>  /* Set up the timer interrupt on this CPU */
>  void __cpuinit init_timer_interrupt(void)
>  {
> @@ -184,10 +230,11 @@ void __cpuinit init_timer_interrupt(void)
>      WRITE_SYSREG32(0, CNTHP_CTL_EL2);   /* Hypervisor's timer disabled */
>      isb();
>  
> -    /* XXX Need to find this IRQ number from devicetree? */
> -    request_irq(26, timer_interrupt, 0, "hyptimer", NULL);
> -    request_irq(27, vtimer_interrupt, 0, "virtimer", NULL);
> -    request_irq(30, timer_interrupt, 0, "phytimer", NULL);
> +    request_dt_irq(&timer_irq[HYP_PPI], timer_interrupt, 0, "hyptimer", NULL);
> +    request_dt_irq(&timer_irq[VIRT_PPI], vtimer_interrupt, 0,
> +                   "virtimer", NULL);
> +    request_dt_irq(&timer_irq[PHYS_NONSECURE_PPI], timer_interrupt, 2,
> +                   "phytimer", NULL);

Why the change to flags == 2 here?

Ian.

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08  2:33 ` [PATCH V2 07/33] xen/arm: Create a hierarchical device tree Julien Grall
  2013-05-08 13:11   ` Ian Campbell
@ 2013-05-08 13:52   ` Ian Campbell
  2013-05-08 15:22     ` Julien Grall
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:52 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
...
>   - Use DOMID_XEN instead of DOMID_INVALID for DT_USED_BY_XEN
> [...]

> +struct dt_device_node {
> +    const char *name;
> +    const char *type;
> +    dt_phandle phandle;
> +    char *full_name;
> +    domid_t used_by; /* By default it's used by dom0 */

It occurred to me as I reviewed the rest of the series that since this
actually a DOMID there is no reason not to use DOMID_XEN directly and
remove DT_USED_BY_XEN.

Ian.

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

* Re: [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree
  2013-05-08  2:33 ` [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
@ 2013-05-08 13:52   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 13:52 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree
  2013-05-08  2:33 ` [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree Julien Grall
@ 2013-05-08 14:01   ` Ian Campbell
  2013-05-08 15:58     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 14:01 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, Keir Fraser, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> This generic UART will find the right UART via xen command line
> with dtuart=myserial.

I suppose there way to determine sensible default, since it differs on
every platform?

> "myserial" is the alias of the UART in the device tree. Xen will retrieve
> the information via the device tree and call the initialization function for
> this specific UART thanks to the device API.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

You need to CC code code maintainers when you change core code. Keir
added.
> 
> Changes in v2:
>     - Use dtuart parameter instead of com1. The first one is more arm
>     while the latter is more x86
> ---
>  xen/arch/arm/setup.c         |    3 +-
>  xen/drivers/char/Makefile    |    1 +
>  xen/drivers/char/arm-uart.c  |   81 ++++++++++++++++++++++++++++++++++++++++++
>  xen/drivers/char/serial.c    |    6 ++++
>  xen/include/asm-arm/config.h |    2 +-
>  xen/include/xen/serial.h     |    7 ++++
>  6 files changed, 98 insertions(+), 2 deletions(-)
>  create mode 100644 xen/drivers/char/arm-uart.c
> 
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index e4228f7..7b2df8b 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -435,8 +435,9 @@ void __init start_xen(unsigned long boot_phys_offset,
>  #ifdef EARLY_UART_ADDRESS
>      /* TODO Need to get device tree or command line for UART address */
>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
> -    console_init_preirq();
>  #endif
> +    arm_uart_init();
> +    console_init_preirq();
>  
>      /* FIXME: Do something smarter */
>      dt_switch_to_printk();
> diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
> index ab2246d..e68a54a 100644
> --- a/xen/drivers/char/Makefile
> +++ b/xen/drivers/char/Makefile
> @@ -2,4 +2,5 @@ obj-y += console.o
>  obj-$(HAS_NS16550) += ns16550.o
>  obj-$(HAS_PL011) += pl011.o
>  obj-$(HAS_EHCI) += ehci-dbgp.o
> +obj-$(CONFIG_ARM) += arm-uart.o
>  obj-y += serial.o
> diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c
> new file mode 100644
> index 0000000..c76875e
> --- /dev/null
> +++ b/xen/drivers/char/arm-uart.c
> @@ -0,0 +1,81 @@
> +/*
> + * xen/drivers/char/arm-uart.c
> + *
> + * Generic ARM uart retrieved via the device tree
> + *
> + * Julien Grall <julien.grall@linaro.org>
> + * Copyright (c) 2013 Linaro Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <asm/device.h>
> +#include <asm/early_printk.h>
> +#include <asm/types.h>
> +#include <xen/console.h>
> +#include <xen/device_tree.h>
> +#include <xen/mm.h>
> +#include <xen/serial.h>
> +
> +/*
> + * Configure UART port with a string:
> + * alias
> + *
> + * @alias: alias used in the device tree for the UART
> + * TODO: Implement config  in each UART driver.
> + */
> +static char __initdata opt_dtuart[30] = "";
> +string_param("dtuart", opt_dtuart);
> +
> +void __init arm_uart_init(void)

This (and the file and struct serial_arm_defaults etc) could perhaps be
better called dt_uart_init etc? There's nothing inherently ARM specific
here.

> +{
> +    struct dt_device_node *dev;
> +    int ret;
> +    u64 addr, size;
> +    struct serial_arm_defaults defaults;
> +    const char *devalias = opt_dtuart;
> +
> +    if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
> +    {
> +        early_printk("No console\n");
> +        return;
> +    }
> +
> +    early_printk("Looking for UART console %s\n", devalias);
> +    dev = dt_find_node_by_alias(devalias);
> +
> +    if ( !dev )
> +    {
> +        early_printk("Unable to find device \"%s\"\n", devalias);
> +        return;
> +    }
> +
> +    /* TODO: Handle UART with 0 or multiple base address */
> +    ret = dt_device_get_address(dev, 0, &addr, &size);
> +    if ( ret )
> +    {
> +        early_printk("Unable to retrieve the base address of the serial\n");
> +        return;
> +    }
> +
> +    clear_fixmap(FIXMAP_CONSOLE);
> +    set_fixmap(FIXMAP_CONSOLE, addr >> PAGE_SHIFT, DEV_SHARED);
> +
> +    addr = FIXMAP_ADDR(FIXMAP_CONSOLE) + (addr & (PAGE_SIZE - 1));
> +
> +    defaults.index = 0;
> +    defaults.register_base_address = addr;
> +
> +    ret = device_init(dev, DEVICE_SERIAL, &defaults);
> +
> +    if ( ret )
> +        early_printk("Unable to initialize serial: %d\n", ret);
> +}
> diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
> index 0ae7e4d..c4c4a84 100644
> --- a/xen/drivers/char/serial.c
> +++ b/xen/drivers/char/serial.c
> @@ -271,6 +271,12 @@ int __init serial_parse_handle(char *conf)
>          goto common;
>      }
>  
> +    if ( !strncmp(conf, "dtuart", 5) )
> +    {
> +        handle = SERHND_COM1;

Do you mean COM1 here? Or did you intend to add SERHND_DT?

> +        goto common;
> +    }
> +
>      if ( strncmp(conf, "com", 3) )
>          goto fail;
>  
> diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
> index 98a3a43..8ed72f5 100644
> --- a/xen/include/asm-arm/config.h
> +++ b/xen/include/asm-arm/config.h
> @@ -39,7 +39,7 @@
>  
>  #define CONFIG_VIDEO 1
>  
> -#define OPT_CONSOLE_STR "com1"
> +#define OPT_CONSOLE_STR "dtuart"
>  
>  #ifdef MAX_PHYS_CPUS
>  #define NR_CPUS MAX_PHYS_CPUS
> diff --git a/xen/include/xen/serial.h b/xen/include/xen/serial.h
> index 5de5171..f548f8b 100644
> --- a/xen/include/xen/serial.h
> +++ b/xen/include/xen/serial.h
> @@ -9,6 +9,7 @@
>  #ifndef __XEN_SERIAL_H__
>  #define __XEN_SERIAL_H__
>  
> +#include <xen/init.h>
>  #include <xen/spinlock.h>
>  
>  struct cpu_user_regs;
> @@ -156,6 +157,12 @@ void ns16550_init(int index, struct ns16550_defaults *defaults);
>  void ehci_dbgp_init(void);
>  
>  void pl011_init(int index, unsigned long register_base_address);
> +/* Default value for UART on ARM boards */
> +struct serial_arm_defaults {
> +    int index;                              /* Serial index */
> +    unsigned long register_base_address;    /* Virtual base address */
> +};
> +void __init arm_uart_init(void);
>  
>  struct physdev_dbgp_op;
>  int dbgp_op(const struct physdev_dbgp_op *);

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 13:41       ` Ian Campbell
@ 2013-05-08 15:15         ` Julien Grall
  2013-05-08 15:34           ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:15 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:41 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
>>> Which only leaves ones which are both? How many are these? I'm inclined
>>> towards suggesting that if they are debug prints which are disabled by
>>> default and require a recompile to enable then the person doing the
>>> debugging can select whether they care about early or late messages by 
>>> #define-ing DEBUG or EARLY_DEBUG or both as required.
>>
>> We can't choose at compile time. Early printk function is in init code
>> section. So at the end of boot the function will disappear.
> 
> Oh, right.
> 
> Perhaps something could be conditional on system_state =
> SYS_STATE_active, this happens not long before we discard the initial
> sections.


I think it's too late. If we use early_printk until this stage, we will
lose some usefull debug when early printk is disabled (ie most of the time).

How about adding the missing system_state = SYS_STATE_boot just after
console_init_preirq? Early printk will only be used when system_state ==
SYS_STATE_early_boot.

>> Device tree function could be called after the end of the boot. For the
>> moment it's not the case.
>>
>> The best solution would be: early_printk is directly handled in console
>> as linux does.
> 
> That does sound best.


I will send a patch later for this.

-- 
Julien

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

* Re: [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver
  2013-05-08  2:33 ` [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver Julien Grall
@ 2013-05-08 15:17   ` Ian Campbell
  2013-05-08 16:23     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:17 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> @@ -227,32 +239,56 @@ static struct uart_driver __read_mostly pl011_driver = {
>      .tx_ready     = pl011_tx_ready,
>      .putc         = pl011_putc,
>      .getc         = pl011_getc,
> -    .irq          = pl011_irq
> +    .irq          = pl011_irq,
> +    .dt_irq_get   = pl011_dt_irq,
>  };
>  
> -/* TODO: Parse UART config from device-tree or command-line */
> -
> -void __init pl011_init(int index, unsigned long register_base_address)
> +/* TODO: Parse UART config from the command line */
> +static int __init pl011_uart_init(struct dt_device_node *dev,
> +                                  const void *data)
>  {
> +    const struct serial_arm_defaults *defaults = data;
>      struct pl011 *uart;
> +    int res;
>  
> -    if ( (index < 0) || (index > 1) )
> -        return;
> +    if ( (defaults->index < 0) || (defaults->index > 1) )
> +        return -EINVAL;
>  
> -    uart = &pl011_com[index];
> +    uart = &pl011_com[defaults->index];
>  
>      uart->clock_hz  = 0x16e3600;
>      uart->baud      = 38400;
>      uart->data_bits = 8;
>      uart->parity    = PARITY_NONE;
>      uart->stop_bits = 1;
> -    uart->irq       = 37; /* TODO Need to find this from devicetree */
> -    uart->regs      = (uint32_t *) register_base_address;
> +    uart->regs      = (uint32_t *) defaults->register_base_address;

Should this not come from struct dt_device_node?

Perhaps the driver needs to be instantiating its own FIXMAP mapping
instead of doing it in common code? In fact can we not get rid of the
fixmap for the runtime (not early) console and use the ioremap stuff
which Stefano just enabled with his vmap patches, or the early_ioremap
stuff if necessary.

That does then call into question the whole serial_arm_defaults thing.
Perhaps index should just be the order in which they are registered (and
at the moment it is effectively hardcoded to 0 anyway)

> +
> +    res = dt_device_get_irq(dev, 0, &uart->irq);
> +    if ( res )
> +    {
> +        early_printk("pl011: Unable to retrieve the IRQ\n");
> +        return res;
> +    }
>  
>      /* Register with generic serial driver. */
>      serial_register_uart(uart - pl011_com, &pl011_driver, uart);
> +
> +    dt_device_set_used_by(dev, DT_USED_BY_XEN);
> +
> +    return 0;
>  }

Ian.

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 13:52   ` Ian Campbell
@ 2013-05-08 15:22     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:22 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:52 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> ...
>>   - Use DOMID_XEN instead of DOMID_INVALID for DT_USED_BY_XEN
>> [...]
> 
>> +struct dt_device_node {
>> +    const char *name;
>> +    const char *type;
>> +    dt_phandle phandle;
>> +    char *full_name;
>> +    domid_t used_by; /* By default it's used by dom0 */
> 
> It occurred to me as I reviewed the rest of the series that since this
> actually a DOMID there is no reason not to use DOMID_XEN directly and
> remove DT_USED_BY_XEN.


Will be fix on the next patch series.

-- 
Julien

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

* Re: [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0
  2013-05-08  2:33 ` [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
@ 2013-05-08 15:28   ` Ian Campbell
  2013-05-08 16:59     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:28 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> - gic_route_irq_to_guest takes a dt_irq instead of an IRQ number
> - remove hardcoded address/IRQ
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - Use the new function dt_irq_is_level_trigger
>     - Disable DEBUG_DT by default
>     - Rename parse_device_tree to map_device_from_device_tree

Should be map_devices_...

> +        /**

Javadoc!

> +         * Don't map IRQ that have no physical meaning
> +         * ie: IRQ whose controller is not the GIC
> +         */
> +        if ( rirq.controller != dt_interrupt_controller )
> +        {
> +            DPRINT("irq %u skipped it controller (%s)\n",

you might mean "skipped its controller" ? But I think a clearer message
would be "irq %u not connected to primary controller" or something.

> +                   i, dt_node_full_name(rirq.controller));
> +            continue;
> +        }
> +
> +        res = dt_irq_translate(&rirq, &irq);
> +        if ( res )
> +        {
> +            printk(XENLOG_ERR "Unable to translate irq %u for %s\n",
> +                   i, dt_node_full_name(dev));
> +            return res;
> +        }
> +
> +        DPRINT("irq %u = %u type = %#x\n", i, irq.irq, irq.type);

The # format specifier is required by $STANDARD to not be all that
sensible and/or consistent when when the value is 0, i.e.
	printf("%#x\n", 0) => "0"
	printf("%#x\n", 1) => "0x1"
Worse if you use widths then:
        printf("%#02x\n", 0); => "00"
        printf("%#02x\n", 1); => "0x1"
        printf("%#04x\n", 0); => "0000"
    printf("%#04x\n", 1); => "0x01"
        
For this reason we tend to avoid # and just use "0x%...", assuming
irq==0 is a possibility, and likewise below addr==0 it's probably better
to avoid #.

> +        /* Don't check return because the IRQ can be use by multiple device */

"used by"

> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index f7b9889..ddad0c8 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -692,13 +692,14 @@ void gic_inject(void)
>          gic_inject_irq_start();
>  }
>  
> -int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
> +int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
>                             const char * devname)
>  {
>      struct irqaction *action;
> -    struct irq_desc *desc = irq_to_desc(irq);
> +    struct irq_desc *desc = irq_to_desc(irq->irq);
>      unsigned long flags;
>      int retval;
> +    bool_t level;
>  
>      action = xmalloc(struct irqaction);
>      if (!action)
> @@ -706,6 +707,7 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
>  
>      action->dev_id = d;
>      action->name = devname;
> +    action->free_on_release = 1;
>  
>      spin_lock_irqsave(&desc->lock, flags);
>      spin_lock(&gic.lock);
> @@ -713,9 +715,11 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
>      desc->handler = &gic_guest_irq_type;
>      desc->status |= IRQ_GUEST;
>  
> -    gic_set_irq_properties(irq, 1, 1u << smp_processor_id(), 0xa0);
> +    level = dt_irq_is_level_trigger(irq);
> +
> +    gic_set_irq_properties(irq->irq, level, 1u << smp_processor_id(), 0xa0);

By the end of this series are all callers going through the above dance?
git_set_irq_properties could take a dt_irq?

Ian.

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

* Re: [PATCH V2 08/33] xen/arm: Add helpers to use the device tree
  2013-05-08 13:18   ` Ian Campbell
@ 2013-05-08 15:31     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:31 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:18 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> Changes in v2:
>>     - use dt_node_cmp and dt_compat_cmp in early device tree code
>> ---
>>  xen/common/device_tree.c      |  127 ++++++++++++++++++++++++++++++++++++++++-
>>  xen/include/xen/device_tree.h |  120 ++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 245 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
>> index bdf8871..449c332 100644
>> --- a/xen/common/device_tree.c
>> +++ b/xen/common/device_tree.c
>> @@ -88,20 +88,23 @@ bool_t device_tree_type_matches(const void *fdt, int node, const char *match)
>>      if ( prop == NULL )
>>          return 0;
>>  
>> -    return !strcmp(prop, match);
>> +    return !dt_node_cmp(prop, match);
>>  }
>>  
>>  bool_t device_tree_node_compatible(const void *fdt, int node, const char *match)
> 
> Aside: I wonder if any of these should be __init...


I think yes.

> 
>>  {
>>      int len, l;
>> +    int mlen;
>>      const void *prop;
>>  
>> +    mlen = strlen(match);
>> +
>>      prop = fdt_getprop(fdt, node, "compatible", &len);
>>      if ( prop == NULL )
>>          return 0;
>>  
>>      while ( len > 0 ) {
>> -        if ( !strcmp(prop, match) )
>> +        if ( !dt_compat_cmp(prop, match, mlen) )
> 
> Is there a change in behaviour here where strlen(match) < strlen(prop)?
> 
> I may be mistaken but I think match=="foo" would be compatible with a
> node "foobar" now whereas it wasn't before.

I have checked the linux code and the also use strncmp with the length
of "match"/"compatible".

> On the otherhand this is the same behaviour as dt_device_is_compatible
> so maybe it is expected. I seem to recall some name matching code which
> explicitly wanted to handle foo@0 as matching foo and things, not sure
> that applies here though.


This behaviour only happens for the compatible node.

-- 
Julien Grall

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

* Re: [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from the device tree
  2013-05-08 13:23   ` Ian Campbell
@ 2013-05-08 15:32     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:32 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:23 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> ---
>>  xen/common/device_tree.c      |  343 +++++++++++++++++++++++++++++++++++++++++
>>  xen/include/xen/device_tree.h |   22 +++
>>  2 files changed, 365 insertions(+)
>>
>> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
>> index 449c332..8d37018 100644
>> --- a/xen/common/device_tree.c
>> +++ b/xen/common/device_tree.c
>> @@ -62,10 +62,38 @@ static void (*dt_printk)(const char *fmt, ...) = early_printk;
>>
>>  #ifdef DEBUG_DT
>>  # define dt_dprintk(fmt, args...) dt_printk(XENLOG_DEBUG fmt, ##args)
>> +static void dt_dump_addr(const char *s, const __be32 *addr, int na)
>> +{
>> +    dt_dprintk("%s", s);
>> +    while ( na-- )
>> +        dt_dprintk(" %08x", be32_to_cpu(*(addr++)));
>> +    dt_dprintk("\n");
>> +}
>>  #else
>>  # define dt_dprintk(fmt, args...) do {} while ( 0 )
>> +static void dt_dump_addr(const char *s, const __be32 *addr, int na) { }
>>  #endif
>>
>> +#define DT_BAD_ADDR ((u64)-1)
>> +
>> +/* Max address size we deal with */
>> +#define DT_MAX_ADDR_CELLS 4
>> +#define DT_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= DT_MAX_ADDR_CELLS)
>> +#define DT_CHECK_COUNTS(na, ns) (DT_CHECK_ADDR_COUNT(na) && (ns) > 0)
>> +
>> +/* Callbacks for bus specific translators */
>> +struct dt_bus
>> +{
>> +    const char *name;
>> +    const char *addresses;
>> +    int (*match)(const struct dt_device_node *parent);
>> +    void (*count_cells)(const struct dt_device_node *child,
>> +                        int *addrc, int *sizec);
>> +    u64        (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna);
>> +       int (*translate)(__be32 *addr, u64 offset, int na);
>> +       unsigned int (*get_flags)(const __be32 *addr);
> 
> Spacing is weird here. Hard tabs perhaps?


Right. I will fix all the errors on the next patch series.

-- 
Julien

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

* Re: [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-08  2:33 ` [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
@ 2013-05-08 15:32   ` Ian Campbell
  2013-05-08 15:35     ` Ian Campbell
  2013-05-08 16:38     ` Julien Grall
  0 siblings, 2 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:32 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
> index bfc41c2..1114fe7 100644
> --- a/xen/arch/arm/time.c
> +++ b/xen/arch/arm/time.c
> @@ -33,6 +33,7 @@
>  #include <asm/time.h>
>  #include <asm/gic.h>
>  #include <asm/cpufeature.h>
> +#include <asm/platform.h>
>  
>  /*
>   * Unfortunately the hypervisor timer interrupt appears to be buggy in
> @@ -130,6 +131,11 @@ int __init init_xen_time(void)
>          panic("CPU does not support the Generic Timer v1 interface.\n");
>  
>      cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;

Might be better to read this after platform_init_time, in case p_i_t
does something "magic" on this platform?

> +/* Helper to read/write a register */
> +static inline uint32_t platform_read_register(uint32_t addr)
> +{
> +    volatile const uint32_t *reg;
> +    uint32_t value;
> +
> +    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
> +    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
> +    value = *reg;
> +    dsb(); isb();
> +    clear_fixmap(FIXMAP_MISC);

I don't think the fixmap is per-PCPU so you probably want some locking
here.

FIXMAP_MISC is a bit of an awful thing, but this isn't especially new,
so OK.

> +
> +    return value;
> +}
> +
> +static inline void platform_write_register(uint32_t addr, uint32_t value)
> +{
> +    volatile uint32_t *reg;
> +
> +    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
> +    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
> +    *reg = value;
> +    clear_fixmap(FIXMAP_MISC);
> +}
> +

Ian.

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 15:15         ` Julien Grall
@ 2013-05-08 15:34           ` Ian Campbell
  2013-05-09 14:38             ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:34 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 16:15 +0100, Julien Grall wrote:
> On 05/08/2013 02:41 PM, Ian Campbell wrote:
> 
> > On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
> >>> Which only leaves ones which are both? How many are these? I'm inclined
> >>> towards suggesting that if they are debug prints which are disabled by
> >>> default and require a recompile to enable then the person doing the
> >>> debugging can select whether they care about early or late messages by 
> >>> #define-ing DEBUG or EARLY_DEBUG or both as required.
> >>
> >> We can't choose at compile time. Early printk function is in init code
> >> section. So at the end of boot the function will disappear.
> > 
> > Oh, right.
> > 
> > Perhaps something could be conditional on system_state =
> > SYS_STATE_active, this happens not long before we discard the initial
> > sections.
> 
> 
> I think it's too late. If we use early_printk until this stage, we will
> lose some usefull debug when early printk is disabled (ie most of the time).
> 
> How about adding the missing system_state = SYS_STATE_boot just after
> console_init_preirq? Early printk will only be used when system_state ==
> SYS_STATE_early_boot.

I think this is a common thing so it'd need wider discussion.

> >> Device tree function could be called after the end of the boot. For the
> >> moment it's not the case.
> >>
> >> The best solution would be: early_printk is directly handled in console
> >> as linux does.
> > 
> > That does sound best.
> 
> 
> I will send a patch later for this.

Does that make the above moot?

Ian.

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

* Re: [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-08 15:32   ` Ian Campbell
@ 2013-05-08 15:35     ` Ian Campbell
  2013-05-08 16:32       ` Julien Grall
  2013-05-08 16:38     ` Julien Grall
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:35 UTC (permalink / raw)
  To: Julien Grall; +Cc: patches, xen-devel, Stefano Stabellini

On Wed, 2013-05-08 at 16:32 +0100, Ian Campbell wrote:
> > +/* Helper to read/write a register */
> > +static inline uint32_t platform_read_register(uint32_t addr)
> > +{
> > +    volatile const uint32_t *reg;
> > +    uint32_t value;
> > +
> > +    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
> > +    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
> > +    value = *reg;
> > +    dsb(); isb();
> > +    clear_fixmap(FIXMAP_MISC);
> 
> I don't think the fixmap is per-PCPU so you probably want some locking
> here.
> 
> FIXMAP_MISC is a bit of an awful thing, but this isn't especially new,
> so OK.

In fact now I'm wondering if the platform specific code shouldn't
establish its own permanent mapping with ioremap and use that.

Ian.

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

* Re: [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-08 13:46   ` Ian Campbell
@ 2013-05-08 15:49     ` Julien Grall
  2013-05-08 15:56       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:49 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:46 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> - Remove early parsing for GIC addresses
>> - Remove hard coded maintenance IRQ number
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> Changes in v2:
>>     - use the new function request_dt_irq
>> ---
>>  xen/arch/arm/gic.c            |   63 ++++++++++++++++++++++++++++-------------
>>  xen/common/device_tree.c      |   42 ---------------------------
>>  xen/include/xen/device_tree.h |    8 ------
>>  3 files changed, 43 insertions(+), 70 deletions(-)
>>
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index 1efa9a3..34304b3 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -45,6 +45,7 @@ static struct {
>>      paddr_t hbase;       /* Address of virtual interface registers */
>>      paddr_t vbase;       /* Address of virtual cpu interface registers */
>>      unsigned int lines;  /* Number of interrupts (SPIs + PPIs + SGIs) */
>> +    struct dt_irq maintenance; /* IRQ maintenance */
>>      unsigned int cpus;
>>      spinlock_t lock;
>>  } gic;
>> @@ -352,28 +353,49 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
>>  /* Set up the GIC */
>>  void __init gic_init(void)
>>  {
>> +    struct dt_device_node *node;
>> +    int res;
>> +
>> +    node = dt_find_interrupt_controller("arm,cortex-a15-gic");
>> +    if ( !node )
>> +        panic("Unable to find compatible GIC in the device tree\n");
>> +
>> +    dt_device_set_used_by(node, DT_USED_BY_XEN);
>> +
>> +    res = dt_device_get_address(node, 0, &gic.dbase, NULL);
>> +    if ( res || !gic.dbase || (gic.dbase & ~PAGE_MASK) )
>> +        panic("GIC: Cannot find a valid address for the distributor\n");
>> +
>> +    res = dt_device_get_address(node, 1, &gic.cbase, NULL);
>> +    if ( res || !gic.cbase || (gic.cbase & ~PAGE_MASK) )
>> +        panic("GIC: Cannot find a valid address for the CPU\n");
>> +
>> +    res = dt_device_get_address(node, 2, &gic.hbase, NULL);
>> +    if ( res || !gic.hbase || (gic.hbase & ~PAGE_MASK) )
>> +        panic("GIC: Cannot find a valid address for the hypervisor\n");
>> +
>> +    res = dt_device_get_address(node, 3, &gic.vbase, NULL);
>> +    if ( res || !gic.vbase || (gic.vbase & ~PAGE_MASK) )
>> +        panic("GIC: Cannot find a valid address for the virtual CPU\n");
>> +
>> +    res = dt_device_get_irq(node, 0, &gic.maintenance);
>> +    if ( res )
>> +        panic("GIC: Cannot find the maintenance IRQ\n");
>> +
>> +    /* Set the GIC as the primary interrupt controller */
>> +    dt_interrupt_controller = node;
>> +
>> +    /* TODO: Add check on distributor, cpu size */
>> +
>>      printk("GIC initialization:\n"
>>                "        gic_dist_addr=%"PRIpaddr"\n"
>>                "        gic_cpu_addr=%"PRIpaddr"\n"
>>                "        gic_hyp_addr=%"PRIpaddr"\n"
>> -              "        gic_vcpu_addr=%"PRIpaddr"\n",
>> -              early_info.gic.gic_dist_addr, early_info.gic.gic_cpu_addr,
>> -              early_info.gic.gic_hyp_addr, early_info.gic.gic_vcpu_addr);
>> -    if ( !early_info.gic.gic_dist_addr ||
>> -         !early_info.gic.gic_cpu_addr ||
>> -         !early_info.gic.gic_hyp_addr ||
>> -         !early_info.gic.gic_vcpu_addr )
>> -        panic("the physical address of one of the GIC interfaces is missing\n");
>> -    if ( (early_info.gic.gic_dist_addr & ~PAGE_MASK) ||
>> -         (early_info.gic.gic_cpu_addr & ~PAGE_MASK) ||
>> -         (early_info.gic.gic_hyp_addr & ~PAGE_MASK) ||
>> -         (early_info.gic.gic_vcpu_addr & ~PAGE_MASK) )
>> -        panic("GIC interfaces not page aligned.\n");
> 
> Please can we keep this last check separate and after the print, this
> way we get to see why it failed (not present vs invalid).


I will fix it on the next patch series.

> 
> I'm ambivalent about keeping the !gic.Xbase separate or including it in
> the res check.


I don't see a good reason why the gic base address could not be 0. I
prefer to remove this check.

-- 
Julien

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

* Re: [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree
  2013-05-08 13:50   ` Ian Campbell
@ 2013-05-08 15:53     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:53 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:50 PM, Ian Campbell wrote:

>> @@ -167,6 +204,15 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
>>      vgic_vcpu_inject_irq(current, irq, 1);
>>  }
>>  
>> +/* Route timer's IRQ on this CPU */
>> +void __cpuinit route_timer_interrupt(void)
>> +{
>> +    gic_route_dt_irq(&timer_irq[PHYS_NONSECURE_PPI],
>> +                     1u << smp_processor_id(), 0xa0);
>> +    gic_route_dt_irq(&timer_irq[HYP_PPI], 1u << smp_processor_id(), 0xa0);
>> +    gic_route_dt_irq(&timer_irq[VIRT_PPI], 1u << smp_processor_id(), 0xa0);
> 
> It occurs to me that this guy (and the underlying function) should
> probably take a cpumask_t. Not now though.
> 
>> +}
>> +
>>  /* Set up the timer interrupt on this CPU */
>>  void __cpuinit init_timer_interrupt(void)
>>  {
>> @@ -184,10 +230,11 @@ void __cpuinit init_timer_interrupt(void)
>>      WRITE_SYSREG32(0, CNTHP_CTL_EL2);   /* Hypervisor's timer disabled */
>>      isb();
>>  
>> -    /* XXX Need to find this IRQ number from devicetree? */
>> -    request_irq(26, timer_interrupt, 0, "hyptimer", NULL);
>> -    request_irq(27, vtimer_interrupt, 0, "virtimer", NULL);
>> -    request_irq(30, timer_interrupt, 0, "phytimer", NULL);
>> +    request_dt_irq(&timer_irq[HYP_PPI], timer_interrupt, 0, "hyptimer", NULL);
>> +    request_dt_irq(&timer_irq[VIRT_PPI], vtimer_interrupt, 0,
>> +                   "virtimer", NULL);
>> +    request_dt_irq(&timer_irq[PHYS_NONSECURE_PPI], timer_interrupt, 2,
>> +                   "phytimer", NULL);
> 
> Why the change to flags == 2 here?


It's a mistake. I will fix it on the next patch series.

-- 
Julien

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

* Re: [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0
  2013-05-08  2:33 ` [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
@ 2013-05-08 15:54   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:54 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Currently xen doesn't implement SYS MMU. When a device will talk with dom0
> with DMA request the domain will use GFN instead of MFN.
> For instance on the arndale board, without this patch the network doesn't
> work.
> 
> The 1:1 mapping is a workaround and MUST be remove as soon as a SYS MMU is
> implemented in XEN.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

(Somewhat reluctantly) Acked-by: Ian Campbell <ian.campbell@citrix.com>

I consider this to be a temporary workaround and at some point (possibly
even as soon as 4.4) I intend to push for its removal, even if this
breaks some platforms which have not by then implemented SYS MMU support
for whatever reason.

Vendors who care about support for their platform under Xen need to sort
out SYS MMU support for them sooner rather than later (which probably
means patches, but documentation would be at least a tolerable
alternative).

> + * Usefull on platform where System MMU is not yet implemented

"Useful"

Ian.

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

* Re: [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-08 15:49     ` Julien Grall
@ 2013-05-08 15:56       ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 15:56 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 16:49 +0100, Julien Grall wrote:
> On 05/08/2013 02:46 PM, Ian Campbell wrote:

> > Please can we keep this last check separate and after the print, this
> > way we get to see why it failed (not present vs invalid).
> 
> 
> I will fix it on the next patch series.

Thanks.

> > 
> > I'm ambivalent about keeping the !gic.Xbase separate or including it in
> > the res check.
> 
> 
> I don't see a good reason why the gic base address could not be 0. I
> prefer to remove this check.

True, agreed.

Ian.

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

* Re: [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree
  2013-05-08 14:01   ` Ian Campbell
@ 2013-05-08 15:58     ` Julien Grall
  2013-05-08 16:41       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08 15:58 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, Keir Fraser, patches, xen-devel

On 05/08/2013 03:01 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> This generic UART will find the right UART via xen command line
>> with dtuart=myserial.
> 
> I suppose there way to determine sensible default, since it differs on
> every platform?
> 
>> "myserial" is the alias of the UART in the device tree. Xen will retrieve
>> the information via the device tree and call the initialization function for
>> this specific UART thanks to the device API.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> You need to CC code code maintainers when you change core code. Keir
> added.
>>
>> Changes in v2:
>>     - Use dtuart parameter instead of com1. The first one is more arm
>>     while the latter is more x86
>> ---
>>  xen/arch/arm/setup.c         |    3 +-
>>  xen/drivers/char/Makefile    |    1 +
>>  xen/drivers/char/arm-uart.c  |   81 ++++++++++++++++++++++++++++++++++++++++++
>>  xen/drivers/char/serial.c    |    6 ++++
>>  xen/include/asm-arm/config.h |    2 +-
>>  xen/include/xen/serial.h     |    7 ++++
>>  6 files changed, 98 insertions(+), 2 deletions(-)
>>  create mode 100644 xen/drivers/char/arm-uart.c
>>
>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index e4228f7..7b2df8b 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -435,8 +435,9 @@ void __init start_xen(unsigned long boot_phys_offset,
>>  #ifdef EARLY_UART_ADDRESS
>>      /* TODO Need to get device tree or command line for UART address */
>>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
>> -    console_init_preirq();
>>  #endif
>> +    arm_uart_init();
>> +    console_init_preirq();
>>  
>>      /* FIXME: Do something smarter */
>>      dt_switch_to_printk();
>> diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
>> index ab2246d..e68a54a 100644
>> --- a/xen/drivers/char/Makefile
>> +++ b/xen/drivers/char/Makefile
>> @@ -2,4 +2,5 @@ obj-y += console.o
>>  obj-$(HAS_NS16550) += ns16550.o
>>  obj-$(HAS_PL011) += pl011.o
>>  obj-$(HAS_EHCI) += ehci-dbgp.o
>> +obj-$(CONFIG_ARM) += arm-uart.o
>>  obj-y += serial.o
>> diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c
>> new file mode 100644
>> index 0000000..c76875e
>> --- /dev/null
>> +++ b/xen/drivers/char/arm-uart.c
>> @@ -0,0 +1,81 @@
>> +/*
>> + * xen/drivers/char/arm-uart.c
>> + *
>> + * Generic ARM uart retrieved via the device tree
>> + *
>> + * Julien Grall <julien.grall@linaro.org>
>> + * Copyright (c) 2013 Linaro Limited.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <asm/device.h>
>> +#include <asm/early_printk.h>
>> +#include <asm/types.h>
>> +#include <xen/console.h>
>> +#include <xen/device_tree.h>
>> +#include <xen/mm.h>
>> +#include <xen/serial.h>
>> +
>> +/*
>> + * Configure UART port with a string:
>> + * alias
>> + *
>> + * @alias: alias used in the device tree for the UART
>> + * TODO: Implement config  in each UART driver.
>> + */
>> +static char __initdata opt_dtuart[30] = "";
>> +string_param("dtuart", opt_dtuart);
>> +
>> +void __init arm_uart_init(void)
> 
> This (and the file and struct serial_arm_defaults etc) could perhaps be
> better called dt_uart_init etc? There's nothing inherently ARM specific
> here.

The FIXMAP_CONSOLE is ARM specific it can not works on x86. I'm
wondering if it's usefull to move FIXMAP_CONSOLE on each UART driver.

>> +{
>> +    struct dt_device_node *dev;
>> +    int ret;
>> +    u64 addr, size;
>> +    struct serial_arm_defaults defaults;
>> +    const char *devalias = opt_dtuart;
>> +
>> +    if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
>> +    {
>> +        early_printk("No console\n");
>> +        return;
>> +    }
>> +
>> +    early_printk("Looking for UART console %s\n", devalias);
>> +    dev = dt_find_node_by_alias(devalias);
>> +
>> +    if ( !dev )
>> +    {
>> +        early_printk("Unable to find device \"%s\"\n", devalias);
>> +        return;
>> +    }
>> +
>> +    /* TODO: Handle UART with 0 or multiple base address */
>> +    ret = dt_device_get_address(dev, 0, &addr, &size);
>> +    if ( ret )
>> +    {
>> +        early_printk("Unable to retrieve the base address of the serial\n");
>> +        return;
>> +    }
>> +
>> +    clear_fixmap(FIXMAP_CONSOLE);
>> +    set_fixmap(FIXMAP_CONSOLE, addr >> PAGE_SHIFT, DEV_SHARED);
>> +
>> +    addr = FIXMAP_ADDR(FIXMAP_CONSOLE) + (addr & (PAGE_SIZE - 1));
>> +
>> +    defaults.index = 0;
>> +    defaults.register_base_address = addr;
>> +
>> +    ret = device_init(dev, DEVICE_SERIAL, &defaults);
>> +
>> +    if ( ret )
>> +        early_printk("Unable to initialize serial: %d\n", ret);
>> +}
>> diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
>> index 0ae7e4d..c4c4a84 100644
>> --- a/xen/drivers/char/serial.c
>> +++ b/xen/drivers/char/serial.c
>> @@ -271,6 +271,12 @@ int __init serial_parse_handle(char *conf)
>>          goto common;
>>      }
>>  
>> +    if ( !strncmp(conf, "dtuart", 5) )
>> +    {
>> +        handle = SERHND_COM1;
> 
> Do you mean COM1 here? Or did you intend to add SERHND_DT?

I mean COM1, I use the first serial slot for dtuart. I don't really see
why we need to extend the number of serial slot.

-- 
Julien

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

* Re: [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver
  2013-05-08 15:17   ` Ian Campbell
@ 2013-05-08 16:23     ` Julien Grall
  2013-05-08 16:43       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-08 16:23 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 04:17 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> @@ -227,32 +239,56 @@ static struct uart_driver __read_mostly pl011_driver = {
>>      .tx_ready     = pl011_tx_ready,
>>      .putc         = pl011_putc,
>>      .getc         = pl011_getc,
>> -    .irq          = pl011_irq
>> +    .irq          = pl011_irq,
>> +    .dt_irq_get   = pl011_dt_irq,
>>  };
>>  
>> -/* TODO: Parse UART config from device-tree or command-line */
>> -
>> -void __init pl011_init(int index, unsigned long register_base_address)
>> +/* TODO: Parse UART config from the command line */
>> +static int __init pl011_uart_init(struct dt_device_node *dev,
>> +                                  const void *data)
>>  {
>> +    const struct serial_arm_defaults *defaults = data;
>>      struct pl011 *uart;
>> +    int res;
>>  
>> -    if ( (index < 0) || (index > 1) )
>> -        return;
>> +    if ( (defaults->index < 0) || (defaults->index > 1) )
>> +        return -EINVAL;
>>  
>> -    uart = &pl011_com[index];
>> +    uart = &pl011_com[defaults->index];
>>  
>>      uart->clock_hz  = 0x16e3600;
>>      uart->baud      = 38400;
>>      uart->data_bits = 8;
>>      uart->parity    = PARITY_NONE;
>>      uart->stop_bits = 1;
>> -    uart->irq       = 37; /* TODO Need to find this from devicetree */
>> -    uart->regs      = (uint32_t *) register_base_address;
>> +    uart->regs      = (uint32_t *) defaults->register_base_address;
> 
> Should this not come from struct dt_device_node?
> 
> Perhaps the driver needs to be instantiating its own FIXMAP mapping
> instead of doing it in common code? In fact can we not get rid of the
> fixmap for the runtime (not early) console and use the ioremap stuff
> which Stefano just enabled with his vmap patches, or the early_ioremap
> stuff if necessary.

Right. I will use ioremap in the next patch series.

> That does then call into question the whole serial_arm_defaults thing.
> Perhaps index should just be the order in which they are registered (and
> at the moment it is effectively hardcoded to 0 anyway)


I'm thinking about using serial_arm_defaults for baud rate,... For the
moment the different values are hardcoded.

{arm,dt}_init_uart will parse the dtuart parameters on the command line
and then fill serial_arm_defaults.

-- 
Julien

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

* Re: [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-08 15:35     ` Ian Campbell
@ 2013-05-08 16:32       ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 16:32 UTC (permalink / raw)
  To: Ian Campbell; +Cc: patches, xen-devel, Stefano Stabellini

On 05/08/2013 04:35 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 16:32 +0100, Ian Campbell wrote:
>>> +/* Helper to read/write a register */
>>> +static inline uint32_t platform_read_register(uint32_t addr)
>>> +{
>>> +    volatile const uint32_t *reg;
>>> +    uint32_t value;
>>> +
>>> +    set_fixmap(FIXMAP_MISC, addr >> PAGE_SHIFT, DEV_SHARED);
>>> +    reg = (uint32_t *)(FIXMAP_ADDR(FIXMAP_MISC) + (addr & ~PAGE_MASK));
>>> +    value = *reg;
>>> +    dsb(); isb();
>>> +    clear_fixmap(FIXMAP_MISC);
>>
>> I don't think the fixmap is per-PCPU so you probably want some locking
>> here.
>>
>> FIXMAP_MISC is a bit of an awful thing, but this isn't especially new,
>> so OK.
> 
> In fact now I'm wondering if the platform specific code shouldn't
> establish its own permanent mapping with ioremap and use that.

I will rework this patch with ioremap

-- 
Julien

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

* Re: [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-08 15:32   ` Ian Campbell
  2013-05-08 15:35     ` Ian Campbell
@ 2013-05-08 16:38     ` Julien Grall
  1 sibling, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 16:38 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 04:32 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
>> index bfc41c2..1114fe7 100644
>> --- a/xen/arch/arm/time.c
>> +++ b/xen/arch/arm/time.c
>> @@ -33,6 +33,7 @@
>>  #include <asm/time.h>
>>  #include <asm/gic.h>
>>  #include <asm/cpufeature.h>
>> +#include <asm/platform.h>
>>  
>>  /*
>>   * Unfortunately the hypervisor timer interrupt appears to be buggy in
>> @@ -130,6 +131,11 @@ int __init init_xen_time(void)
>>          panic("CPU does not support the Generic Timer v1 interface.\n");
>>  
>>      cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
> 
> Might be better to read this after platform_init_time, in case p_i_t
> does something "magic" on this platform?


Ok. I will move the platform_init_time just before.

-- 
Julien

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

* Re: [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree
  2013-05-08 15:58     ` Julien Grall
@ 2013-05-08 16:41       ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 16:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, Keir (Xen.org), patches, xen-devel

On Wed, 2013-05-08 at 16:58 +0100, Julien Grall wrote:
> On 05/08/2013 03:01 PM, Ian Campbell wrote:
> 
> > On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> >> This generic UART will find the right UART via xen command line
> >> with dtuart=myserial.
> > 
> > I suppose there way to determine sensible default, since it differs on
> > every platform?
> > 
> >> "myserial" is the alias of the UART in the device tree. Xen will retrieve
> >> the information via the device tree and call the initialization function for
> >> this specific UART thanks to the device API.
> >>
> >> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> > 
> > You need to CC code code maintainers when you change core code. Keir
> > added.
> >>
> >> Changes in v2:
> >>     - Use dtuart parameter instead of com1. The first one is more arm
> >>     while the latter is more x86
> >> ---
> >>  xen/arch/arm/setup.c         |    3 +-
> >>  xen/drivers/char/Makefile    |    1 +
> >>  xen/drivers/char/arm-uart.c  |   81 ++++++++++++++++++++++++++++++++++++++++++
> >>  xen/drivers/char/serial.c    |    6 ++++
> >>  xen/include/asm-arm/config.h |    2 +-
> >>  xen/include/xen/serial.h     |    7 ++++
> >>  6 files changed, 98 insertions(+), 2 deletions(-)
> >>  create mode 100644 xen/drivers/char/arm-uart.c
> >>
> >> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> >> index e4228f7..7b2df8b 100644
> >> --- a/xen/arch/arm/setup.c
> >> +++ b/xen/arch/arm/setup.c
> >> @@ -435,8 +435,9 @@ void __init start_xen(unsigned long boot_phys_offset,
> >>  #ifdef EARLY_UART_ADDRESS
> >>      /* TODO Need to get device tree or command line for UART address */
> >>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
> >> -    console_init_preirq();
> >>  #endif
> >> +    arm_uart_init();
> >> +    console_init_preirq();
> >>  
> >>      /* FIXME: Do something smarter */
> >>      dt_switch_to_printk();
> >> diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
> >> index ab2246d..e68a54a 100644
> >> --- a/xen/drivers/char/Makefile
> >> +++ b/xen/drivers/char/Makefile
> >> @@ -2,4 +2,5 @@ obj-y += console.o
> >>  obj-$(HAS_NS16550) += ns16550.o
> >>  obj-$(HAS_PL011) += pl011.o
> >>  obj-$(HAS_EHCI) += ehci-dbgp.o
> >> +obj-$(CONFIG_ARM) += arm-uart.o
> >>  obj-y += serial.o
> >> diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c
> >> new file mode 100644
> >> index 0000000..c76875e
> >> --- /dev/null
> >> +++ b/xen/drivers/char/arm-uart.c
> >> @@ -0,0 +1,81 @@
> >> +/*
> >> + * xen/drivers/char/arm-uart.c
> >> + *
> >> + * Generic ARM uart retrieved via the device tree
> >> + *
> >> + * Julien Grall <julien.grall@linaro.org>
> >> + * Copyright (c) 2013 Linaro Limited.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as published by
> >> + * the Free Software Foundation; either version 2 of the License, or
> >> + * (at your option) any later version.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + */
> >> +
> >> +#include <asm/device.h>
> >> +#include <asm/early_printk.h>
> >> +#include <asm/types.h>
> >> +#include <xen/console.h>
> >> +#include <xen/device_tree.h>
> >> +#include <xen/mm.h>
> >> +#include <xen/serial.h>
> >> +
> >> +/*
> >> + * Configure UART port with a string:
> >> + * alias
> >> + *
> >> + * @alias: alias used in the device tree for the UART
> >> + * TODO: Implement config  in each UART driver.
> >> + */
> >> +static char __initdata opt_dtuart[30] = "";
> >> +string_param("dtuart", opt_dtuart);
> >> +
> >> +void __init arm_uart_init(void)
> > 
> > This (and the file and struct serial_arm_defaults etc) could perhaps be
> > better called dt_uart_init etc? There's nothing inherently ARM specific
> > here.
> 
> The FIXMAP_CONSOLE is ARM specific it can not works on x86. I'm
> wondering if it's usefull to move FIXMAP_CONSOLE on each UART driver.

I think I came to the same conclusion later in the series too, or more
likely the uart drivers should use ioremap.

> >> +    if ( !strncmp(conf, "dtuart", 5) )
> >> +    {
> >> +        handle = SERHND_COM1;
> > 
> > Do you mean COM1 here? Or did you intend to add SERHND_DT?
> 
> I mean COM1, I use the first serial slot for dtuart. I don't really see
> why we need to extend the number of serial slot.

I just dislike using things with one name for another purpose.

Ultimately this bit is up to Keir though.

Ian.

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

* Re: [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver
  2013-05-08 16:23     ` Julien Grall
@ 2013-05-08 16:43       ` Ian Campbell
  2013-05-08 16:55         ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-08 16:43 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 17:23 +0100, Julien Grall wrote:
> > That does then call into question the whole serial_arm_defaults thing.
> > Perhaps index should just be the order in which they are registered (and
> > at the moment it is effectively hardcoded to 0 anyway)
> 
> 
> I'm thinking about using serial_arm_defaults for baud rate,... For the
> moment the different values are hardcoded.
> 
> {arm,dt}_init_uart will parse the dtuart parameters on the command line
> and then fill serial_arm_defaults.

Perhaps instead of &serial_arm_defaults you should pass a char * pointer
to opt_dtuart? This would allow for per-device settings and is
consistent with the ns16550 driver.

Ian.

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

* Re: [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver
  2013-05-08 16:43       ` Ian Campbell
@ 2013-05-08 16:55         ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 16:55 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 05:43 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 17:23 +0100, Julien Grall wrote:
>>> That does then call into question the whole serial_arm_defaults thing.
>>> Perhaps index should just be the order in which they are registered (and
>>> at the moment it is effectively hardcoded to 0 anyway)
>>
>>
>> I'm thinking about using serial_arm_defaults for baud rate,... For the
>> moment the different values are hardcoded.
>>
>> {arm,dt}_init_uart will parse the dtuart parameters on the command line
>> and then fill serial_arm_defaults.
> 
> Perhaps instead of &serial_arm_defaults you should pass a char * pointer
> to opt_dtuart? This would allow for per-device settings and is
> consistent with the ns16550 driver.

Ok. I will modify it in the next patch series.

-- 
Julien

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

* Re: [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0
  2013-05-08 15:28   ` Ian Campbell
@ 2013-05-08 16:59     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-08 16:59 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 04:28 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> - gic_route_irq_to_guest takes a dt_irq instead of an IRQ number
>> - remove hardcoded address/IRQ
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> Changes in v2:
>>     - Use the new function dt_irq_is_level_trigger
>>     - Disable DEBUG_DT by default
>>     - Rename parse_device_tree to map_device_from_device_tree
> 
> Should be map_devices_...

Will be fix on the next patch series.

>> +        /**
> 
> Javadoc!
> 
>> +         * Don't map IRQ that have no physical meaning
>> +         * ie: IRQ whose controller is not the GIC
>> +         */
>> +        if ( rirq.controller != dt_interrupt_controller )
>> +        {
>> +            DPRINT("irq %u skipped it controller (%s)\n",
> 
> you might mean "skipped its controller" ? But I think a clearer message
> would be "irq %u not connected to primary controller" or something.
> 
>> +                   i, dt_node_full_name(rirq.controller));
>> +            continue;
>> +        }
>> +
>> +        res = dt_irq_translate(&rirq, &irq);
>> +        if ( res )
>> +        {
>> +            printk(XENLOG_ERR "Unable to translate irq %u for %s\n",
>> +                   i, dt_node_full_name(dev));
>> +            return res;
>> +        }
>> +
>> +        DPRINT("irq %u = %u type = %#x\n", i, irq.irq, irq.type);
> 
> The # format specifier is required by $STANDARD to not be all that
> sensible and/or consistent when when the value is 0, i.e.
> 	printf("%#x\n", 0) => "0"
> 	printf("%#x\n", 1) => "0x1"
> Worse if you use widths then:
>         printf("%#02x\n", 0); => "00"
>         printf("%#02x\n", 1); => "0x1"
>         printf("%#04x\n", 0); => "0000"
>     printf("%#04x\n", 1); => "0x01"
>         
> For this reason we tend to avoid # and just use "0x%...", assuming
> irq==0 is a possibility, and likewise below addr==0 it's probably better
> to avoid #.

Thanks for this hint. I will replace all my %#x by 0x%x.

>> +        /* Don't check return because the IRQ can be use by multiple device */
> 
> "used by"
> 
>> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
>> index f7b9889..ddad0c8 100644
>> --- a/xen/arch/arm/gic.c
>> +++ b/xen/arch/arm/gic.c
>> @@ -692,13 +692,14 @@ void gic_inject(void)
>>          gic_inject_irq_start();
>>  }
>>  
>> -int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
>> +int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
>>                             const char * devname)
>>  {
>>      struct irqaction *action;
>> -    struct irq_desc *desc = irq_to_desc(irq);
>> +    struct irq_desc *desc = irq_to_desc(irq->irq);
>>      unsigned long flags;
>>      int retval;
>> +    bool_t level;
>>  
>>      action = xmalloc(struct irqaction);
>>      if (!action)
>> @@ -706,6 +707,7 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
>>  
>>      action->dev_id = d;
>>      action->name = devname;
>> +    action->free_on_release = 1;
>>  
>>      spin_lock_irqsave(&desc->lock, flags);
>>      spin_lock(&gic.lock);
>> @@ -713,9 +715,11 @@ int gic_route_irq_to_guest(struct domain *d, unsigned int irq,
>>      desc->handler = &gic_guest_irq_type;
>>      desc->status |= IRQ_GUEST;
>>  
>> -    gic_set_irq_properties(irq, 1, 1u << smp_processor_id(), 0xa0);
>> +    level = dt_irq_is_level_trigger(irq);
>> +
>> +    gic_set_irq_properties(irq->irq, level, 1u << smp_processor_id(), 0xa0);
> 
> By the end of this series are all callers going through the above dance?
> git_set_irq_properties could take a dt_irq?


No. I can add patch to use a dt_irq.

-- 
Julien

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

* Re: [PATCH V2 26/33] xen/arm: remove request_irq
  2013-05-08  2:33 ` [PATCH V2 26/33] xen/arm: remove request_irq Julien Grall
@ 2013-05-09  9:59   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-09  9:59 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> All calls to this function in ARM code have been removed. This function SHOULD
> not be used. If someone calls this function, a linking error will occur.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 27/33] xen/arm: remove setup_irq
  2013-05-08  2:33 ` [PATCH V2 27/33] xen/arm: remove setup_irq Julien Grall
@ 2013-05-09 10:00   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:00 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> All calls to this function in ARM code have been removed. This function SHOULD
> not be used. If someone calls this function, a linking error will occur.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk
  2013-05-08  2:33 ` [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
@ 2013-05-09 10:10   ` Ian Campbell
  2013-05-09 13:14     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:10 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
> index 1ad3364..6af8ca3 100644
> --- a/xen/arch/arm/arm32/Makefile
> +++ b/xen/arch/arm/arm32/Makefile
> @@ -5,4 +5,7 @@ obj-y += mode_switch.o
>  obj-y += proc-ca15.o
> 
>  obj-y += traps.o
> -obj-y += domain.o
> \ No newline at end of file
> +obj-y += domain.o
> +
> +obj-$(EARLY_PRINTK) += debug.o
> +obj-$(CONFIG_EARLY_PL011) += debug-pl011.o

Is this correct now that you are using debug-pl011.inc?

>  /* Print a 32-bit number in hex.  Specific to the PL011 UART.
>   * r0: Number to print.
> - * clobbers r0-r3 */
> + * r11: Early UART base address
> + * clobbers r1-r3 */

This still clobbers r0, via the lsl below.

>  putn:
>          adr   r1, hex
>          mov   r3, #8
> -1:      ldr   r2, [r11, #0x18]       /* <- UARTFR (Flag register) */
> -        tst   r2, #0x8               /* Check BUSY bit */
> -        bne   1b                     /* Wait for the UART to be ready */
> +1:
> +        early_uart_ready r11, r2
>          and   r2, r0, #0xf0000000    /* Mask off the top nybble */
>          ldrb  r2, [r1, r2, lsr #28]  /* Convert to a char */
> -        str   r2, [r11]              /* -> UARTDR (Data Register) */
> +        early_uart_transmit r11, r2
>          lsl   r0, #4                 /* Roll it through one nybble at a time */
>          subs  r3, r3, #1
>          bne   1b
> @@ -329,51 +329,44 @@ fail:   PRINT("- Boot failed -\r\n")
>  1:      wfe
>          b     1b
> 
> -#ifdef EARLY_UART_ADDRESS
> +#ifdef EARLY_PRINTK
> 
> -/* Bring up the UART. Specific to the PL011 UART.
> - * Clobbers r0-r2 */
> +/* Bring up the UART.
> + * x23: Early UART base address
> + * Clobbers x0-x1 */

Does it actually clobber x1?

>  init_uart:
> -        mov   x1, #0x0
> -        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor fraction) */
> -        mov   x1, #0x4               /* 7.3728MHz / 0x4 == 16 * 115200 */
> -        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor integer) */
> -        mov   x1, #0x60              /* 8n1 */
> -        strh  w1, [x23, #0x24]       /* -> UARTLCR_H (Line control) */
> -        ldr   x1, =0x00000301        /* RXE | TXE | UARTEN */
> -        strh  w1, [x23, #0x30]       /* -> UARTCR (Control Register) */
> +        early_uart_init x23, 0
>          adr   x0, 1f
> -        b     puts
> +        b     puts                   /* Jump to puts */
>  1:      .asciz "- UART enabled -\r\n"
>          .align 4

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

* Re: [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support
  2013-05-08  2:33 ` [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support Julien Grall
@ 2013-05-09 10:13   ` Ian Campbell
  2013-05-09 18:33     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:13 UTC (permalink / raw)
  To: Julien Grall; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> +        /* TODO: should be updated */
> +        /* Baud rate already set: read it out from the divisor latch. */
> +#if 0
> +        divisor = (uart->regs[IBRD] << 6) | uart->regs[FBRD];
> +        uart->baud = (uart->clock_hz << 2) / divisor;
> +#endif

Can we drop the #if 0, extending the comment if necessary, or if
possible drop the whole thing.

> +static int __init exynos4210_uart_init(struct dt_device_node *dev,
> +                                       const void *data)
> +{
> +    const struct serial_arm_defaults *defaults = data;
> +    struct exynos4210_uart *uart;
> +    int res;
> +
> +    if ( (defaults->index < 0) || (defaults->index > 1) )
> +        return -EINVAL;
> +
> +    uart = &exynos4210_com[defaults->index];
> +
> +    /* uart->clock_hz  = 0x16e3600; */
> +    uart->baud      = BAUD_AUTO;//115200;

Drop the //115200.

> diff --git a/xen/include/asm-arm/exynos4210-uart.h b/xen/include/asm-arm/exynos4210-uart.h
> new file mode 100644
> index 0000000..1527521
> --- /dev/null
> +++ b/xen/include/asm-arm/exynos4210-uart.h
> @@ -0,0 +1,111 @@
> +/*
> + * xen/include/asm-arm/exynos4210-uart.h
> + *
> + * Common constant definition between ealry printk and the UART driver

"early"

If you fix all the above then
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Ian.

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

* Re: [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk
  2013-05-08  2:33 ` [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
@ 2013-05-09 10:16   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:16 UTC (permalink / raw)
  To: Julien Grall; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> From: Anthony PERARD <anthony.perard@citrix.com>
> 
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - Use assembly macro instead of function
>     - Add Anthony as first author
> ---
>  docs/misc/arm/early-printk.txt          |    1 +
>  xen/arch/arm/Rules.mk                   |    4 ++
>  xen/arch/arm/arm32/Makefile             |    1 -
>  xen/arch/arm/arm32/debug-exynos4210.inc |   77 +++++++++++++++++++++++++++++++
>  4 files changed, 82 insertions(+), 1 deletion(-)
>  create mode 100644 xen/arch/arm/arm32/debug-exynos4210.inc
> 
> diff --git a/docs/misc/arm/early-printk.txt b/docs/misc/arm/early-printk.txt
> index 4065811..d5cae85 100644
> --- a/docs/misc/arm/early-printk.txt
> +++ b/docs/misc/arm/early-printk.txt
> @@ -10,5 +10,6 @@ option should not be enable for Xens that are intended to be portable.
>  CONFIG_EARLY_PRINTK=mach
>  where mach is the name of the machine:
>    - vexpress: printk with pl011 for versatile express
> +  - exynos5250: printk with the second UART
>  
>  By default early printk is disabled.
> diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
> index 4af052c..cff834e 100644
> --- a/xen/arch/arm/Rules.mk
> +++ b/xen/arch/arm/Rules.mk
> @@ -47,6 +47,10 @@ ifeq ($(CONFIG_EARLY_PRINTK), vexpress)
>  EARLY_PRINTK := y
>  EARLY_PRINTK_INC := pl011
>  endif
> +ifeq ($(CONFIG_EARLY_PRINTK), exynos5250)
> +EARLY_PRINTK := y
> +EARLY_PRINTK_INC := exynos4210

> +endif
>  
>  CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK
>  CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_INC=\"debug-$(EARLY_PRINTK_INC).inc\"

These are somewhat redundant, we could almost combine them into one
which is the .inc file to use and then use ifdef on that.

> diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
> index 6af8ca3..aaf277a 100644
> --- a/xen/arch/arm/arm32/Makefile
> +++ b/xen/arch/arm/arm32/Makefile
> @@ -8,4 +8,3 @@ obj-y += traps.o
>  obj-y += domain.o
>  
>  obj-$(EARLY_PRINTK) += debug.o
> -obj-$(CONFIG_EARLY_PL011) += debug-pl011.o

I think this shouldn't have been added earlier and so shouldn't need to
be removed here.

> diff --git a/xen/arch/arm/arm32/debug-exynos4210.inc b/xen/arch/arm/arm32/debug-exynos4210.inc
> new file mode 100644
> index 0000000..17ee5f1
> --- /dev/null
> +++ b/xen/arch/arm/arm32/debug-exynos4210.inc
> @@ -0,0 +1,77 @@
> +/*
> + * xen/arch/arm/arm32/debug-exynos4210.inc
> + *
> + * Exynos 5 specific debug code
> + *
> + * Copyright (c) 2013 Citrix Systems.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <asm/exynos4210-uart.h>
> +
> +#define EARLY_UART_BASE_ADDRESS 0x12c20000
> +
> +/* Exynos 5 UART initialization
> + * rb: register which containts the UART base address

"contains"

> + * rc: scratch register 1
> + * rd: scratch register 2 */
> +.macro early_uart_init rb rc rd
> +        /* init clock */
> +        ldr   \rc, =0x10020000
> +        /* select MPLL (800MHz) source clock */
> +        ldr   \rd, [\rc, #0x250]
> +        and   \rd, \rd, #(~(0xf<<8))
> +        orr   \rd, \rd, #(0x6<<8)
> +        str   \rd, [\rc, #0x250]
> +        /* ratio 800/(7+1) */
> +        ldr   \rd, [\rc, #0x558]
> +        and   \rd, \rd, #(~(0xf<<8))
> +        orr   \rd, \rd, #(0x7<<8)
> +        str   \rd, [\rc, #0x558]
> +
> +        mov   \rc, #4
> +        str   \rc, [\rb, #UFRACVAL]     /* -> UFRACVAL (Baud divisor fraction) */
> +        mov   \rc, #53
> +        str   \rc, [\rb, #UBRDIV]       /* -> UBRDIV (Baud divisor integer) */
> +        mov   \rc, #3                   /* 8n1 */
> +        str   \rc, [\rb, #ULCON]        /* -> (Line control) */
> +        ldr   \rc, =UCON_TX_IRQ         /* TX IRQMODE */
> +        str   \rc, [\rb, #UCON]         /* -> (Control Register) */
> +        mov   \rc, #0x0
> +        str   \rc, [\rb, #UFCON]        /* disable FIFO */
> +        mov   \rc, #0x0
> +        str   \rc, [\rb, #UMCON]        /* no auto flow control */
> +.endm
> +
> +/* Exynos 5 UART wait UART to be ready to transmit
> + * rb: register which containts the UART base address

"contains", again and twice more below.

> + * rc: scratch register */
> +.macro early_uart_ready rb rc
> +1:
> +        ldr   \rc, [\rb, #UTRSTAT]   /* <- UTRSTAT (Flag register) */
> +        tst   \rc, #UTRSTAT_TX_EMPTY /* Check BUSY bit */
> +        beq   1b                     /* Wait for the UART to be ready */
> +.endm
> +
> +/* Exynos 5 UART transmit character
> + * rb: register which containts the UART base address
> + * rt: register which containts the character to transmit */
> +.macro early_uart_transmit rb rt
> +        str   \rt, [\rb, #UTXH]      /* -> UTXH (Data Register) */
> +.endm
> +
> +/*
> + * Local variables:
> + * mode: ASM
> + * indent-tabs-mode: nil
> + * End:
> + */

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

* Re: [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5
  2013-05-08  2:33 ` [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5 Julien Grall
@ 2013-05-09 10:19   ` Ian Campbell
  2013-05-09 13:03     ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:19 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Changes in v2:
>     - Add dom0 1:1 mapping quirk for the arndale board
>     - s/mapping/mappings/ in comment
>     - Remove debug trap (unnecessary with linux 3.9)
> ---
>  xen/arch/arm/platforms/Makefile         |    1 +
>  xen/arch/arm/platforms/exynos5.c        |   86 +++++++++++++++++++++++++++++++
>  xen/include/asm-arm/platforms/exynos5.h |   40 ++++++++++++++
>  3 files changed, 127 insertions(+)
>  create mode 100644 xen/arch/arm/platforms/exynos5.c
>  create mode 100644 xen/include/asm-arm/platforms/exynos5.h
> 
> diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
> index 4313e95..ff2b65b 100644
> --- a/xen/arch/arm/platforms/Makefile
> +++ b/xen/arch/arm/platforms/Makefile
> @@ -1 +1,2 @@
>  obj-y += vexpress.o
> +obj-y += exynos5.o
> diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
> new file mode 100644
> index 0000000..8620390
> --- /dev/null
> +++ b/xen/arch/arm/platforms/exynos5.c
> @@ -0,0 +1,86 @@
> +/*
> + * xen/arch/arm/platforms/exynos5.c
> + *
> + * Exynos5 specific settings
> + *
> + * Julien Grall <julien.grall@linaro.org>
> + * Copyright (c) 2013 Linaro Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <asm/p2m.h>
> +#include <xen/config.h>
> +#include <xen/device_tree.h>
> +#include <xen/domain_page.h>
> +#include <xen/mm.h>
> +#include <asm/platforms/exynos5.h>
> +#include <asm/platform.h>
> +
> +static int exynos5_init_time(void)
> +{
> +    uint32_t reg;
> +
> +    // enable timer on exynos5 arndale board
> +    // should probably be done by u-boot

/* */ please.

> +    reg = platform_read_register(EXYNOS5_MCT_G_TCON);
> +    platform_write_register(EXYNOS5_MCT_G_TCON, reg | EXYNOS5_MCT_G_TCON_START);
> +
> +    return 0;
> +}
> +
> +/* Additionnal mappings for dom0 (Not in the DTS) */

"Additional"

> +static int exynos5_specific_mapping(struct domain *d)
> +{
> +    /* Map the chip ID */
> +    map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
> +                     EXYNOS5_PA_CHIPID);
> +
> +    /* Map the PWM region */
> +    map_mmio_regions(d, EXYNOS5_PA_TIMER,
> +                     EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
> +                     EXYNOS5_PA_TIMER);

If these get added to a future version of the DTS will badness ensue? I
suppose all we can do is add a check for the new compatible node at that
time, which we obviously can't do now...

> diff --git a/xen/include/asm-arm/platforms/exynos5.h b/xen/include/asm-arm/platforms/exynos5.h
> new file mode 100644
> index 0000000..d77623c
> --- /dev/null
> +++ b/xen/include/asm-arm/platforms/exynos5.h
> @@ -0,0 +1,40 @@
> +#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
> +#define __ASM_ASM_PLATFORMS_EXYSNO5_H
> +
> +#define EXYNOS5_MCT_BASE            0x101c0000
> +#define EXYNOS5_MCTREG(x)           (EXYNOS5_MCT_BASE + (x))
> +#define EXYNOS5_MCT_G_TCON		    EXYNOS5_MCTREG(0x240)
> +#define EXYNOS5_MCT_G_TCON_START	(1 << 8)

Inconsistent indent, hard tabs perhaps?

> +
> +#define EXYNOS5_PA_CHIPID           0x10000000
> +#define EXYNOS5_PA_TIMER            0x12dd0000
> +/* Base address of system controller */
> +#define EXYNOS5_PA_PMU              0x10040000
> +
> +#define EXYNOS5_SWRESET             (EXYNOS5_PA_PMU + 0x0400)
> +
> +#define S5P_PA_SYSRAM   0x02020000
> +
> +/* Constants below is only used in assembly because the DTS is not yet parsed */

In a subsequent patch?

> +#ifdef __ASSEMBLY__
> +
> +/* GIC Base Address */
> +#define EXYNOS5_GIC_BASE_ADDRESS    0x10480000
> +
> +/* Timer's frequency */
> +#define EXYNOS5_TIMER_FREQUENCY     (24 * 1000 * 1000) /* 24 MHz */
> +
> +/* Arndale machine ID */
> +#define MACH_TYPE_SMDK5250          3774
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* __ASM_ARM_PLATFORMS_EXYNOS5_H */
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */

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

* Re: [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor for the exynos5
  2013-05-08  2:33 ` [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
@ 2013-05-09 10:24   ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 10:24 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> Use machine ID to know what is the current board. This value is only given
> to the first CPU by the bootloader.
> 
> When the exynos 5 starts, there is only one CPU up. Xen needs to start the
> secondary cpu. The latter boots in secure mode.
> 
> Theses modifications aim to be removed as soon as possible. It should
> be moved either in a platform specific boot-wrapper (which will be start
> before Xen), or in the bootloader (assuming U-Boot/Grub will support SMP).

With this proviso I'm OK with this change for 4.3, I'd like to see this
gone for 4.4 though.

> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5
  2013-05-09 10:19   ` Ian Campbell
@ 2013-05-09 13:03     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-09 13:03 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/09/2013 11:19 AM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> Changes in v2:
>>     - Add dom0 1:1 mapping quirk for the arndale board
>>     - s/mapping/mappings/ in comment
>>     - Remove debug trap (unnecessary with linux 3.9)
>> ---
>>  xen/arch/arm/platforms/Makefile         |    1 +
>>  xen/arch/arm/platforms/exynos5.c        |   86 +++++++++++++++++++++++++++++++
>>  xen/include/asm-arm/platforms/exynos5.h |   40 ++++++++++++++
>>  3 files changed, 127 insertions(+)
>>  create mode 100644 xen/arch/arm/platforms/exynos5.c
>>  create mode 100644 xen/include/asm-arm/platforms/exynos5.h
>>
>> diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
>> index 4313e95..ff2b65b 100644
>> --- a/xen/arch/arm/platforms/Makefile
>> +++ b/xen/arch/arm/platforms/Makefile
>> @@ -1 +1,2 @@
>>  obj-y += vexpress.o
>> +obj-y += exynos5.o
>> diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
>> new file mode 100644
>> index 0000000..8620390
>> --- /dev/null
>> +++ b/xen/arch/arm/platforms/exynos5.c
>> @@ -0,0 +1,86 @@
>> +/*
>> + * xen/arch/arm/platforms/exynos5.c
>> + *
>> + * Exynos5 specific settings
>> + *
>> + * Julien Grall <julien.grall@linaro.org>
>> + * Copyright (c) 2013 Linaro Limited.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <asm/p2m.h>
>> +#include <xen/config.h>
>> +#include <xen/device_tree.h>
>> +#include <xen/domain_page.h>
>> +#include <xen/mm.h>
>> +#include <asm/platforms/exynos5.h>
>> +#include <asm/platform.h>
>> +
>> +static int exynos5_init_time(void)
>> +{
>> +    uint32_t reg;
>> +
>> +    // enable timer on exynos5 arndale board
>> +    // should probably be done by u-boot
> 
> /* */ please.
> 
>> +    reg = platform_read_register(EXYNOS5_MCT_G_TCON);
>> +    platform_write_register(EXYNOS5_MCT_G_TCON, reg | EXYNOS5_MCT_G_TCON_START);
>> +
>> +    return 0;
>> +}
>> +
>> +/* Additionnal mappings for dom0 (Not in the DTS) */
> 
> "Additional"
> 
>> +static int exynos5_specific_mapping(struct domain *d)
>> +{
>> +    /* Map the chip ID */
>> +    map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
>> +                     EXYNOS5_PA_CHIPID);
>> +
>> +    /* Map the PWM region */
>> +    map_mmio_regions(d, EXYNOS5_PA_TIMER,
>> +                     EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
>> +                     EXYNOS5_PA_TIMER);
> 
> If these get added to a future version of the DTS will badness ensue? I
> suppose all we can do is add a check for the new compatible node at that
> time, which we obviously can't do now...

In this case, we can remove this both lines.
map_devices_from_device_tree will do all the work.
But I think it's too specific to be added in the DTS.

>> diff --git a/xen/include/asm-arm/platforms/exynos5.h b/xen/include/asm-arm/platforms/exynos5.h
>> new file mode 100644
>> index 0000000..d77623c
>> --- /dev/null
>> +++ b/xen/include/asm-arm/platforms/exynos5.h
>> @@ -0,0 +1,40 @@
>> +#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
>> +#define __ASM_ASM_PLATFORMS_EXYSNO5_H
>> +
>> +#define EXYNOS5_MCT_BASE            0x101c0000
>> +#define EXYNOS5_MCTREG(x)           (EXYNOS5_MCT_BASE + (x))
>> +#define EXYNOS5_MCT_G_TCON		    EXYNOS5_MCTREG(0x240)
>> +#define EXYNOS5_MCT_G_TCON_START	(1 << 8)
> 
> Inconsistent indent, hard tabs perhaps?

Right. Will be fix on the next patch series.

>> +
>> +#define EXYNOS5_PA_CHIPID           0x10000000
>> +#define EXYNOS5_PA_TIMER            0x12dd0000
>> +/* Base address of system controller */
>> +#define EXYNOS5_PA_PMU              0x10040000
>> +
>> +#define EXYNOS5_SWRESET             (EXYNOS5_PA_PMU + 0x0400)
>> +
>> +#define S5P_PA_SYSRAM   0x02020000
>> +
>> +/* Constants below is only used in assembly because the DTS is not yet parsed */
> 
> In a subsequent patch?

Yes. It's used in patch 32.

>> +#ifdef __ASSEMBLY__
>> +
>> +/* GIC Base Address */
>> +#define EXYNOS5_GIC_BASE_ADDRESS    0x10480000
>> +
>> +/* Timer's frequency */
>> +#define EXYNOS5_TIMER_FREQUENCY     (24 * 1000 * 1000) /* 24 MHz */
>> +
>> +/* Arndale machine ID */
>> +#define MACH_TYPE_SMDK5250          3774
>> +
>> +#endif /* __ASSEMBLY__ */
>> +
>> +#endif /* __ASM_ARM_PLATFORMS_EXYNOS5_H */
>> +/*
>> + * Local variables:
>> + * mode: C
>> + * c-file-style: "BSD"
>> + * c-basic-offset: 4
>> + * indent-tabs-mode: nil
>> + * End:
>> + */
> 
> 


-- 
Julien

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

* Re: [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk
  2013-05-09 10:10   ` Ian Campbell
@ 2013-05-09 13:14     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-09 13:14 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/09/2013 11:10 AM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
>> index 1ad3364..6af8ca3 100644
>> --- a/xen/arch/arm/arm32/Makefile
>> +++ b/xen/arch/arm/arm32/Makefile
>> @@ -5,4 +5,7 @@ obj-y += mode_switch.o
>>  obj-y += proc-ca15.o
>>
>>  obj-y += traps.o
>> -obj-y += domain.o
>> \ No newline at end of file
>> +obj-y += domain.o
>> +
>> +obj-$(EARLY_PRINTK) += debug.o
>> +obj-$(CONFIG_EARLY_PL011) += debug-pl011.o
> 
> Is this correct now that you are using debug-pl011.inc?


It comes from a bad merge. I will fix it on the next patch series.

>>  /* Print a 32-bit number in hex.  Specific to the PL011 UART.
>>   * r0: Number to print.
>> - * clobbers r0-r3 */
>> + * r11: Early UART base address
>> + * clobbers r1-r3 */
> 
> This still clobbers r0, via the lsl below.

Right will be fix on the next patch series.

>>  putn:
>>          adr   r1, hex
>>          mov   r3, #8
>> -1:      ldr   r2, [r11, #0x18]       /* <- UARTFR (Flag register) */
>> -        tst   r2, #0x8               /* Check BUSY bit */
>> -        bne   1b                     /* Wait for the UART to be ready */
>> +1:
>> +        early_uart_ready r11, r2
>>          and   r2, r0, #0xf0000000    /* Mask off the top nybble */
>>          ldrb  r2, [r1, r2, lsr #28]  /* Convert to a char */
>> -        str   r2, [r11]              /* -> UARTDR (Data Register) */
>> +        early_uart_transmit r11, r2
>>          lsl   r0, #4                 /* Roll it through one nybble at a time */
>>          subs  r3, r3, #1
>>          bne   1b
>> @@ -329,51 +329,44 @@ fail:   PRINT("- Boot failed -\r\n")
>>  1:      wfe
>>          b     1b
>>
>> -#ifdef EARLY_UART_ADDRESS
>> +#ifdef EARLY_PRINTK
>>
>> -/* Bring up the UART. Specific to the PL011 UART.
>> - * Clobbers r0-r2 */
>> +/* Bring up the UART.
>> + * x23: Early UART base address
>> + * Clobbers x0-x1 */
> 
> Does it actually clobber x1?

Yes, by puts. init_uart will jump to this function at the end.

>>  init_uart:
>> -        mov   x1, #0x0
>> -        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor fraction) */
>> -        mov   x1, #0x4               /* 7.3728MHz / 0x4 == 16 * 115200 */
>> -        strh  w1, [x23, #0x24]       /* -> UARTIBRD (Baud divisor integer) */
>> -        mov   x1, #0x60              /* 8n1 */
>> -        strh  w1, [x23, #0x24]       /* -> UARTLCR_H (Line control) */
>> -        ldr   x1, =0x00000301        /* RXE | TXE | UARTEN */
>> -        strh  w1, [x23, #0x30]       /* -> UARTCR (Control Register) */
>> +        early_uart_init x23, 0
>>          adr   x0, 1f
>> -        b     puts
>> +        b     puts                   /* Jump to puts */
>>  1:      .asciz "- UART enabled -\r\n"
>>          .align 4
> 
> 
> 


-- 
Julien

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

* Re: [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512
  2013-05-08 13:00   ` Ian Campbell
@ 2013-05-09 14:32     ` Julien Grall
  2013-05-09 14:46       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-09 14:32 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 02:00 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> When debug is enabled in device tree code, some lines
>> are bigger than 80 characters.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> 
> Although if we can also take steps to not let the line length get too
> long that would be valuable, I can see 80-100 being tolerable but if we
> are actually seeing lines with 512 characters that is an issue in its
> own right. I appreciate you've just picked a "big enough" number and we
> hopefully aren't seeing anything like 512 in practice.


It seems, the function printk uses a buffer of 10024.
It's mainly when device tree prints full path on each node.

>> Changes in v2:
>>  - Move buffer to a static variable
>> ---
>>  xen/arch/arm/early_printk.c |    5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
>> index bdf4c0e..0f99a43 100644
>> --- a/xen/arch/arm/early_printk.c
>> +++ b/xen/arch/arm/early_printk.c
>> @@ -29,6 +29,9 @@ void __init early_putch(char c)
>>      *r = c;
>>  }
>>  
>> +/* Early printk buffer */
>> +static char __initdata buf[512];
>> +
>>  static void __init early_puts(const char *s)
>>  {
>>      while (*s != '\0') {
>> @@ -41,8 +44,6 @@ static void __init early_puts(const char *s)
>>  
>>  static void __init early_vprintk(const char *fmt, va_list args)
>>  {
>> -    char buf[80];
>> -
>>      vsnprintf(buf, sizeof(buf), fmt, args);
>>      early_puts(buf);
>>  }
> 
> 

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-08 15:34           ` Ian Campbell
@ 2013-05-09 14:38             ` Julien Grall
  2013-05-09 14:43               ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Julien Grall @ 2013-05-09 14:38 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/08/2013 04:34 PM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 16:15 +0100, Julien Grall wrote:
>> On 05/08/2013 02:41 PM, Ian Campbell wrote:
>>
>>> On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
>>>>> Which only leaves ones which are both? How many are these? I'm inclined
>>>>> towards suggesting that if they are debug prints which are disabled by
>>>>> default and require a recompile to enable then the person doing the
>>>>> debugging can select whether they care about early or late messages by 
>>>>> #define-ing DEBUG or EARLY_DEBUG or both as required.
>>>>
>>>> We can't choose at compile time. Early printk function is in init code
>>>> section. So at the end of boot the function will disappear.
>>>
>>> Oh, right.
>>>
>>> Perhaps something could be conditional on system_state =
>>> SYS_STATE_active, this happens not long before we discard the initial
>>> sections.
>>
>>
>> I think it's too late. If we use early_printk until this stage, we will
>> lose some usefull debug when early printk is disabled (ie most of the time).
>>
>> How about adding the missing system_state = SYS_STATE_boot just after
>> console_init_preirq? Early printk will only be used when system_state ==
>> SYS_STATE_early_boot.
> 
> I think this is a common thing so it'd need wider discussion.


SYS_STATE_boot already exists for x86. We forgot to use it on Xen Arm.
So all ARM boot is done with system_state equals to SYS_STATE_early_boot.

> 
>>>> Device tree function could be called after the end of the boot. For the
>>>> moment it's not the case.
>>>>
>>>> The best solution would be: early_printk is directly handled in console
>>>> as linux does.
>>>
>>> That does sound best.
>>
>>
>> I will send a patch later for this.
> 
> Does that make the above moot?


Yes. I think this will avoid lots of headache to know if we need to use
early_printk or printk in the code. It's really annoying when Xen is
stucked with no log because an assert, which uses printk, is raised when
console is not setup. But this changes will impact x86.

-- 
Julien

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-09 14:38             ` Julien Grall
@ 2013-05-09 14:43               ` Ian Campbell
  2013-05-09 14:55                 ` Julien Grall
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 14:43 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Thu, 2013-05-09 at 15:38 +0100, Julien Grall wrote:
> On 05/08/2013 04:34 PM, Ian Campbell wrote:
> 
> > On Wed, 2013-05-08 at 16:15 +0100, Julien Grall wrote:
> >> On 05/08/2013 02:41 PM, Ian Campbell wrote:
> >>
> >>> On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
> >>>>> Which only leaves ones which are both? How many are these? I'm inclined
> >>>>> towards suggesting that if they are debug prints which are disabled by
> >>>>> default and require a recompile to enable then the person doing the
> >>>>> debugging can select whether they care about early or late messages by 
> >>>>> #define-ing DEBUG or EARLY_DEBUG or both as required.
> >>>>
> >>>> We can't choose at compile time. Early printk function is in init code
> >>>> section. So at the end of boot the function will disappear.
> >>>
> >>> Oh, right.
> >>>
> >>> Perhaps something could be conditional on system_state =
> >>> SYS_STATE_active, this happens not long before we discard the initial
> >>> sections.
> >>
> >>
> >> I think it's too late. If we use early_printk until this stage, we will
> >> lose some usefull debug when early printk is disabled (ie most of the time).
> >>
> >> How about adding the missing system_state = SYS_STATE_boot just after
> >> console_init_preirq? Early printk will only be used when system_state ==
> >> SYS_STATE_early_boot.
> > 
> > I think this is a common thing so it'd need wider discussion.
> 
> 
> SYS_STATE_boot already exists for x86. We forgot to use it on Xen Arm.
> So all ARM boot is done with system_state equals to SYS_STATE_early_boot.

Oh, then great lets use that ;-)

> >>>> Device tree function could be called after the end of the boot. For the
> >>>> moment it's not the case.
> >>>>
> >>>> The best solution would be: early_printk is directly handled in console
> >>>> as linux does.
> >>>
> >>> That does sound best.
> >>
> >>
> >> I will send a patch later for this.
> > 
> > Does that make the above moot?
> 
> 
> Yes. I think this will avoid lots of headache to know if we need to use
> early_printk or printk in the code. It's really annoying when Xen is
> stucked with no log because an assert, which uses printk, is raised when
> console is not setup. But this changes will impact x86.

Yes, this is probably 4.4 material then?

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

* Re: [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512
  2013-05-09 14:32     ` Julien Grall
@ 2013-05-09 14:46       ` Ian Campbell
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Campbell @ 2013-05-09 14:46 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Thu, 2013-05-09 at 15:32 +0100, Julien Grall wrote:
> On 05/08/2013 02:00 PM, Ian Campbell wrote:
> 
> > On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
> >> When debug is enabled in device tree code, some lines
> >> are bigger than 80 characters.
> >>
> >> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> > 
> > Acked-by: Ian Campbell <ian.campbell@citrix.com>
> > 
> > Although if we can also take steps to not let the line length get too
> > long that would be valuable, I can see 80-100 being tolerable but if we
> > are actually seeing lines with 512 characters that is an issue in its
> > own right. I appreciate you've just picked a "big enough" number and we
> > hopefully aren't seeing anything like 512 in practice.
> 
> 
> It seems, the function printk uses a buffer of 10024.

I suppose the extra 0 is a typo, but even 1024 seems excessive!

> It's mainly when device tree prints full path on each node.

OK, lets leave it for now but maybe at some point think about ways of
shortening these lines since even if we print them they are going to be
wrapped and hard to read. Perhaps indenting children instead of printing
the whole path.

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

* Re: [PATCH V2 07/33] xen/arm: Create a hierarchical device tree
  2013-05-09 14:43               ` Ian Campbell
@ 2013-05-09 14:55                 ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-09 14:55 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/09/2013 03:43 PM, Ian Campbell wrote:

> On Thu, 2013-05-09 at 15:38 +0100, Julien Grall wrote:
>> On 05/08/2013 04:34 PM, Ian Campbell wrote:
>>
>>> On Wed, 2013-05-08 at 16:15 +0100, Julien Grall wrote:
>>>> On 05/08/2013 02:41 PM, Ian Campbell wrote:
>>>>
>>>>> On Wed, 2013-05-08 at 14:34 +0100, Julien Grall wrote:
>>>>>>> Which only leaves ones which are both? How many are these? I'm inclined
>>>>>>> towards suggesting that if they are debug prints which are disabled by
>>>>>>> default and require a recompile to enable then the person doing the
>>>>>>> debugging can select whether they care about early or late messages by 
>>>>>>> #define-ing DEBUG or EARLY_DEBUG or both as required.
>>>>>>
>>>>>> We can't choose at compile time. Early printk function is in init code
>>>>>> section. So at the end of boot the function will disappear.
>>>>>
>>>>> Oh, right.
>>>>>
>>>>> Perhaps something could be conditional on system_state =
>>>>> SYS_STATE_active, this happens not long before we discard the initial
>>>>> sections.
>>>>
>>>>
>>>> I think it's too late. If we use early_printk until this stage, we will
>>>> lose some usefull debug when early printk is disabled (ie most of the time).
>>>>
>>>> How about adding the missing system_state = SYS_STATE_boot just after
>>>> console_init_preirq? Early printk will only be used when system_state ==
>>>> SYS_STATE_early_boot.
>>>
>>> I think this is a common thing so it'd need wider discussion.
>>
>>
>> SYS_STATE_boot already exists for x86. We forgot to use it on Xen Arm.
>> So all ARM boot is done with system_state equals to SYS_STATE_early_boot.
> 
> Oh, then great lets use that ;-)
> 
>>>>>> Device tree function could be called after the end of the boot. For the
>>>>>> moment it's not the case.
>>>>>>
>>>>>> The best solution would be: early_printk is directly handled in console
>>>>>> as linux does.
>>>>>
>>>>> That does sound best.
>>>>
>>>>
>>>> I will send a patch later for this.
>>>
>>> Does that make the above moot?
>>
>>
>> Yes. I think this will avoid lots of headache to know if we need to use
>> early_printk or printk in the code. It's really annoying when Xen is
>> stucked with no log because an assert, which uses printk, is raised when
>> console is not setup. But this changes will impact x86.
> 
> Yes, this is probably 4.4 material then?

Yes, I will write a line on this issue with ASSERT on the wiki.

-- 
Julien

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

* Re: [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support
  2013-05-09 10:13   ` Ian Campbell
@ 2013-05-09 18:33     ` Julien Grall
  0 siblings, 0 replies; 88+ messages in thread
From: Julien Grall @ 2013-05-09 18:33 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On 05/09/2013 11:13 AM, Ian Campbell wrote:

> On Wed, 2013-05-08 at 03:33 +0100, Julien Grall wrote:
>> +        /* TODO: should be updated */
>> +        /* Baud rate already set: read it out from the divisor latch. */
>> +#if 0
>> +        divisor = (uart->regs[IBRD] << 6) | uart->regs[FBRD];
>> +        uart->baud = (uart->clock_hz << 2) / divisor;
>> +#endif
> 
> Can we drop the #if 0, extending the comment if necessary, or if
> possible drop the whole thing.

I will move this two lines in the comment.

>> +static int __init exynos4210_uart_init(struct dt_device_node *dev,
>> +                                       const void *data)
>> +{
>> +    const struct serial_arm_defaults *defaults = data;
>> +    struct exynos4210_uart *uart;
>> +    int res;
>> +
>> +    if ( (defaults->index < 0) || (defaults->index > 1) )
>> +        return -EINVAL;
>> +
>> +    uart = &exynos4210_com[defaults->index];
>> +
>> +    /* uart->clock_hz  = 0x16e3600; */
>> +    uart->baud      = BAUD_AUTO;//115200;
> 
> Drop the //115200.


Will be fixed in the next patch series.

>> diff --git a/xen/include/asm-arm/exynos4210-uart.h b/xen/include/asm-arm/exynos4210-uart.h
>> new file mode 100644
>> index 0000000..1527521
>> --- /dev/null
>> +++ b/xen/include/asm-arm/exynos4210-uart.h
>> @@ -0,0 +1,111 @@
>> +/*
>> + * xen/include/asm-arm/exynos4210-uart.h
>> + *
>> + * Common constant definition between ealry printk and the UART driver
> 
> "early"
> 
> If you fix all the above then
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> 
> Ian.
> 

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

end of thread, other threads:[~2013-05-09 18:33 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-08  2:33 [PATCH V2 00/33] Support multiple ARM platforms in Xen Julien Grall
2013-05-08  2:33 ` [PATCH V2 01/33] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
2013-05-08  2:33 ` [PATCH V2 02/33] xen/arm: don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
2013-05-08  2:33 ` [PATCH V2 03/33] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
2013-05-08  2:33 ` [PATCH V2 04/33] xen/arm: Bump early printk internal buffer to 512 Julien Grall
2013-05-08 13:00   ` Ian Campbell
2013-05-09 14:32     ` Julien Grall
2013-05-09 14:46       ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 05/33] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
2013-05-08  2:33 ` [PATCH V2 06/33] xen/arm: Load dtb after dom0 kernel Julien Grall
2013-05-08  2:33 ` [PATCH V2 07/33] xen/arm: Create a hierarchical device tree Julien Grall
2013-05-08 13:11   ` Ian Campbell
2013-05-08 13:34     ` Julien Grall
2013-05-08 13:41       ` Ian Campbell
2013-05-08 15:15         ` Julien Grall
2013-05-08 15:34           ` Ian Campbell
2013-05-09 14:38             ` Julien Grall
2013-05-09 14:43               ` Ian Campbell
2013-05-09 14:55                 ` Julien Grall
2013-05-08 13:52   ` Ian Campbell
2013-05-08 15:22     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 08/33] xen/arm: Add helpers to use the " Julien Grall
2013-05-08 13:18   ` Ian Campbell
2013-05-08 15:31     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 09/33] xen/arm: Add helpers to retrieve an address from " Julien Grall
2013-05-08 13:23   ` Ian Campbell
2013-05-08 15:32     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 10/33] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
2013-05-08 13:30   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 11/33] xen/arm: Introduce gic_route_dt_irq Julien Grall
2013-05-08 13:31   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 12/33] xen/arm: Introduce gic_irq_xlate Julien Grall
2013-05-08 13:32   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 13/33] xen/arm: Introduce setup_dt_irq Julien Grall
2013-05-08 13:35   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 14/33] xen/arm: Introduce request_dt_irq Julien Grall
2013-05-08 13:41   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 15/33] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
2013-05-08 13:46   ` Ian Campbell
2013-05-08 15:49     ` Julien Grall
2013-05-08 15:56       ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 16/33] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
2013-05-08 13:50   ` Ian Campbell
2013-05-08 15:53     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 17/33] xen/arm: Don't hardcode VGIC informations Julien Grall
2013-05-08  2:33 ` [PATCH V2 18/33] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
2013-05-08 13:52   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 19/33] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
2013-05-08  2:33 ` [PATCH V2 20/33] xen/arm: Add generic UART to get the device in the device tree Julien Grall
2013-05-08 14:01   ` Ian Campbell
2013-05-08 15:58     ` Julien Grall
2013-05-08 16:41       ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 21/33] xen/arm: Use device tree API in pl011 UART driver Julien Grall
2013-05-08 15:17   ` Ian Campbell
2013-05-08 16:23     ` Julien Grall
2013-05-08 16:43       ` Ian Campbell
2013-05-08 16:55         ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 22/33] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
2013-05-08 15:28   ` Ian Campbell
2013-05-08 16:59     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 23/33] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
2013-05-08 15:32   ` Ian Campbell
2013-05-08 15:35     ` Ian Campbell
2013-05-08 16:32       ` Julien Grall
2013-05-08 16:38     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 24/33] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
2013-05-08 15:54   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 25/33] xen/arm: Add versatile express platform Julien Grall
2013-05-08  2:33 ` [PATCH V2 26/33] xen/arm: remove request_irq Julien Grall
2013-05-09  9:59   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 27/33] xen/arm: remove setup_irq Julien Grall
2013-05-09 10:00   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 28/33] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
2013-05-09 10:10   ` Ian Campbell
2013-05-09 13:14     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 29/33] xen/arm: Add exynos 4210 UART support Julien Grall
2013-05-09 10:13   ` Ian Campbell
2013-05-09 18:33     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 30/33] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
2013-05-09 10:16   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 31/33] xen/arm: Add platform specific code for the exynos5 Julien Grall
2013-05-09 10:19   ` Ian Campbell
2013-05-09 13:03     ` Julien Grall
2013-05-08  2:33 ` [PATCH V2 32/33] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
2013-05-09 10:24   ` Ian Campbell
2013-05-08  2:33 ` [PATCH V2 33/33] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
2013-05-08  7:03 ` [PATCH V2 00/33] Support multiple ARM platforms in Xen Gihun Jung
2013-05-08 11:01   ` Julien Grall

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