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

Hi,

This is the third version of the patch series. It's rebased on the lastest
master, with 3 others patches.

Major changes in v3:
    - Introduce ioremap_attr, ioreadl, iowritel
    - Typoes, hard tab, java doc...
    - Make generic UART based on DT architecture agnostic
    - Remove hardcoded IRQs in the virtual timer
    - Rework device tree printk

Major changes in v2:
    - 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 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

For the moment the ARM specific 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.
    - Assert in early code, ie before console is setup, let Xen spinned
    without an error message.

If you want to try this patch series you can clone:
    git clone -b arm-v3 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. The wiki page is up-to-date for the arndale
board:
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Arndale

Cheers,

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

Julien Grall (39):
  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: Switch to SYS_STATE_boot right after console setup
  xen/arm: Export early_vprintk
  xen/arm: Extend create_xen_entries prototype to take mapping
    attribute
  xen/mm: Align virtual address on PAGE_SIZE in iounmap
  xen/arm: Introduce ioremap_attr
  xen/arm: Add helpers ioreadl/iowritel
  xen/arm: Remove early_ioremap
  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: Don't hardcode virtual timer IRQs
  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                    |   21 +
 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                |   69 +-
 xen/arch/arm/arm64/mode_switch.S         |    7 +-
 xen/arch/arm/device.c                    |   74 ++
 xen/arch/arm/domain_build.c              |  194 ++++-
 xen/arch/arm/early_printk.c              |   21 +-
 xen/arch/arm/gic.c                       |  160 +++-
 xen/arch/arm/irq.c                       |    8 +-
 xen/arch/arm/mm.c                        |   57 +-
 xen/arch/arm/platform.c                  |  137 +++
 xen/arch/arm/platforms/Makefile          |    1 +
 xen/arch/arm/platforms/exynos5.c         |  110 +++
 xen/arch/arm/platforms/vexpress.c        |   43 +
 xen/arch/arm/setup.c                     |   16 +-
 xen/arch/arm/shutdown.c                  |   16 +-
 xen/arch/arm/time.c                      |   68 +-
 xen/arch/arm/vgic.c                      |   20 +-
 xen/arch/arm/vpl011.c                    |    4 +-
 xen/arch/arm/vtimer.c                    |   13 +-
 xen/arch/arm/xen.lds.S                   |   14 +
 xen/common/device_tree.c                 | 1372 ++++++++++++++++++++++++++++--
 xen/drivers/char/Makefile                |    2 +
 xen/drivers/char/dt-uart.c               |   69 ++
 xen/drivers/char/exynos4210-uart.c       |  359 ++++++++
 xen/drivers/char/pl011.c                 |   84 +-
 xen/drivers/char/serial.c                |   16 +
 xen/drivers/video/arm_hdlcd.c            |    3 +-
 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       |    8 +-
 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/mm.h                 |   14 +-
 xen/include/asm-arm/page.h               |    2 +
 xen/include/asm-arm/platform.h           |   61 ++
 xen/include/asm-arm/platforms/exynos5.h  |   39 +
 xen/include/asm-arm/platforms/vexpress.h |   14 +
 xen/include/asm-arm/time.h               |   15 +
 xen/include/xen/device_tree.h            |  404 ++++++++-
 xen/include/xen/serial.h                 |   11 +-
 xen/include/xen/vmap.h                   |    4 +-
 55 files changed, 3804 insertions(+), 378 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/dt-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

-- 
1.7.10.4

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

* [PATCH V3 01/41] xen/arm: lr must be included in range [0-nr_lr(
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 02/41] xen/arm: Don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
                   ` (40 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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 feb7b29..eeb526e 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 |
-- 
1.7.10.4

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

* [PATCH V3 02/41] xen/arm: Don't allow dom0 to access to vpl011 UART0 memory range
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
  2013-05-10  2:17 ` [PATCH V3 01/41] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 03/41] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
                   ` (39 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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)
-- 
1.7.10.4

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

* [PATCH V3 03/41] xen/arm: Remove duplicated GICD_ICPIDR2 definition
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
  2013-05-10  2:17 ` [PATCH V3 01/41] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
  2013-05-10  2:17 ` [PATCH V3 02/41] xen/arm: Don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 04/41] xen/arm: Bump early printk internal buffer to 512 Julien Grall
                   ` (38 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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)
-- 
1.7.10.4

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

* [PATCH V3 04/41] xen/arm: Bump early printk internal buffer to 512
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (2 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 03/41] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 05/41] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
                   ` (37 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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);
 }
-- 
1.7.10.4

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

* [PATCH V3 05/41] xen/arm: Fix early_panic when EARLY_PRINTK is disabled
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (3 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 04/41] xen/arm: Bump early printk internal buffer to 512 Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 06/41] xen/arm: Load dtb after dom0 kernel Julien Grall
                   ` (36 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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
 
-- 
1.7.10.4

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

* [PATCH V3 06/41] xen/arm: Load dtb after dom0 kernel
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (4 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 05/41] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup Julien Grall
                   ` (35 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 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();
 
-- 
1.7.10.4

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

* [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (5 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 06/41] xen/arm: Load dtb after dom0 kernel Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  8:40   ` Ian Campbell
  2013-05-10  2:17 ` [PATCH V3 08/41] xen/arm: Export early_vprintk Julien Grall
                   ` (34 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

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

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 59646d6..29447ef 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -435,6 +435,8 @@ void __init start_xen(unsigned long boot_phys_offset,
     console_init_preirq();
 #endif
 
+    system_state = SYS_STATE_boot;
+
     processor_id();
 
     init_xen_time();
-- 
1.7.10.4

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

* [PATCH V3 08/41] xen/arm: Export early_vprintk
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (6 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  8:46   ` Ian Campbell
  2013-05-10  2:17 ` [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
                   ` (33 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

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

diff --git a/xen/arch/arm/early_printk.c b/xen/arch/arm/early_printk.c
index 0f99a43..65fa912 100644
--- a/xen/arch/arm/early_printk.c
+++ b/xen/arch/arm/early_printk.c
@@ -42,7 +42,7 @@ static void __init early_puts(const char *s)
     }
 }
 
-static void __init early_vprintk(const char *fmt, va_list args)
+void __init early_vprintk(const char *fmt, va_list args)
 {
     vsnprintf(buf, sizeof(buf), fmt, args);
     early_puts(buf);
diff --git a/xen/include/asm-arm/early_printk.h b/xen/include/asm-arm/early_printk.h
index a0297a7..7083199 100644
--- a/xen/include/asm-arm/early_printk.h
+++ b/xen/include/asm-arm/early_printk.h
@@ -11,14 +11,18 @@
 #define __ARM_EARLY_PRINTK_H__
 
 #include <xen/config.h>
+#include <xen/init.h>
+#include <xen/stdarg.h>
 
 #ifdef EARLY_UART_ADDRESS
 
+void __init early_vprintk(const char *fmt, va_list args);
 void early_printk(const char *fmt, ...);
 void early_panic(const char *fmt, ...) __attribute__((noreturn));
 
 #else
 
+static inline void __init early_vprintk(const char *fmt, va_list args) {}
 static inline void early_printk(const char *fmt, ...) {}
 static inline void  __attribute__((noreturn)) early_panic(const char *fmt, ...) {while(1);}
 
-- 
1.7.10.4

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

* [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (7 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 08/41] xen/arm: Export early_vprintk Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  9:08   ` Ian Campbell
  2013-05-10  2:17 ` [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
                   ` (32 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

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

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 2836cbb..96297d3 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -631,7 +631,8 @@ enum xenmap_operation {
 static int create_xen_entries(enum xenmap_operation op,
                               unsigned long virt,
                               unsigned long mfn,
-                              unsigned long nr_mfns)
+                              unsigned long nr_mfns,
+                              unsigned int flags)
 {
     int rc;
     unsigned long addr = virt, addr_end = addr + nr_mfns * PAGE_SIZE;
@@ -664,6 +665,7 @@ static int create_xen_entries(enum xenmap_operation op,
                 }
                 pte = mfn_to_xen_entry(mfn);
                 pte.pt.table = 1;
+                pte.pt.ai = flags;
                 write_pte(&third[third_table_offset(addr)], pte);
                 break;
             case REMOVE:
@@ -693,12 +695,11 @@ int map_pages_to_xen(unsigned long virt,
                      unsigned long nr_mfns,
                      unsigned int flags)
 {
-    ASSERT(flags == PAGE_HYPERVISOR);
-    return create_xen_entries(INSERT, virt, mfn, nr_mfns);
+    return create_xen_entries(INSERT, virt, mfn, nr_mfns, flags);
 }
 void destroy_xen_mappings(unsigned long v, unsigned long e)
 {
-    create_xen_entries(REMOVE, v, 0, (e - v) >> PAGE_SHIFT);
+    create_xen_entries(REMOVE, v, 0, (e - v) >> PAGE_SHIFT, 0);
 }
 
 enum mg { mg_clear, mg_ro, mg_rw, mg_rx };
-- 
1.7.10.4

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

* [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (8 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  8:23   ` Jan Beulich
  2013-05-10  2:17 ` [PATCH V3 11/41] xen/arm: Introduce ioremap_attr Julien Grall
                   ` (31 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel
  Cc: keir, ian.campbell, patches, Julien Grall, JBeulich, Stefano.Stabellini

ioremap function can unlikely return an unaligned virtual address if
the physical address itself is unaligned on a page size.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
CC: JBeulich@suse.com
CC: keir@xen.org
---
 xen/include/xen/vmap.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/include/xen/vmap.h b/xen/include/xen/vmap.h
index 88e5d99..c713a43 100644
--- a/xen/include/xen/vmap.h
+++ b/xen/include/xen/vmap.h
@@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
 
 static inline void iounmap(void __iomem *va)
 {
-    vunmap((void __force *)va);
+    vaddr_t addr = (vaddr_t)(void __force *)va;
+
+    vunmap((void *)(addr & PAGE_MASK));
 }
 
 void vm_init(void);
-- 
1.7.10.4

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

* [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (9 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  9:13   ` Ian Campbell
  2013-05-10  9:17   ` Ian Campbell
  2013-05-10  2:17 ` [PATCH V3 12/41] xen/arm: Add helpers ioreadl/iowritel Julien Grall
                   ` (30 subsequent siblings)
  41 siblings, 2 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Map physical range in virtual memory with a specific mapping attribute.
Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
and PAGE_HYPERVISOR_WC.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/mm.c          |   14 ++++++++++++++
 xen/arch/arm/setup.c       |    4 ++--
 xen/include/asm-arm/mm.h   |    2 ++
 xen/include/asm-arm/page.h |    2 ++
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 96297d3..10d2869 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -38,6 +38,7 @@
 #include <xen/sched.h>
 #include <xen/vmap.h>
 #include <xsm/xsm.h>
+#include <xen/pfn.h>
 
 struct domain *dom_xen, *dom_io, *dom_cow;
 
@@ -608,6 +609,19 @@ void *__init arch_vmap_virt_end(void)
     return (void *)early_vmap_start;
 }
 
+/*
+ * This function should only be used to remap device address ranges
+ * TODO: add a check to verify this assumption
+ */
+void *ioremap_attr(paddr_t pa, size_t len, unsigned int attributes)
+{
+    unsigned long pfn = PFN_DOWN(pa);
+    unsigned int offs = pa & (PAGE_SIZE - 1);
+    unsigned int nr = PFN_UP(offs + len);
+
+    return (__vmap(&pfn, nr, 1, 1, attributes) + offs);
+}
+
 static int create_xen_table(lpae_t *entry)
 {
     void *p;
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 29447ef..a667db4 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
     setup_pagetables(boot_phys_offset, get_xen_paddr());
     setup_mm(fdt_paddr, fdt_size);
 
+    vm_init();
+
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
     pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
@@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     console_init_postirq();
 
-    vm_init();
-
     do_presmp_initcalls();
 
     for_each_present_cpu ( i )
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 26c271e..4ac8fab 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -155,6 +155,8 @@ extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes);
 extern void clear_fixmap(unsigned map);
 /* map a 2MB aligned physical range in virtual memory. */
 void* early_ioremap(paddr_t start, size_t len, unsigned attributes);
+/* map a physical range in virtual memory */
+void *ioremap_attr(paddr_t start, size_t len, unsigned attributes);
 
 #define mfn_valid(mfn)        ({                                              \
     unsigned long __m_f_n = (mfn);                                            \
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index fd6946e..13fbd78 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -59,6 +59,8 @@
 #define DEV_CACHED    WRITEBACK
 
 #define PAGE_HYPERVISOR         (MATTR_MEM)
+#define PAGE_HYPERVISOR_NOCACHE (DEV_SHARED)
+#define PAGE_HYPERVISOR_WC      (DEV_WC)
 #define MAP_SMALL_PAGES         PAGE_HYPERVISOR
 
 /*
-- 
1.7.10.4

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

* [PATCH V3 12/41] xen/arm: Add helpers ioreadl/iowritel
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (10 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 11/41] xen/arm: Introduce ioremap_attr Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  2:17 ` [PATCH V3 13/41] xen/arm: Remove early_ioremap Julien Grall
                   ` (29 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/include/asm-arm/mm.h |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 4ac8fab..b5ea2d1 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -156,7 +156,17 @@ extern void clear_fixmap(unsigned map);
 /* map a 2MB aligned physical range in virtual memory. */
 void* early_ioremap(paddr_t start, size_t len, unsigned attributes);
 /* map a physical range in virtual memory */
-void *ioremap_attr(paddr_t start, size_t len, unsigned attributes);
+void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned attributes);
+
+static inline uint32_t ioreadl(const volatile void __iomem *addr)
+{
+    return (*(volatile uint32_t *)addr);
+}
+
+static inline void iowritel(const volatile void __iomem *addr, uint32_t val)
+{
+    *(volatile uint32_t *)addr = val;
+}
 
 #define mfn_valid(mfn)        ({                                              \
     unsigned long __m_f_n = (mfn);                                            \
-- 
1.7.10.4

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

* [PATCH V3 13/41] xen/arm: Remove early_ioremap
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (11 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 12/41] xen/arm: Add helpers ioreadl/iowritel Julien Grall
@ 2013-05-10  2:17 ` Julien Grall
  2013-05-10  9:21   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 14/41] xen/arm: Create a hierarchical device tree Julien Grall
                   ` (28 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:17 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

In the commit "xen/arm: Introduce ioremap_attr", vamp initialization has been
moved earlier in the boot process.
All the calls to early_ioremap can be replaced by ioremap_attr.

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/mm.c             |   38 +-------------------------------------
 xen/drivers/video/arm_hdlcd.c |    3 ++-
 xen/include/asm-arm/mm.h      |    2 --
 3 files changed, 3 insertions(+), 40 deletions(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 10d2869..d8d0309 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -568,45 +568,9 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe)
     frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info));
 }
 
-/* Map the physical memory range start -  start + len into virtual
- * memory and return the virtual address of the mapping.
- * start has to be 2MB aligned.
- * len has to be < VMAP_VIRT_END - VMAP_VIRT_START.
- */
-static __initdata unsigned long early_vmap_start = VMAP_VIRT_END;
-void* __init early_ioremap(paddr_t start, size_t len, unsigned attributes)
-{
-    paddr_t end = start + len;
-    unsigned long map_start;
-
-    len = (len + SECOND_SIZE - 1) & ~SECOND_MASK;
-    early_vmap_start -= len;
-
-    ASSERT(!(start & (~SECOND_MASK)));
-    ASSERT(!(early_vmap_start & (~SECOND_MASK)));
-
-    /* The range we need to map is too big */
-    if ( early_vmap_start >= VMAP_VIRT_START )
-        return NULL;
-
-    map_start = early_vmap_start;
-    while ( start < end )
-    {
-        lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT);
-        e.pt.ai = attributes;
-        write_pte(xen_second + second_table_offset(map_start), e);
-
-        start += SECOND_SIZE;
-        map_start += SECOND_SIZE;
-    }
-    flush_xen_data_tlb_range_va(early_vmap_start, len);
-
-    return (void*)early_vmap_start;
-}
-
 void *__init arch_vmap_virt_end(void)
 {
-    return (void *)early_vmap_start;
+    return (void *)VMAP_VIRT_END;
 }
 
 /*
diff --git a/xen/drivers/video/arm_hdlcd.c b/xen/drivers/video/arm_hdlcd.c
index d0ec13d..ecf2eba 100644
--- a/xen/drivers/video/arm_hdlcd.c
+++ b/xen/drivers/video/arm_hdlcd.c
@@ -211,7 +211,8 @@ void __init video_init(void)
 
     printk(KERN_INFO "Initializing HDLCD driver\n");
 
-    lfb = early_ioremap(framebuffer_start, framebuffer_size, DEV_WC);
+    lfb = ioremap_attr(framebuffer_start, framebuffer_size,
+                       PAGE_HYPERVISOR_WC);
     if ( !lfb )
     {
         printk(KERN_ERR "Couldn't map the framebuffer\n");
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index b5ea2d1..6b993bc 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -153,8 +153,6 @@ extern void setup_frametable_mappings(paddr_t ps, paddr_t pe);
 extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes);
 /* Remove a mapping from a fixmap entry */
 extern void clear_fixmap(unsigned map);
-/* map a 2MB aligned physical range in virtual memory. */
-void* early_ioremap(paddr_t start, size_t len, unsigned attributes);
 /* map a physical range in virtual memory */
 void __iomem *ioremap_attr(paddr_t start, size_t len, unsigned attributes);
 
-- 
1.7.10.4

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

* [PATCH V3 14/41] xen/arm: Create a hierarchical device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (12 preceding siblings ...)
  2013-05-10  2:17 ` [PATCH V3 13/41] xen/arm: Remove early_ioremap Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  8:54   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 15/41] xen/arm: Add helpers to use the " Julien Grall
                   ` (27 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
  - Remove dt_switch_to_printk
  - Use system_state to choose between early_printk and printk
  - Remove DT_USE_BY_XEN, instead use DOMID_XEN

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          |    1 +
 xen/common/device_tree.c      |  463 ++++++++++++++++++++++++++++++++++++++++-
 xen/include/xen/device_tree.h |   89 ++++++++
 3 files changed, 548 insertions(+), 5 deletions(-)

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index a667db4..81bc956 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);
 
     vm_init();
+    dt_unflatten_host_device_tree();
 
 #ifdef EARLY_UART_ADDRESS
     /* TODO Need to get device tree or command line for UART address */
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 7997f41..6d55a02 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,14 +21,64 @@
 #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;
+static void dt_printk(const char *fmt, ...)
+{
+    static char buf[512];
+    va_list args;
+
+    va_start(args, fmt);
+
+    if ( system_state == SYS_STATE_early_boot )
+        early_vprintk(fmt, args);
+    else
+    {
+        vsnprintf(buf, sizeof(buf), fmt, args);
+        printk(buf);
+    }
+    va_end(args);
+}
+
+#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)
 {
@@ -263,7 +315,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 +325,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 +540,412 @@ 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();
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 19bda98..015b808 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,49 @@ 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;
+};
+
+/**
+ * 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 +124,46 @@ 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);
+
+/**
+ * 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
-- 
1.7.10.4

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

* [PATCH V3 15/41] xen/arm: Add helpers to use the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (13 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 14/41] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  8:54   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 16/41] xen/arm: Add helpers to retrieve an address from " Julien Grall
                   ` (26 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Allow to use "old" functions only in init code

Changes in v2:
    - Use dt_node_cmp and dt_compat_cmp in early device tree code
---
 xen/common/device_tree.c      |  162 ++++++++++++++++++++++++++++++++++++-----
 xen/include/xen/device_tree.h |  155 +++++++++++++++++++++++++++++++++++----
 2 files changed, 283 insertions(+), 34 deletions(-)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 6d55a02..c731105 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -80,7 +80,8 @@ static void dt_printk(const char *fmt, ...)
 # define dt_dprintk(fmt, args...) do {} while ( 0 )
 #endif
 
-bool_t device_tree_node_matches(const void *fdt, int node, const char *match)
+bool_t __init device_tree_node_matches(const void *fdt, int node,
+                                       const char *match)
 {
     const char *name;
     size_t match_len;
@@ -94,7 +95,8 @@ bool_t device_tree_node_matches(const void *fdt, int node, const char *match)
         && (name[match_len] == '@' || name[match_len] == '\0');
 }
 
-bool_t device_tree_type_matches(const void *fdt, int node, const char *match)
+bool_t __init device_tree_type_matches(const void *fdt, int node,
+                                       const char *match)
 {
     const void *prop;
 
@@ -102,20 +104,24 @@ 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)
+bool_t __init 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;
@@ -125,7 +131,7 @@ bool_t device_tree_node_compatible(const void *fdt, int node, const char *match)
     return 0;
 }
 
-static int device_tree_nr_reg_ranges(const struct fdt_property *prop,
+static __init int device_tree_nr_reg_ranges(const struct fdt_property *prop,
         u32 address_cells, u32 size_cells)
 {
     u32 reg_cells = address_cells + size_cells;
@@ -146,14 +152,14 @@ static void __init get_val(const u32 **cell, u32 cells, u64 *val)
     }
 }
 
-void device_tree_get_reg(const u32 **cell, u32 address_cells, u32 size_cells,
-                         u64 *start, u64 *size)
+void __init device_tree_get_reg(const u32 **cell, u32 address_cells,
+                                u32 size_cells, u64 *start, u64 *size)
 {
     get_val(cell, address_cells, start);
     get_val(cell, size_cells, size);
 }
 
-static void set_val(u32 **cell, u32 cells, u64 val)
+static void __init set_val(u32 **cell, u32 cells, u64 val)
 {
     u32 c = cells;
 
@@ -165,15 +171,15 @@ static void set_val(u32 **cell, u32 cells, u64 val)
     (*cell) += cells;
 }
 
-void device_tree_set_reg(u32 **cell, u32 address_cells, u32 size_cells,
-                         u64 start, u64 size)
+void __init device_tree_set_reg(u32 **cell, u32 address_cells, u32 size_cells,
+                                u64 start, u64 size)
 {
     set_val(cell, address_cells, start);
     set_val(cell, size_cells, size);
 }
 
-u32 device_tree_get_u32(const void *fdt, int node, const char *prop_name,
-                        u32 dflt)
+u32 __init device_tree_get_u32(const void *fdt, int node, const char *prop_name,
+                               u32 dflt)
 {
     const struct fdt_property *prop;
 
@@ -195,8 +201,8 @@ u32 device_tree_get_u32(const void *fdt, int node, const char *prop_name,
  * Returns 0 if all nodes were iterated over successfully.  If @func
  * returns a value different from 0, that value is returned immediately.
  */
-int device_tree_for_each_node(const void *fdt,
-                              device_tree_node_func func, void *data)
+int __init device_tree_for_each_node(const void *fdt,
+                                     device_tree_node_func func, void *data)
 {
     int node;
     int depth;
@@ -262,8 +268,8 @@ static int _find_compatible_node(const void *fdt,
     return 0;
 }
 
-int find_compatible_node(const char *compatible, int *node, int *depth,
-                u32 *address_cells, u32 *size_cells)
+int __init find_compatible_node(const char *compatible, int *node, int *depth,
+                                u32 *address_cells, u32 *size_cells)
 {
     int ret;
     struct find_compat c;
@@ -335,7 +341,7 @@ static int dump_node(const void *fdt, int node, const char *name, int depth,
  * device_tree_dump - print a text representation of a device tree
  * @fdt: flat device tree to print
  */
-void device_tree_dump(const void *fdt)
+void __init device_tree_dump(const void *fdt)
 {
     device_tree_for_each_node(fdt, dump_node, NULL);
 }
@@ -587,6 +593,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;
@@ -598,6 +652,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 015b808..7a6adc7 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -107,22 +107,25 @@ typedef int (*device_tree_node_func)(const void *fdt,
 extern struct dt_early_info early_info;
 extern void *device_tree_flattened;
 
-size_t device_tree_early_init(const void *fdt);
-
-void device_tree_get_reg(const u32 **cell, u32 address_cells, u32 size_cells,
-                         u64 *start, u64 *size);
-void device_tree_set_reg(u32 **cell, u32 address_cells, u32 size_cells,
-                         u64 start, u64 size);
-u32 device_tree_get_u32(const void *fdt, int node, const char *prop_name,
-			u32 dflt);
-bool_t device_tree_node_matches(const void *fdt, int node, const char *match);
-bool_t device_tree_node_compatible(const void *fdt, int node, const char *match);
-int find_compatible_node(const char *compatible, int *node, int *depth,
-                u32 *address_cells, u32 *size_cells);
-int device_tree_for_each_node(const void *fdt,
-                              device_tree_node_func func, void *data);
-const char *device_tree_bootargs(const void *fdt);
-void device_tree_dump(const void *fdt);
+size_t __init device_tree_early_init(const void *fdt);
+
+void __init device_tree_get_reg(const u32 **cell, u32 address_cells,
+                                u32 size_cells,
+                                u64 *start, u64 *size);
+void __init device_tree_set_reg(u32 **cell, u32 address_cells, u32 size_cells,
+                                u64 start, u64 size);
+u32 __init device_tree_get_u32(const void *fdt, int node,
+                               const char *prop_name, u32 dflt);
+bool_t __init device_tree_node_matches(const void *fdt, int node,
+                                       const char *match);
+bool_t __init device_tree_node_compatible(const void *fdt, int node,
+                                          const char *match);
+int __init find_compatible_node(const char *compatible, int *node, int *depth,
+                                u32 *address_cells, u32 *size_cells);
+int __init device_tree_for_each_node(const void *fdt,
+                                     device_tree_node_func func, void *data);
+const char __init *device_tree_bootargs(const void *fdt);
+void __init device_tree_dump(const void *fdt);
 
 /**
  * dt_unflatten_host_device_tree - Unflatten the host device tree
@@ -141,17 +144,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.
@@ -160,10 +218,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
-- 
1.7.10.4

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

* [PATCH V3 16/41] xen/arm: Add helpers to retrieve an address from the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (14 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 15/41] xen/arm: Add helpers to use the " Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 17/41] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
                   ` (25 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Typoes
    - Remove hard tabs
---
 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 c731105..27328c8 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -76,10 +76,38 @@ static void dt_printk(const char *fmt, ...)
 
 #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 __init device_tree_node_matches(const void *fdt, int node,
                                        const char *match)
 {
@@ -724,6 +752,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 7a6adc7..cc3a070 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -272,6 +272,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 address 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 addresses 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 occurred.
+ */
+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
  *
-- 
1.7.10.4

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

* [PATCH V3 17/41] xen/arm: Add helpers to retrieve an interrupt description from the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (15 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 16/41] xen/arm: Add helpers to retrieve an address from " Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 18/41] xen/arm: Introduce gic_route_dt_irq Julien Grall
                   ` (24 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Rename dt_irq_is_level_trigger to dt_irq_is_level_triggered
    - Remove hard tabs
    - Typoes

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 27328c8..f0f60ce 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
@@ -1037,6 +1040,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;
@@ -1068,6 +1146,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 synthesized 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
@@ -1409,6 +1755,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 cc3a070..a7cfa94 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -99,6 +99,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_triggered(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 specifying 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,
@@ -136,11 +197,40 @@ void __init device_tree_dump(const void *fdt);
 void __init dt_unflatten_host_device_tree(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 which 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)
 
@@ -285,6 +375,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 addresses for a device
  * @device: the device whose number of address is to be retrieved
  *
@@ -294,6 +393,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_translate - 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
  *
-- 
1.7.10.4

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

* [PATCH V3 18/41] xen/arm: Introduce gic_route_dt_irq
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (16 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 17/41] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 19/41] xen/arm: Introduce gic_irq_xlate Julien Grall
                   ` (23 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

Changes in v3:
    - Rename dt_irq_is_level_trigger to dt_irq_is_level_triggered

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 eeb526e..06ba78c 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_triggered(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);
 
-- 
1.7.10.4

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

* [PATCH V3 19/41] xen/arm: Introduce gic_irq_xlate
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (17 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 18/41] xen/arm: Introduce gic_route_dt_irq Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 20/41] xen/arm: Introduce setup_dt_irq Julien Grall
                   ` (22 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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 06ba78c..6f57d66 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 81bc956..fc53117 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -431,6 +431,7 @@ void __init start_xen(unsigned long boot_phys_offset,
 
     vm_init();
     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
 
-- 
1.7.10.4

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

* [PATCH V3 20/41] xen/arm: Introduce setup_dt_irq
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (18 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 19/41] xen/arm: Introduce gic_irq_xlate Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 21/41] xen/arm: Introduce request_dt_irq Julien Grall
                   ` (21 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 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 6f57d66..cd3144e 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 eeb733a..de3aa22 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 */
 
@@ -26,6 +27,7 @@ struct irq_cfg {
 #define nr_static_irqs NR_IRQS
 
 struct irq_desc;
+struct irqaction;
 
 struct irq_desc *__irq_to_desc(int irq);
 
@@ -38,6 +40,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:
-- 
1.7.10.4

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

* [PATCH V3 21/41] xen/arm: Introduce request_dt_irq
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (19 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 20/41] xen/arm: Introduce setup_dt_irq Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
                   ` (20 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 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 b2e486f..e83ad22 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 de3aa22..80ff68d 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -40,6 +40,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 */
-- 
1.7.10.4

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

* [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (20 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 21/41] xen/arm: Introduce request_dt_irq Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:23   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
                   ` (19 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Use DOMID_XEN instead of DT_USED_BY_XEN
    - Re-add page-align check on each GIC base addresses

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, 45 insertions(+), 68 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index cd3144e..d016845 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,53 @@ 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, DOMID_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) )
+              "        gic_vcpu_addr=%"PRIpaddr"\n"
+              "        gic_maintenance_irq=%u\n",
+              gic.dbase, gic.cbase, gic.hbase, gic.vbase,
+              gic.maintenance.irq);
+
+    if ( (gic.dbase & ~PAGE_MASK) || (gic.cbase & ~PAGE_MASK) ||
+         (gic.hbase & ~PAGE_MASK) || (gic.vbase & ~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;
     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 +490,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 */
@@ -851,7 +877,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 f0f60ce..094cd60 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -442,46 +442,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)
@@ -533,8 +493,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 a7cfa94..5a2a5c6 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;
 };
 
-- 
1.7.10.4

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

* [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (21 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:23   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 24/41] xen/arm: Don't hardcode VGIC informations Julien Grall
                   ` (18 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Move enum ppi_nr in asm-arm/time.h and rename it to timer_ppi
    (will be used in vtimer patch)
    - Prefix all ppi_nr by TIMER_
    - Remove spurious 2 when physical IRQ is requested

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        |   53 +++++++++++++++++++++++++++++++++++++++-----
 xen/include/asm-arm/time.h |   12 ++++++++++
 3 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index d016845..1197d53 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -488,15 +488,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..ecb7626 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,8 @@ uint64_t __read_mostly boot_count;
  * register-mapped time source in the SoC. */
 unsigned long __read_mostly cpu_khz;  /* CPU clock frequency in kHz. */
 
+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 +93,29 @@ 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, DOMID_XEN);
+
+    /* Retrieve all IRQs for the timer */
+    for ( i = TIMER_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[TIMER_PHYS_NONSECURE_PPI].irq,
+           timer_irq[TIMER_HYP_PPI].irq,
+           timer_irq[TIMER_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 +169,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[TIMER_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 +178,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[TIMER_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 +195,17 @@ 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[TIMER_PHYS_NONSECURE_PPI],
+                     1u << smp_processor_id(), 0xa0);
+    gic_route_dt_irq(&timer_irq[TIMER_HYP_PPI],
+                     1u << smp_processor_id(), 0xa0);
+    gic_route_dt_irq(&timer_irq[TIMER_VIRT_PPI],
+                     1u << smp_processor_id(), 0xa0);
+}
+
 /* Set up the timer interrupt on this CPU */
 void __cpuinit init_timer_interrupt(void)
 {
@@ -184,10 +223,12 @@ 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[TIMER_HYP_PPI], timer_interrupt, 0,
+                   "hyptimer", NULL);
+    request_dt_irq(&timer_irq[TIMER_VIRT_PPI], vtimer_interrupt, 0,
+                   "virtimer", NULL);
+    request_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI], timer_interrupt, 0,
+                   "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..05833ce 100644
--- a/xen/include/asm-arm/time.h
+++ b/xen/include/asm-arm/time.h
@@ -11,6 +11,18 @@ static inline cycles_t get_cycles (void)
 struct tm;
 struct tm wallclock_time(void);
 
+/* List of timer's IRQ */
+enum timer_ppi
+{
+    TIMER_PHYS_SECURE_PPI = 0,
+    TIMER_PHYS_NONSECURE_PPI = 1,
+    TIMER_VIRT_PPI = 2,
+    TIMER_HYP_PPI = 3,
+    MAX_TIMER_PPI = 4,
+};
+
+/* 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);
-- 
1.7.10.4

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

* [PATCH V3 24/41] xen/arm: Don't hardcode VGIC informations
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (22 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs Julien Grall
                   ` (17 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 1197d53..873c855 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];
@@ -775,11 +780,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 gic_irq_eoi(void *info)
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);
-- 
1.7.10.4

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

* [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (23 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 24/41] xen/arm: Don't hardcode VGIC informations Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:25   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 26/41] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
                   ` (16 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, ian.campbell, Julien Grall, Stefano.Stabellini

Define virtual timer IRQs per VCPU

Signed-off-by: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/time.c        |    9 ++++++++-
 xen/arch/arm/vtimer.c      |   13 ++++++++-----
 xen/include/asm-arm/time.h |    3 +++
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index ecb7626..2e928bc 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -49,6 +49,13 @@ unsigned long __read_mostly cpu_khz;  /* CPU clock frequency in kHz. */
 
 static struct dt_irq timer_irq[MAX_TIMER_PPI];
 
+const struct dt_irq *timer_dt_irq(enum timer_ppi ppi)
+{
+    ASSERT(ppi >= TIMER_PHYS_SECURE_PPI && ppi < MAX_TIMER_PPI);
+
+    return &timer_irq[ppi];
+}
+
 /*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
 {
     return muldiv64(ticks, SECONDS(1), 1000 * cpu_khz);
@@ -192,7 +199,7 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
 {
     current->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
     WRITE_SYSREG32(current->arch.virt_timer.ctl | CNTx_CTL_MASK, CNTV_CTL_EL0);
-    vgic_vcpu_inject_irq(current, irq, 1);
+    vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq, 1);
 }
 
 /* Route timer's IRQ on this CPU */
diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
index 6993425..aee762a 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -34,14 +34,14 @@ static void phys_timer_expired(void *data)
     struct vtimer *t = data;
     t->ctl |= CNTx_CTL_PENDING;
     if ( !(t->ctl & CNTx_CTL_MASK) )
-        vgic_vcpu_inject_irq(t->v, 30, 1);
+        vgic_vcpu_inject_irq(t->v, t->irq, 1);
 }
 
 static void virt_timer_expired(void *data)
 {
     struct vtimer *t = data;
     t->ctl |= CNTx_CTL_MASK;
-    vgic_vcpu_inject_irq(t->v, 27, 1);
+    vgic_vcpu_inject_irq(t->v, t->irq, 1);
 }
 
 int vcpu_domain_init(struct domain *d)
@@ -55,17 +55,20 @@ int vcpu_vtimer_init(struct vcpu *v)
 {
     struct vtimer *t = &v->arch.phys_timer;
 
+    /* TODO: Retrieve physical and virtual timer IRQ from the guest
+     * DT. For the moment we use dom0 DT
+     */
+
     init_timer(&t->timer, phys_timer_expired, t, v->processor);
     t->ctl = 0;
     t->cval = NOW();
-    t->irq = 30;
+    t->irq = timer_dt_irq(TIMER_PHYS_NONSECURE_PPI)->irq;
     t->v = v;
 
     t = &v->arch.virt_timer;
     init_timer(&t->timer, virt_timer_expired, t, v->processor);
     t->ctl = 0;
-    t->cval = 0;
-    t->irq = 27;
+    t->irq = timer_dt_irq(TIMER_VIRT_PPI)->irq;
     t->v = v;
 
     return 0;
diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
index 05833ce..f7aa868 100644
--- a/xen/include/asm-arm/time.h
+++ b/xen/include/asm-arm/time.h
@@ -21,6 +21,9 @@ enum timer_ppi
     MAX_TIMER_PPI = 4,
 };
 
+/* Get one of the timer IRQ description */
+const struct dt_irq* timer_dt_irq(enum timer_ppi ppi);
+
 /* Route timer's IRQ on this CPU */
 extern void __cpuinit route_timer_interrupt(void);
 
-- 
1.7.10.4

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

* [PATCH V3 26/41] xen/arm: Introduce a generic way to use a device from the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (24 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 27/41] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
                   ` (15 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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:
    - 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:
+ */
-- 
1.7.10.4

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

* [PATCH V3 27/41] xen/arm: New callback in uart_driver to get device tree interrupt structure
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (25 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 26/41] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree Julien Grall
                   ` (14 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 873c855..95eb6c6 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>
@@ -501,9 +502,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);
-- 
1.7.10.4

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

* [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (26 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 27/41] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:32   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver Julien Grall
                   ` (13 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 UTC (permalink / raw)
  To: xen-devel; +Cc: patches, keir, 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>
CC: keir@xen.org

Changes in v3:
    - Rename arm-uart.c (resp. arm_uart_init) to dt-uart.c (resp. dt_uart_init)
    - Remove serial_arm_defaults and replace by a string options
    - Let the specific UART driver to get its base address in the DT
    - Add SERHND_DTUART. The value is stolen to SERHND_COM1. Bump the
    value would needs some rework...

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/dt-uart.c   |   69 ++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/char/serial.c    |    6 ++++
 xen/include/asm-arm/config.h |    2 +-
 xen/include/xen/serial.h     |    5 ++-
 6 files changed, 83 insertions(+), 3 deletions(-)
 create mode 100644 xen/drivers/char/dt-uart.c

diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index fc53117..2e331d3 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -436,8 +436,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
+    dt_uart_init();
+    console_init_preirq();
 
     system_state = SYS_STATE_boot;
 
diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile
index ab2246d..9c067f9 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) += dt-uart.o
 obj-y += serial.o
diff --git a/xen/drivers/char/dt-uart.c b/xen/drivers/char/dt-uart.c
new file mode 100644
index 0000000..93bb0f5
--- /dev/null
+++ b/xen/drivers/char/dt-uart.c
@@ -0,0 +1,69 @@
+/*
+ * xen/drivers/char/dt-uart.c
+ *
+ * Generic 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/serial.h>
+
+/*
+ * Configure UART port with a string:
+ * alias,options
+ *
+ * @alias: alias used in the device tree for the UART
+ * @options: UART speficic options (see in each UART driver)
+ */
+static char __initdata opt_dtuart[30] = "";
+string_param("dtuart", opt_dtuart);
+
+void __init dt_uart_init(void)
+{
+    struct dt_device_node *dev;
+    int ret;
+    const char *devalias = opt_dtuart;
+    char *options;
+
+    if ( !console_has("dtuart") || !strcmp(opt_dtuart, "") )
+    {
+        early_printk("No console\n");
+        return;
+    }
+
+    options = strchr(opt_dtuart, ',');
+    if ( options != NULL )
+        *(options++) = '\0';
+    else
+        options = "";
+
+    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;
+    }
+
+    ret = device_init(dev, DEVICE_SERIAL, options);
+
+    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..e1c3f47 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_DTUART;
+        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..8af3bc4 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;
@@ -76,10 +77,11 @@ struct uart_driver {
 };
 
 /* 'Serial handles' are composed from the following fields. */
-#define SERHND_IDX      (3<<0) /* COM1, COM2, or DBGP?                    */
+#define SERHND_IDX      (3<<0) /* COM1, COM2, DBGP, DTUART?               */
 # define SERHND_COM1    (0<<0)
 # define SERHND_COM2    (1<<0)
 # define SERHND_DBGP    (2<<0)
+# define SERHND_DTUART  (0<<0) /* Steal SERHND_COM1 value */
 #define SERHND_HI       (1<<2) /* Mux/demux each transferred char by MSB. */
 #define SERHND_LO       (1<<3) /* Ditto, except that the MSB is cleared.  */
 #define SERHND_COOKED   (1<<4) /* Newline/carriage-return translation?    */
@@ -156,6 +158,7 @@ void ns16550_init(int index, struct ns16550_defaults *defaults);
 void ehci_dbgp_init(void);
 
 void pl011_init(int index, unsigned long register_base_address);
+void __init dt_uart_init(void);
 
 struct physdev_dbgp_op;
 int dbgp_op(const struct physdev_dbgp_op *);
-- 
1.7.10.4

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

* [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (27 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:35   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
                   ` (12 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Remove the usage of serial_arm_defaults
    - Get the base address from the DT and map it with ioremap_attr
    - Allow only 1 PL011 assigned to SERHND_DTUART
    - Replace DT_USED_BY_XEN by DOMID_XEN

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 |   84 ++++++++++++++++++++++++++++++++++++----------
 xen/include/xen/serial.h |    1 -
 4 files changed, 67 insertions(+), 26 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 95eb6c6..a46516a 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -505,10 +505,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 2e331d3..e5f4459 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -433,10 +433,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
     dt_uart_init();
     console_init_preirq();
 
diff --git a/xen/drivers/char/pl011.c b/xen/drivers/char/pl011.c
index 8efd08e..9a4e3b9 100644
--- a/xen/drivers/char/pl011.c
+++ b/xen/drivers/char/pl011.c
@@ -22,9 +22,16 @@
 #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>
+#include <xen/mm.h>
+#include <xen/vmap.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;
@@ -32,7 +39,7 @@ static struct pl011 {
     /* struct timer timer; */
     /* unsigned int timeout_ms; */
     /* bool_t probing, intr_works; */
-} pl011_com[2] = {{0}};
+} pl011_com = {0};
 
 /* PL011 register addresses */
 #define DR     (0x00/4)
@@ -163,13 +170,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 +222,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 +241,68 @@ 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)
 {
     struct pl011 *uart;
+    int res;
+    u64 addr, size;
 
-    if ( (index < 0) || (index > 1) )
-        return;
-
-    uart = &pl011_com[index];
+    uart = &pl011_com;
 
     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;
+
+    res = dt_device_get_address(dev, 0, &addr, &size);
+    if ( res )
+    {
+        early_printk("pl011: Unable to retrieve the base"
+                     " address of the UART\n");
+        return res;
+    }
+
+    uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE);
+    if ( !uart->regs )
+    {
+        early_printk("pl011: Unable to map the UART memory\n");
+
+        return -ENOMEM;
+    }
+
+    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);
+    serial_register_uart(SERHND_DTUART, &pl011_driver, uart);
+
+    dt_device_set_used_by(dev, DOMID_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 8af3bc4..9caf776 100644
--- a/xen/include/xen/serial.h
+++ b/xen/include/xen/serial.h
@@ -157,7 +157,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);
 void __init dt_uart_init(void);
 
 struct physdev_dbgp_op;
-- 
1.7.10.4

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

* [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (28 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:37   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
                   ` (11 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Rename dt_irq_is_level_trigger to dt_irq_is_level_trigerred
    - Rename map_device_from_device_tree to map_devices_from_device_tree
    - Replace all %# by 0x% in DPRINT
    - Use DOMID_XEN instead of DT_USED_BY_XEN
    - Get a rid of java doc style

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 |  146 +++++++++++++++++++++++++++++++++++++------
 xen/arch/arm/gic.c          |   12 ++--
 xen/include/asm-arm/gic.h   |    3 +-
 3 files changed, 138 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 6581492..9a2ccad 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,124 @@ 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 not connected to primary controller."
+                   "Connected to %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 = 0x%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 = 0x%"PRIx64" - 0x%"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 0x%"PRIx64
+                   " - 0x%"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) != DOMID_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_devices_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 +512,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_devices_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 a46516a..9207fad 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -696,13 +696,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)
@@ -710,6 +711,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);
@@ -717,9 +719,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_triggered(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 */
-- 
1.7.10.4

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

* [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (29 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:41   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 32/41] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
                   ` (10 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Remove platform_{read,write}
    - Move platform_init_time before reading the timer frequency

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 |   55 ++++++++++++++++
 8 files changed, 215 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 9a2ccad..75c3006 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>
@@ -513,6 +514,9 @@ int construct_dom0(struct domain *d)
         return rc;
 
     map_devices_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 e5f4459..da2a734 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 2e928bc..db849cf 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
@@ -123,11 +124,16 @@ int __init init_xen_time(void)
            timer_irq[TIMER_HYP_PPI].irq,
            timer_irq[TIMER_VIRT_PPI].irq);
 
+    res = platform_init_time();
+    if ( res )
+        return res;
+
     /* Check that this CPU supports the Generic Timer interface */
     if ( !cpu_has_gentimer )
         panic("CPU does not support the Generic Timer v1 interface.\n");
 
     cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
+
     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..e116265
--- /dev/null
+++ b/xen/include/asm-arm/platform.h
@@ -0,0 +1,55 @@
+#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);
+
+#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:
+ */
-- 
1.7.10.4

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

* [PATCH V3 32/41] xen/arm: WORKAROUND 1:1 memory mapping for dom0
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (30 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 33/41] xen/arm: Add versatile express platform Julien Grall
                   ` (9 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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 75c3006..8369099 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 e116265..f460e9c 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);
-- 
1.7.10.4

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

* [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (31 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 32/41] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:44   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 34/41] xen/arm: Remove request_irq Julien Grall
                   ` (8 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>

Changes in v3:
    - Use ioremap_attr instead of fixmap

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

diff --git a/xen/arch/arm/platforms/vexpress.c b/xen/arch/arm/platforms/vexpress.c
index fd4ce74..9b35e9d 100644
--- a/xen/arch/arm/platforms/vexpress.c
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -18,7 +18,9 @@
  */
 
 #include <asm/platforms/vexpress.h>
+#include <asm/platform.h>
 #include <xen/mm.h>
+#include <xen/vmap.h>
 
 #define DCC_SHIFT      26
 #define FUNCTION_SHIFT 20
@@ -91,6 +93,47 @@ out:
 }
 
 /*
+ * TODO: Get base address from the device tree
+ * See arm,vexpress-reset node
+ */
+static void vexpress_reset(void)
+{
+    void __iomem *base;
+    void __iomem *sp810;
+
+    /* Use the SP810 system controller to force a reset */
+    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
+                        PAGE_HYPERVISOR_NOCACHE);
+    if ( !base )
+    {
+        dprintk(XENLOG_ERR, "Unable to map SP810\n");
+        return;
+    }
+
+    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);
+
+    /* switch to slow mode */
+    iowritel(sp810, 0x3);
+    dsb(); isb();
+    /* writing any value to SCSYSSTAT reg will reset the system */
+    iowritel(sp810 + 4, 0x1);
+    dsb(); isb();
+
+    iounmap(base);
+}
+
+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>
 
-- 
1.7.10.4

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

* [PATCH V3 34/41] xen/arm: Remove request_irq
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (32 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 33/41] xen/arm: Add versatile express platform Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 35/41] xen/arm: Remove setup_irq Julien Grall
                   ` (7 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 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 e83ad22..2fe4296 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);
 
-- 
1.7.10.4

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

* [PATCH V3 35/41] xen/arm: Remove setup_irq
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (33 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 34/41] xen/arm: Remove request_irq Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
                   ` (6 subsequent siblings)
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 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 9207fad..6b30cf9 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -557,20 +557,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);
 
-- 
1.7.10.4

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

* [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (34 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 35/41] xen/arm: Remove setup_irq Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:46   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support Julien Grall
                   ` (5 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Fix clobbers list in UART functions
    - Remove obj-$(CONFIG_EARLY_PL011) in arm32/Makefile. Was unused.
    - Set EARLY_PRINTK to y only if EARLY_DEBUG_INC is not null. Will
    avoid redundant line per early printk machine

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              |   18 ++++++++++
 xen/arch/arm/arm32/Makefile        |    4 ++-
 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          |   69 ++++++++++++++++--------------------
 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, 285 insertions(+), 92 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..297385b 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -36,3 +36,21 @@ 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_INC := pl011
+endif
+
+ifneq ($(EARLY_PRINTK_INC),)
+EARLY_PRINTK := y
+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..aaf277a 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -5,4 +5,6 @@ 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
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..d452b59 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
+ * Clobbers r0-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 r0-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..79a8da9 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
 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
+ * Clobbers x0-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 x0-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 65fa912..90ace5d 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 7083199..c5b99cd 100644
--- a/xen/include/asm-arm/early_printk.h
+++ b/xen/include/asm-arm/early_printk.h
@@ -14,7 +14,7 @@
 #include <xen/init.h>
 #include <xen/stdarg.h>
 
-#ifdef EARLY_UART_ADDRESS
+#ifdef EARLY_PRINTK
 
 void __init early_vprintk(const char *fmt, va_list args);
 void early_printk(const char *fmt, ...);
-- 
1.7.10.4

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

* [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (35 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:49   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
                   ` (4 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Directly get the base address from the DT and map it with ioremap_attr
    - Use ioreadl/iowritel
    - Typoes
    - Remove the remaining //

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    |  359 +++++++++++++++++++++++++++++++++
 xen/include/asm-arm/exynos4210-uart.h |  111 ++++++++++
 4 files changed, 472 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 9c067f9..37543f0 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) += dt-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..437a987
--- /dev/null
+++ b/xen/drivers/char/exynos4210-uart.c
@@ -0,0 +1,359 @@
+/*
+ * 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 <xen/mm.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;
+    void *regs;
+    struct irqaction irqaction;
+} exynos4210_com = {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)
+
+#define exynos4210_read(uart, off)          ioreadl((uart)->regs + off)
+#define exynos4210_write(uart, off, val)    iowritel((uart->regs) + off, val)
+
+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.
+         * divisor = (uart->regs[IBRD] << 6) | uart->regs[FBRD];
+         * uart->baud = (uart->clock_hz << 2) / divisor;
+         */
+    }
+
+    /*
+     * 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,
+};
+
+/* TODO: Parse UART config from the command line */
+static int __init exynos4210_uart_init(struct dt_device_node *dev,
+                                       const void *data)
+{
+    struct exynos4210_uart *uart;
+    int res;
+    u64 addr, size;
+
+    uart = &exynos4210_com;
+
+    /* uart->clock_hz  = 0x16e3600; */
+    uart->baud      = BAUD_AUTO;
+    uart->data_bits = 8;
+    uart->parity    = PARITY_NONE;
+    uart->stop_bits = 1;
+
+    res = dt_device_get_address(dev, 0, &addr, &size);
+    if ( res )
+    {
+        early_printk("exynos4210: Unable to retrieve the base"
+                     " address of the UART\n");
+        return res;
+    }
+
+    uart->regs = ioremap_attr(addr, size, PAGE_HYPERVISOR_NOCACHE);
+    if ( !uart->regs )
+    {
+        early_printk("exynos4210: Unable to map the UART memory\n");
+    }
+    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(SERHND_DTUART, &exynos4210_uart_driver, uart);
+
+    dt_device_set_used_by(dev, DOMID_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..330e1c0
--- /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 early 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:
+ */
-- 
1.7.10.4

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

* [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (36 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:49   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5 Julien Grall
                   ` (3 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Typoes
    - Remove $(CONFIG_EARLY_PL011) because of a bad merge in v2
    - Remove redundant line EARLY_PRINTK :=y

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                   |    3 ++
 xen/arch/arm/arm32/debug-exynos4210.inc |   77 +++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+)
 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 297385b..b6a6890 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -46,6 +46,9 @@ ifeq ($(debug),y)
 ifeq ($(CONFIG_EARLY_PRINTK), vexpress)
 EARLY_PRINTK_INC := pl011
 endif
+ifeq ($(CONFIG_EARLY_PRINTK), exynos5250)
+EARLY_PRINTK_INC := exynos4210
+endif
 
 ifneq ($(EARLY_PRINTK_INC),)
 EARLY_PRINTK := y
diff --git a/xen/arch/arm/arm32/debug-exynos4210.inc b/xen/arch/arm/arm32/debug-exynos4210.inc
new file mode 100644
index 0000000..4241640
--- /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 contains 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 contains 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 contains the UART base address
+ * rt: register which contains 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:
+ */
-- 
1.7.10.4

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

* [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (37 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:50   ` Ian Campbell
  2013-05-10  2:18 ` [PATCH V3 40/41] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
                   ` (2 subsequent siblings)
  41 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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 v3:
    - Remove hard tab
    - Typoes
    - Replace platform_{read,write} call to ioremap_attr, ioreadl, iowritel

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        |  110 +++++++++++++++++++++++++++++++
 xen/include/asm-arm/platforms/exynos5.h |   39 +++++++++++
 3 files changed, 150 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..513a7be
--- /dev/null
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <xen/vmap.h>
+#include <asm/platforms/exynos5.h>
+#include <asm/platform.h>
+
+static int exynos5_init_time(void)
+{
+    uint32_t reg;
+    void __iomem *mct;
+
+    BUILD_BUG_ON(EXYNOS5_MCT_G_TCON >= PAGE_SIZE);
+
+    mct = ioremap_attr(EXYNOS5_MCT_BASE, PAGE_SIZE, PAGE_HYPERVISOR_NOCACHE);
+    if ( !mct )
+    {
+        dprintk(XENLOG_ERR, "Unable to map MCT\n");
+        return -ENOMEM;
+    }
+
+    /* Enable timer on Exynos 5250 should probably be done by u-boot */
+    reg = ioreadl(mct + EXYNOS5_MCT_G_TCON);
+    iowritel(mct + EXYNOS5_MCT_G_TCON, reg | EXYNOS5_MCT_G_TCON_START);
+
+    iounmap(mct);
+
+    return 0;
+}
+
+/* Additional 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)
+{
+    void __iomem *pmu;
+
+    BUILD_BUG_ON(EXYNOS5_SWRESET >= PAGE_SIZE);
+
+    pmu = ioremap_attr(EXYNOS5_PA_PMU, PAGE_SIZE, PAGE_HYPERVISOR_NOCACHE);
+    if ( !pmu )
+    {
+        dprintk(XENLOG_ERR, "Unable to map PMU\n");
+        return;
+    }
+
+    iowritel(pmu + EXYNOS5_SWRESET, 1);
+    iounmap(pmu);
+}
+
+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..ee5bdfa
--- /dev/null
+++ b/xen/include/asm-arm/platforms/exynos5.h
@@ -0,0 +1,39 @@
+#ifndef __ASM_ARM_PLATFORMS_EXYNOS5_H
+#define __ASM_ASM_PLATFORMS_EXYSNO5_H
+
+#define EXYNOS5_MCT_BASE            0x101c0000
+#define EXYNOS5_MCT_G_TCON          0x240       /* Relative to MCT_BASE */
+#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             0x0400      /* Relative to PA_PMU */
+
+#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:
+ */
-- 
1.7.10.4

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

* [PATCH V3 40/41] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor for the exynos5
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (38 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5 Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  2:18 ` [PATCH V3 41/41] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
  2013-05-10  9:48 ` [PATCH V3 00/41] Support multiple ARM platform in Xen George Dunlap
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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>
Acked-by: Ian Campbell <ian.campbell@citrix.com>

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 d452b59..ec7f640 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:
-- 
1.7.10.4

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

* [PATCH V3 41/41] xen/arm64: Remove hardcoded value for gic in assembly code
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (39 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 40/41] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
@ 2013-05-10  2:18 ` Julien Grall
  2013-05-10  9:48 ` [PATCH V3 00/41] Support multiple ARM platform in Xen George Dunlap
  41 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10  2:18 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__ */
 /*
-- 
1.7.10.4

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

* Re: [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10  2:17 ` [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
@ 2013-05-10  8:23   ` Jan Beulich
  2013-05-10 12:40     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Jan Beulich @ 2013-05-10  8:23 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: patches, keir, ian.campbell, Stefano.Stabellini

>>> On 10.05.13 at 04:17, Julien Grall <julien.grall@linaro.org> wrote:
> ioremap function can unlikely return an unaligned virtual address if
> the physical address itself is unaligned on a page size.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

If you used "unsigned long" instead of "vaddr_t" (I don't think this
would build on x86 without doing so, as vaddr-t appear to be ARM
specific):

Acked-by: Jan Beulich <jbeulich@suse.com>

> --- a/xen/include/xen/vmap.h
> +++ b/xen/include/xen/vmap.h
> @@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
>  
>  static inline void iounmap(void __iomem *va)
>  {
> -    vunmap((void __force *)va);
> +    vaddr_t addr = (vaddr_t)(void __force *)va;
> +
> +    vunmap((void *)(addr & PAGE_MASK));
>  }
>  
>  void vm_init(void);

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

* Re: [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup
  2013-05-10  2:17 ` [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup Julien Grall
@ 2013-05-10  8:40   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  8:40 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:17 +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] 79+ messages in thread

* Re: [PATCH V3 08/41] xen/arm: Export early_vprintk
  2013-05-10  2:17 ` [PATCH V3 08/41] xen/arm: Export early_vprintk Julien Grall
@ 2013-05-10  8:46   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  8:46 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:17 +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] 79+ messages in thread

* Re: [PATCH V3 14/41] xen/arm: Create a hierarchical device tree
  2013-05-10  2:18 ` [PATCH V3 14/41] xen/arm: Create a hierarchical device tree Julien Grall
@ 2013-05-10  8:54   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  8:54 UTC (permalink / raw)
  To: Julien Grall, Keir Fraser; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> +static void dt_printk(const char *fmt, ...)
> +{
> +    static char buf[512];
> +    va_list args;
> +
> +    va_start(args, fmt);
> +
> +    if ( system_state == SYS_STATE_early_boot )
> +        early_vprintk(fmt, args);
> +    else
> +    {
> +        vsnprintf(buf, sizeof(buf), fmt, args);
> +        printk(buf);
> +    }
> +    va_end(args);
> +}

It's unfortunate that there is no vprintk, since printk is just going to
do a nop reformatting into yet another buffer.

I wonder what Keir thinks about refactoring printk to allow this? It
looks like it would be trivial.

Of course having done that then we might almost as well go back to the
longer term plan of adding an #ifdef EARLY_PRINTK with this check to
printk itself.

If we don't want to do any of this for 4.3 than I think a macro might
actually be better here:
#define DT_PRINTK(fmt,...) \
	if ( system_state == SYS_STATE_early_boot ) \
		early_vprintk(fmt, __VA_ARGS__); \
	else \
		printk(fmt, __VAR_ARGS__);

Normally I'd be against using a macro, but avoiding the double buffer
seems worth it.

Ian.

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

* Re: [PATCH V3 15/41] xen/arm: Add helpers to use the device tree
  2013-05-10  2:18 ` [PATCH V3 15/41] xen/arm: Add helpers to use the " Julien Grall
@ 2013-05-10  8:54   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  8:54 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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] 79+ messages in thread

* Re: [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute
  2013-05-10  2:17 ` [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
@ 2013-05-10  9:08   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:08 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> ---
>  xen/arch/arm/mm.c |    9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
> index 2836cbb..96297d3 100644
> --- a/xen/arch/arm/mm.c
> +++ b/xen/arch/arm/mm.c
> @@ -631,7 +631,8 @@ enum xenmap_operation {
>  static int create_xen_entries(enum xenmap_operation op,
>                                unsigned long virt,
>                                unsigned long mfn,
> -                              unsigned long nr_mfns)
> +                              unsigned long nr_mfns,
> +                              unsigned int flags)

Please can we call this "attr" or "ai" to reflect the field which it
goes in. Otherwise:

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

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

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10  2:17 ` [PATCH V3 11/41] xen/arm: Introduce ioremap_attr Julien Grall
@ 2013-05-10  9:13   ` Ian Campbell
  2013-05-10 12:00     ` Julien Grall
  2013-05-10  9:17   ` Ian Campbell
  1 sibling, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:13 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
> Map physical range in virtual memory with a specific mapping attribute.
> Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
> and PAGE_HYPERVISOR_WC.

I think it would be useful, e.g. if when we want to reuse Linux SYS MMU
code, to follow the Linux convention here which is ioremap_(no)cache,
ioremap_wc etc.
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 29447ef..a667db4 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>      setup_pagetables(boot_phys_offset, get_xen_paddr());
>      setup_mm(fdt_paddr, fdt_size);
>  
> +    vm_init();
> +
>  #ifdef EARLY_UART_ADDRESS
>      /* TODO Need to get device tree or command line for UART address */
>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
> @@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>  
>      console_init_postirq();
>  
> -    vm_init();
> -
>      do_presmp_initcalls();
>  
>      for_each_present_cpu ( i )

This movement seems to be unrelated to the purpose of this patch?

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

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10  2:17 ` [PATCH V3 11/41] xen/arm: Introduce ioremap_attr Julien Grall
  2013-05-10  9:13   ` Ian Campbell
@ 2013-05-10  9:17   ` Ian Campbell
  2013-05-10 17:06     ` Stefano Stabellini
  1 sibling, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:17 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

> @@ -59,6 +59,8 @@
>  #define DEV_CACHED    WRITEBACK
>  
>  #define PAGE_HYPERVISOR         (MATTR_MEM)

I should have noticed this when Stefano's original vmap patch went in
but this is wrong.

MATTR_* are Second stage paging attributes (i.e. p2m ones) and are not
suitable for the Xen first stage page tables.

MATTR_MEM == 0xf, which I think will be truncated to 0x7 when written to
the ai field in the PT (which is only 3 bits) and so this is equivalent
to using WRITEALLOC. I suspect that isn't at all desirable...

Stefano, can you fix this please?

Ian.

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

* Re: [PATCH V3 13/41] xen/arm: Remove early_ioremap
  2013-05-10  2:17 ` [PATCH V3 13/41] xen/arm: Remove early_ioremap Julien Grall
@ 2013-05-10  9:21   ` Ian Campbell
  2013-05-10 12:35     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:21 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
> In the commit "xen/arm: Introduce ioremap_attr", vamp initialization has been
> moved earlier in the boot process.

Any reason not to make that move as part of this change?

This pushes vm_init before a whole bunch of other setup -- has this been
checked for safety?

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

* Re: [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information
  2013-05-10  2:18 ` [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
@ 2013-05-10  9:23   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:23 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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>

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

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

* Re: [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree
  2013-05-10  2:18 ` [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
@ 2013-05-10  9:23   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:23 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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] 79+ messages in thread

* Re: [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs
  2013-05-10  2:18 ` [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs Julien Grall
@ 2013-05-10  9:25   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:25 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> Define virtual timer IRQs per VCPU
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

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

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

* Re: [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree
  2013-05-10  2:18 ` [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree Julien Grall
@ 2013-05-10  9:32   ` Ian Campbell
  2013-05-10 12:47     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:32 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, Keir (Xen.org), patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> 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>


> CC: keir@xen.org
> 
> Changes in v3:
>     - Rename arm-uart.c (resp. arm_uart_init) to dt-uart.c (resp. dt_uart_init)
>     - Remove serial_arm_defaults and replace by a string options
>     - Let the specific UART driver to get its base address in the DT
>     - Add SERHND_DTUART. The value is stolen to SERHND_COM1. Bump the
>     value would needs some rework...

This is because of the need to encode the value in 2 bits? Due to
SERHND_IDX etc, is the rework more than simply changing the mask and
bumping the flags up and increasing the size of the com array?

I'm OK with this for 4.3 if Keir is:

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

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

* Re: [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver
  2013-05-10  2:18 ` [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver Julien Grall
@ 2013-05-10  9:35   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:35 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> 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>

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

+static int __init pl011_uart_init(struct dt_device_node *dev,
+                                  const void *data)

... might be worth warning if (char *)data != ""?

Ian.

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

* Re: [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0
  2013-05-10  2:18 ` [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
@ 2013-05-10  9:37   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:37 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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 v3:
>     - Rename dt_irq_is_level_trigger to dt_irq_is_level_trigerred

Sorry, this is my fault, it should be "triggered"

Oh, but it's right in the code, yay!

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

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

* Re: [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-10  2:18 ` [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
@ 2013-05-10  9:41   ` Ian Campbell
  2013-05-10 14:47     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:41 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> 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>

Acked-by: Ian Campbell <ian.campbell@citrix.com>
[...]
> +/* 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)
> +{
[...]
> +    /* 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();

Looks like the TODO is obsolete?

Ian.

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

* Re: [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10  2:18 ` [PATCH V3 33/41] xen/arm: Add versatile express platform Julien Grall
@ 2013-05-10  9:44   ` Ian Campbell
  2013-05-10 14:00     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:44 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

> @@ -91,6 +93,47 @@ out:
>  }
>  
>  /*
> + * TODO: Get base address from the device tree
> + * See arm,vexpress-reset node
> + */
> +static void vexpress_reset(void)
> +{
> +    void __iomem *base;
> +    void __iomem *sp810;
> +
> +    /* Use the SP810 system controller to force a reset */
> +    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
> +                        PAGE_HYPERVISOR_NOCACHE);
> +    if ( !base )
> +    {
> +        dprintk(XENLOG_ERR, "Unable to map SP810\n");
> +        return;
> +    }
> +
> +    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);

Didn't I see you making vunmap, which iounmap is based on, take care of
the page offsets itself in an earlier patch? Or is that not the reason
you are going through the base + offset dance?

> +
> +    /* switch to slow mode */
> +    iowritel(sp810, 0x3);
> +    dsb(); isb();
> +    /* writing any value to SCSYSSTAT reg will reset the system */
> +    iowritel(sp810 + 4, 0x1);
> +    dsb(); isb();

Hopefully we don't get here ;-)

> +    iounmap(base);
> +}
> +

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

* Re: [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk
  2013-05-10  2:18 ` [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
@ 2013-05-10  9:46   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:46 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
> 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>

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

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

* Re: [PATCH V3 00/41] Support multiple ARM platform in Xen
  2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
                   ` (40 preceding siblings ...)
  2013-05-10  2:18 ` [PATCH V3 41/41] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
@ 2013-05-10  9:48 ` George Dunlap
  2013-05-10 12:50   ` Julien Grall
  41 siblings, 1 reply; 79+ messages in thread
From: George Dunlap @ 2013-05-10  9:48 UTC (permalink / raw)
  To: Julien Grall; +Cc: patches, Ian Campbell, Stefano Stabellini, xen-devel

On Fri, May 10, 2013 at 3:17 AM, Julien Grall <julien.grall@linaro.org> wrote:
> Hi,
>
> This is the third version of the patch series. It's rebased on the lastest
> master, with 3 others patches.

If this version isn't ready for acceptance yet, is there any way we
could at least accept some of these patches?  A 40+ patch series is
awfully long to be reposted every few days...

 -George

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

* Re: [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support
  2013-05-10  2:18 ` [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support Julien Grall
@ 2013-05-10  9:49   ` Ian Campbell
  2013-05-10 13:00     ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:49 UTC (permalink / raw)
  To: Julien Grall; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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>
> [...]

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

I'm curious to know where these dprintk's go ;-), but:

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

Ian.

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

* Re: [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk
  2013-05-10  2:18 ` [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
@ 2013-05-10  9:49   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:49 UTC (permalink / raw)
  To: Julien Grall; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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>

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

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

* Re: [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5
  2013-05-10  2:18 ` [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5 Julien Grall
@ 2013-05-10  9:50   ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10  9:50 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 03:18 +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] 79+ messages in thread

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10  9:13   ` Ian Campbell
@ 2013-05-10 12:00     ` Julien Grall
  2013-05-10 12:07       ` Ian Campbell
  0 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 10:13 AM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
>> Map physical range in virtual memory with a specific mapping attribute.
>> Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
>> and PAGE_HYPERVISOR_WC.
> 
> I think it would be useful, e.g. if when we want to reuse Linux SYS MMU
> code, to follow the Linux convention here which is ioremap_(no)cache,
> ioremap_wc etc.


Is macro for those functions is sufficient?

>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index 29447ef..a667db4 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>>      setup_pagetables(boot_phys_offset, get_xen_paddr());
>>      setup_mm(fdt_paddr, fdt_size);
>>  
>> +    vm_init();
>> +
>>  #ifdef EARLY_UART_ADDRESS
>>      /* TODO Need to get device tree or command line for UART address */
>>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
>> @@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>>  
>>      console_init_postirq();
>>  
>> -    vm_init();
>> -
>>      do_presmp_initcalls();
>>  
>>      for_each_present_cpu ( i )
> 
> This movement seems to be unrelated to the purpose of this patch?

vm_init initialize vmap code, which is used by ioremap_attr. The
function was called to late.

-- 
Julien

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

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10 12:00     ` Julien Grall
@ 2013-05-10 12:07       ` Ian Campbell
  2013-05-10 12:38         ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10 12:07 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 13:00 +0100, Julien Grall wrote:
> On 05/10/2013 10:13 AM, Ian Campbell wrote:
> 
> > On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
> >> Map physical range in virtual memory with a specific mapping attribute.
> >> Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
> >> and PAGE_HYPERVISOR_WC.
> > 
> > I think it would be useful, e.g. if when we want to reuse Linux SYS MMU
> > code, to follow the Linux convention here which is ioremap_(no)cache,
> > ioremap_wc etc.

> Is macro for those functions is sufficient?

If need be that's fine, is there anything which breaks if you use a
static inline?

> >> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> >> index 29447ef..a667db4 100644
> >> --- a/xen/arch/arm/setup.c
> >> +++ b/xen/arch/arm/setup.c
> >> @@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
> >>      setup_pagetables(boot_phys_offset, get_xen_paddr());
> >>      setup_mm(fdt_paddr, fdt_size);
> >>  
> >> +    vm_init();
> >> +
> >>  #ifdef EARLY_UART_ADDRESS
> >>      /* TODO Need to get device tree or command line for UART address */
> >>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
> >> @@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
> >>  
> >>      console_init_postirq();
> >>  
> >> -    vm_init();
> >> -
> >>      do_presmp_initcalls();
> >>  
> >>      for_each_present_cpu ( i )
> > 
> > This movement seems to be unrelated to the purpose of this patch?
> 
> vm_init initialize vmap code, which is used by ioremap_attr. The
> function was called to late.

But this patch doesn't add any callers, I presume that a caller will
subsequently be introduce which then requires it to be earlier. I think
it would be sufficient to simply mention this upcoming caller in the
commit message and refer to the need to init sooner.

Ian.

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

* Re: [PATCH V3 13/41] xen/arm: Remove early_ioremap
  2013-05-10  9:21   ` Ian Campbell
@ 2013-05-10 12:35     ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:35 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 10:21 AM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
>> In the commit "xen/arm: Introduce ioremap_attr", vamp initialization has been
>> moved earlier in the boot process.
> 
> Any reason not to make that move as part of this change?

No. I will merge with the previous patch.

> This pushes vm_init before a whole bunch of other setup -- has this been
> checked for safety?

I didn't find any reason to not move vm_init. It only relies on memory,
which is initialized by setup_mm.

-- 
Julien

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

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10 12:07       ` Ian Campbell
@ 2013-05-10 12:38         ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:38 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 01:07 PM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 13:00 +0100, Julien Grall wrote:
>> On 05/10/2013 10:13 AM, Ian Campbell wrote:
>>
>>> On Fri, 2013-05-10 at 03:17 +0100, Julien Grall wrote:
>>>> Map physical range in virtual memory with a specific mapping attribute.
>>>> Also add new mapping attributes for ARM: PAGE_HYPERVISOR_NOCACHE
>>>> and PAGE_HYPERVISOR_WC.
>>>
>>> I think it would be useful, e.g. if when we want to reuse Linux SYS MMU
>>> code, to follow the Linux convention here which is ioremap_(no)cache,
>>> ioremap_wc etc.
> 
>> Is macro for those functions is sufficient?
> 
> If need be that's fine, is there anything which breaks if you use a
> static inline?

I will use it on the next version of this patch.

>>>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>>>> index 29447ef..a667db4 100644
>>>> --- a/xen/arch/arm/setup.c
>>>> +++ b/xen/arch/arm/setup.c
>>>> @@ -429,6 +429,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>>>>      setup_pagetables(boot_phys_offset, get_xen_paddr());
>>>>      setup_mm(fdt_paddr, fdt_size);
>>>>  
>>>> +    vm_init();
>>>> +
>>>>  #ifdef EARLY_UART_ADDRESS
>>>>      /* TODO Need to get device tree or command line for UART address */
>>>>      pl011_init(0, FIXMAP_ADDR(FIXMAP_CONSOLE));
>>>> @@ -483,8 +485,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>>>>  
>>>>      console_init_postirq();
>>>>  
>>>> -    vm_init();
>>>> -
>>>>      do_presmp_initcalls();
>>>>  
>>>>      for_each_present_cpu ( i )
>>>
>>> This movement seems to be unrelated to the purpose of this patch?
>>
>> vm_init initialize vmap code, which is used by ioremap_attr. The
>> function was called to late.
> 
> But this patch doesn't add any callers, I presume that a caller will
> subsequently be introduce which then requires it to be earlier. I think
> it would be sufficient to simply mention this upcoming caller in the
> commit message and refer to the need to init sooner.


I will mention it on the commit message.

-- 
Julien

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

* Re: [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap
  2013-05-10  8:23   ` Jan Beulich
@ 2013-05-10 12:40     ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:40 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Stefano.Stabellini, keir, ian.campbell, patches, xen-devel

On 05/10/2013 09:23 AM, Jan Beulich wrote:

>>>> On 10.05.13 at 04:17, Julien Grall <julien.grall@linaro.org> wrote:
>> ioremap function can unlikely return an unaligned virtual address if
>> the physical address itself is unaligned on a page size.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> If you used "unsigned long" instead of "vaddr_t" (I don't think this
> would build on x86 without doing so, as vaddr-t appear to be ARM
> specific):

Right. I will fix it.

> Acked-by: Jan Beulich <jbeulich@suse.com>
> 
>> --- a/xen/include/xen/vmap.h
>> +++ b/xen/include/xen/vmap.h
>> @@ -15,7 +15,9 @@ void __iomem *ioremap(paddr_t, size_t);
>>  
>>  static inline void iounmap(void __iomem *va)
>>  {
>> -    vunmap((void __force *)va);
>> +    vaddr_t addr = (vaddr_t)(void __force *)va;
>> +
>> +    vunmap((void *)(addr & PAGE_MASK));
>>  }
>>  
>>  void vm_init(void);
> 
> 


-- 
Julien

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

* Re: [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree
  2013-05-10  9:32   ` Ian Campbell
@ 2013-05-10 12:47     ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:47 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, Keir (Xen.org), patches, xen-devel

On 05/10/2013 10:32 AM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
>> 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>
> 
> 
>> CC: keir@xen.org
>>
>> Changes in v3:
>>     - Rename arm-uart.c (resp. arm_uart_init) to dt-uart.c (resp. dt_uart_init)
>>     - Remove serial_arm_defaults and replace by a string options
>>     - Let the specific UART driver to get its base address in the DT
>>     - Add SERHND_DTUART. The value is stolen to SERHND_COM1. Bump the
>>     value would needs some rework...
> 
> This is because of the need to encode the value in 2 bits? Due to
> SERHND_IDX etc, is the rework more than simply changing the mask and
> bumping the flags up and increasing the size of the com array?

The console code is able to handle one serial at time so, I don't
understand why we need to "waste" another memory space for a new kind of
serial.

> I'm OK with this for 4.3 if Keir is:
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> 
> 


-- 
Julien

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

* Re: [PATCH V3 00/41] Support multiple ARM platform in Xen
  2013-05-10  9:48 ` [PATCH V3 00/41] Support multiple ARM platform in Xen George Dunlap
@ 2013-05-10 12:50   ` Julien Grall
  2013-05-10 13:34     ` Ian Campbell
  0 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10 12:50 UTC (permalink / raw)
  To: George Dunlap; +Cc: patches, Ian Campbell, Stefano Stabellini, xen-devel

On 05/10/2013 10:48 AM, George Dunlap wrote:

> On Fri, May 10, 2013 at 3:17 AM, Julien Grall <julien.grall@linaro.org> wrote:
>> Hi,
>>
>> This is the third version of the patch series. It's rebased on the lastest
>> master, with 3 others patches.
> 
> If this version isn't ready for acceptance yet, is there any way we
> could at least accept some of these patches?  A 40+ patch series is
> awfully long to be reposted every few days...


I think patches 1-8 can be applied. For the next patch series, I will
only resend the modified patches.

-- 
Julien

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

* Re: [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support
  2013-05-10  9:49   ` Ian Campbell
@ 2013-05-10 13:00     ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 13:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Anthony Perard, Stefano Stabellini, patches, xen-devel

On 05/10/2013 10:49 AM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 03:18 +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>
>> [...]
> 
>> +        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");
> 
> I'm curious to know where these dprintk's go ;-), but:

Directly on the UART :/. But I'm not sure if UART errors are fatal or not.

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


-- 
Julien

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

* Re: [PATCH V3 00/41] Support multiple ARM platform in Xen
  2013-05-10 12:50   ` Julien Grall
@ 2013-05-10 13:34     ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10 13:34 UTC (permalink / raw)
  To: Julien Grall; +Cc: George Dunlap, patches, Stefano Stabellini, xen-devel

On Fri, 2013-05-10 at 13:50 +0100, Julien Grall wrote:
> On 05/10/2013 10:48 AM, George Dunlap wrote:
> 
> > On Fri, May 10, 2013 at 3:17 AM, Julien Grall <julien.grall@linaro.org> wrote:
> >> Hi,
> >>
> >> This is the third version of the patch series. It's rebased on the lastest
> >> master, with 3 others patches.
> > 
> > If this version isn't ready for acceptance yet, is there any way we
> > could at least accept some of these patches?  A 40+ patch series is
> > awfully long to be reposted every few days...
> 
> 
> I think patches 1-8 can be applied. For the next patch series, I will
> only resend the modified patches.

Applied 1-7. #8 was "xen/arm: Export early_vprintk" which I think
changes I suggested to the dt_printk patch have made unnecessary.

Ian.

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

* Re: [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10  9:44   ` Ian Campbell
@ 2013-05-10 14:00     ` Julien Grall
  2013-05-10 14:06       ` Ian Campbell
  0 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10 14:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 10:44 AM, Ian Campbell wrote:

>> @@ -91,6 +93,47 @@ out:
>>  }
>>  
>>  /*
>> + * TODO: Get base address from the device tree
>> + * See arm,vexpress-reset node
>> + */
>> +static void vexpress_reset(void)
>> +{
>> +    void __iomem *base;
>> +    void __iomem *sp810;
>> +
>> +    /* Use the SP810 system controller to force a reset */
>> +    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
>> +                        PAGE_HYPERVISOR_NOCACHE);
>> +    if ( !base )
>> +    {
>> +        dprintk(XENLOG_ERR, "Unable to map SP810\n");
>> +        return;
>> +    }
>> +
>> +    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);
> 
> Didn't I see you making vunmap, which iounmap is based on, take care of
> the page offsets itself in an earlier patch? Or is that not the reason
> you are going through the base + offset dance?


I wasn't not sure if you will accept ioremap(..., 8); I will fix the patch.

> 
>> +
>> +    /* switch to slow mode */
>> +    iowritel(sp810, 0x3);
>> +    dsb(); isb();
>> +    /* writing any value to SCSYSSTAT reg will reset the system */
>> +    iowritel(sp810 + 4, 0x1);
>> +    dsb(); isb();
> 
> Hopefully we don't get here ;-)
> 
>> +    iounmap(base);
>> +}
>> +
> 


-- 
Julien

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

* Re: [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10 14:00     ` Julien Grall
@ 2013-05-10 14:06       ` Ian Campbell
  2013-05-10 14:10         ` Julien Grall
  0 siblings, 1 reply; 79+ messages in thread
From: Ian Campbell @ 2013-05-10 14:06 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 15:00 +0100, Julien Grall wrote:
> On 05/10/2013 10:44 AM, Ian Campbell wrote:
> 
> >> @@ -91,6 +93,47 @@ out:
> >>  }
> >>  
> >>  /*
> >> + * TODO: Get base address from the device tree
> >> + * See arm,vexpress-reset node
> >> + */
> >> +static void vexpress_reset(void)
> >> +{
> >> +    void __iomem *base;
> >> +    void __iomem *sp810;
> >> +
> >> +    /* Use the SP810 system controller to force a reset */
> >> +    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
> >> +                        PAGE_HYPERVISOR_NOCACHE);
> >> +    if ( !base )
> >> +    {
> >> +        dprintk(XENLOG_ERR, "Unable to map SP810\n");
> >> +        return;
> >> +    }
> >> +
> >> +    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);
> > 
> > Didn't I see you making vunmap, which iounmap is based on, take care of
> > the page offsets itself in an earlier patch? Or is that not the reason
> > you are going through the base + offset dance?
> 
> 
> I wasn't not sure if you will accept ioremap(..., 8); I will fix the patch.

I'm confused, what does (..., 8) mean?

What I was asking about was why the code couldn't be:
	sp810 = ioremap_..(SP810_ADDRESS, PAGE_SIZE,..)
	iowritel(sp810,...)
	iounmap(sp810)

Ian.

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

* Re: [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10 14:06       ` Ian Campbell
@ 2013-05-10 14:10         ` Julien Grall
  2013-05-10 14:19           ` Ian Campbell
  0 siblings, 1 reply; 79+ messages in thread
From: Julien Grall @ 2013-05-10 14:10 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 03:06 PM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 15:00 +0100, Julien Grall wrote:
>> On 05/10/2013 10:44 AM, Ian Campbell wrote:
>>
>>>> @@ -91,6 +93,47 @@ out:
>>>>  }
>>>>  
>>>>  /*
>>>> + * TODO: Get base address from the device tree
>>>> + * See arm,vexpress-reset node
>>>> + */
>>>> +static void vexpress_reset(void)
>>>> +{
>>>> +    void __iomem *base;
>>>> +    void __iomem *sp810;
>>>> +
>>>> +    /* Use the SP810 system controller to force a reset */
>>>> +    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
>>>> +                        PAGE_HYPERVISOR_NOCACHE);
>>>> +    if ( !base )
>>>> +    {
>>>> +        dprintk(XENLOG_ERR, "Unable to map SP810\n");
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);
>>>
>>> Didn't I see you making vunmap, which iounmap is based on, take care of
>>> the page offsets itself in an earlier patch? Or is that not the reason
>>> you are going through the base + offset dance?
>>
>>
>> I wasn't not sure if you will accept ioremap(..., 8); I will fix the patch.
> 
> I'm confused, what does (..., 8) mean?

Because we only need to the first 8 bytes.

> What I was asking about was why the code couldn't be:
> 	sp810 = ioremap_..(SP810_ADDRESS, PAGE_SIZE,..)
> 	iowritel(sp810,...)
> 	iounmap(sp810)


Indeed. I will use this solution.

-- 
Julien

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

* Re: [PATCH V3 33/41] xen/arm: Add versatile express platform
  2013-05-10 14:10         ` Julien Grall
@ 2013-05-10 14:19           ` Ian Campbell
  0 siblings, 0 replies; 79+ messages in thread
From: Ian Campbell @ 2013-05-10 14:19 UTC (permalink / raw)
  To: Julien Grall; +Cc: Stefano Stabellini, patches, xen-devel

On Fri, 2013-05-10 at 15:10 +0100, Julien Grall wrote:
> On 05/10/2013 03:06 PM, Ian Campbell wrote:
> 
> > On Fri, 2013-05-10 at 15:00 +0100, Julien Grall wrote:
> >> On 05/10/2013 10:44 AM, Ian Campbell wrote:
> >>
> >>>> @@ -91,6 +93,47 @@ out:
> >>>>  }
> >>>>  
> >>>>  /*
> >>>> + * TODO: Get base address from the device tree
> >>>> + * See arm,vexpress-reset node
> >>>> + */
> >>>> +static void vexpress_reset(void)
> >>>> +{
> >>>> +    void __iomem *base;
> >>>> +    void __iomem *sp810;
> >>>> +
> >>>> +    /* Use the SP810 system controller to force a reset */
> >>>> +    base = ioremap_attr(SP810_ADDRESS & PAGE_MASK, PAGE_SIZE,
> >>>> +                        PAGE_HYPERVISOR_NOCACHE);
> >>>> +    if ( !base )
> >>>> +    {
> >>>> +        dprintk(XENLOG_ERR, "Unable to map SP810\n");
> >>>> +        return;
> >>>> +    }
> >>>> +
> >>>> +    sp810 = base + (SP810_ADDRESS & ~PAGE_MASK);
> >>>
> >>> Didn't I see you making vunmap, which iounmap is based on, take care of
> >>> the page offsets itself in an earlier patch? Or is that not the reason
> >>> you are going through the base + offset dance?
> >>
> >>
> >> I wasn't not sure if you will accept ioremap(..., 8); I will fix the patch.
> > 
> > I'm confused, what does (..., 8) mean?
> 
> Because we only need to the first 8 bytes.

If ioremap is happy with sub-page sizes then I'm ok with this or using
PAGE_SIZE.

Ian.

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

* Re: [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation
  2013-05-10  9:41   ` Ian Campbell
@ 2013-05-10 14:47     ` Julien Grall
  0 siblings, 0 replies; 79+ messages in thread
From: Julien Grall @ 2013-05-10 14:47 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Stefano Stabellini, patches, xen-devel

On 05/10/2013 10:41 AM, Ian Campbell wrote:

> On Fri, 2013-05-10 at 03:18 +0100, Julien Grall wrote:
>> 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>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> [...]
>> +/* 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)
>> +{
> [...]
>> +    /* 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();
> 
> Looks like the TODO is obsolete?

No. It means we need to print the compatible list of the DTS. Here Xen
only prints which platform is actually supported.
I will update the comment.

-- 
Julien

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

* Re: [PATCH V3 11/41] xen/arm: Introduce ioremap_attr
  2013-05-10  9:17   ` Ian Campbell
@ 2013-05-10 17:06     ` Stefano Stabellini
  0 siblings, 0 replies; 79+ messages in thread
From: Stefano Stabellini @ 2013-05-10 17:06 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Julien Grall, patches, Stefano Stabellini, xen-devel

On Fri, 10 May 2013, Ian Campbell wrote:
> > @@ -59,6 +59,8 @@
> >  #define DEV_CACHED    WRITEBACK
> >  
> >  #define PAGE_HYPERVISOR         (MATTR_MEM)
> 
> I should have noticed this when Stefano's original vmap patch went in
> but this is wrong.
> 
> MATTR_* are Second stage paging attributes (i.e. p2m ones) and are not
> suitable for the Xen first stage page tables.
> 
> MATTR_MEM == 0xf, which I think will be truncated to 0x7 when written to
> the ai field in the PT (which is only 3 bits) and so this is equivalent
> to using WRITEALLOC. I suspect that isn't at all desirable...
> 
> Stefano, can you fix this please?

Yep

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

end of thread, other threads:[~2013-05-10 17:06 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-10  2:17 [PATCH V3 00/41] Support multiple ARM platform in Xen Julien Grall
2013-05-10  2:17 ` [PATCH V3 01/41] xen/arm: lr must be included in range [0-nr_lr( Julien Grall
2013-05-10  2:17 ` [PATCH V3 02/41] xen/arm: Don't allow dom0 to access to vpl011 UART0 memory range Julien Grall
2013-05-10  2:17 ` [PATCH V3 03/41] xen/arm: Remove duplicated GICD_ICPIDR2 definition Julien Grall
2013-05-10  2:17 ` [PATCH V3 04/41] xen/arm: Bump early printk internal buffer to 512 Julien Grall
2013-05-10  2:17 ` [PATCH V3 05/41] xen/arm: Fix early_panic when EARLY_PRINTK is disabled Julien Grall
2013-05-10  2:17 ` [PATCH V3 06/41] xen/arm: Load dtb after dom0 kernel Julien Grall
2013-05-10  2:17 ` [PATCH V3 07/41] xen/arm: Switch to SYS_STATE_boot right after console setup Julien Grall
2013-05-10  8:40   ` Ian Campbell
2013-05-10  2:17 ` [PATCH V3 08/41] xen/arm: Export early_vprintk Julien Grall
2013-05-10  8:46   ` Ian Campbell
2013-05-10  2:17 ` [PATCH V3 09/41] xen/arm: Extend create_xen_entries prototype to take mapping attribute Julien Grall
2013-05-10  9:08   ` Ian Campbell
2013-05-10  2:17 ` [PATCH V3 10/41] xen/mm: Align virtual address on PAGE_SIZE in iounmap Julien Grall
2013-05-10  8:23   ` Jan Beulich
2013-05-10 12:40     ` Julien Grall
2013-05-10  2:17 ` [PATCH V3 11/41] xen/arm: Introduce ioremap_attr Julien Grall
2013-05-10  9:13   ` Ian Campbell
2013-05-10 12:00     ` Julien Grall
2013-05-10 12:07       ` Ian Campbell
2013-05-10 12:38         ` Julien Grall
2013-05-10  9:17   ` Ian Campbell
2013-05-10 17:06     ` Stefano Stabellini
2013-05-10  2:17 ` [PATCH V3 12/41] xen/arm: Add helpers ioreadl/iowritel Julien Grall
2013-05-10  2:17 ` [PATCH V3 13/41] xen/arm: Remove early_ioremap Julien Grall
2013-05-10  9:21   ` Ian Campbell
2013-05-10 12:35     ` Julien Grall
2013-05-10  2:18 ` [PATCH V3 14/41] xen/arm: Create a hierarchical device tree Julien Grall
2013-05-10  8:54   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 15/41] xen/arm: Add helpers to use the " Julien Grall
2013-05-10  8:54   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 16/41] xen/arm: Add helpers to retrieve an address from " Julien Grall
2013-05-10  2:18 ` [PATCH V3 17/41] xen/arm: Add helpers to retrieve an interrupt description " Julien Grall
2013-05-10  2:18 ` [PATCH V3 18/41] xen/arm: Introduce gic_route_dt_irq Julien Grall
2013-05-10  2:18 ` [PATCH V3 19/41] xen/arm: Introduce gic_irq_xlate Julien Grall
2013-05-10  2:18 ` [PATCH V3 20/41] xen/arm: Introduce setup_dt_irq Julien Grall
2013-05-10  2:18 ` [PATCH V3 21/41] xen/arm: Introduce request_dt_irq Julien Grall
2013-05-10  2:18 ` [PATCH V3 22/41] xen/arm: Use hierarchical device tree to retrieve GIC information Julien Grall
2013-05-10  9:23   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 23/41] xen/arm: Retrieve timer interrupts from the device tree Julien Grall
2013-05-10  9:23   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 24/41] xen/arm: Don't hardcode VGIC informations Julien Grall
2013-05-10  2:18 ` [PATCH V3 25/41] xen/arm: Don't hardcode virtual timer IRQs Julien Grall
2013-05-10  9:25   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 26/41] xen/arm: Introduce a generic way to use a device from the device tree Julien Grall
2013-05-10  2:18 ` [PATCH V3 27/41] xen/arm: New callback in uart_driver to get device tree interrupt structure Julien Grall
2013-05-10  2:18 ` [PATCH V3 28/41] xen/arm: Add generic UART to get the device in the device tree Julien Grall
2013-05-10  9:32   ` Ian Campbell
2013-05-10 12:47     ` Julien Grall
2013-05-10  2:18 ` [PATCH V3 29/41] xen/arm: Use device tree API in pl011 UART driver Julien Grall
2013-05-10  9:35   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 30/41] xen/arm: Use the device tree to map the address range and IRQ to dom0 Julien Grall
2013-05-10  9:37   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 31/41] xen/arm: Allow Xen to run on multiple platform without recompilation Julien Grall
2013-05-10  9:41   ` Ian Campbell
2013-05-10 14:47     ` Julien Grall
2013-05-10  2:18 ` [PATCH V3 32/41] xen/arm: WORKAROUND 1:1 memory mapping for dom0 Julien Grall
2013-05-10  2:18 ` [PATCH V3 33/41] xen/arm: Add versatile express platform Julien Grall
2013-05-10  9:44   ` Ian Campbell
2013-05-10 14:00     ` Julien Grall
2013-05-10 14:06       ` Ian Campbell
2013-05-10 14:10         ` Julien Grall
2013-05-10 14:19           ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 34/41] xen/arm: Remove request_irq Julien Grall
2013-05-10  2:18 ` [PATCH V3 35/41] xen/arm: Remove setup_irq Julien Grall
2013-05-10  2:18 ` [PATCH V3 36/41] xen/arm: Don't use pl011 UART by default for early printk Julien Grall
2013-05-10  9:46   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 37/41] xen/arm: Add exynos 4210 UART support Julien Grall
2013-05-10  9:49   ` Ian Campbell
2013-05-10 13:00     ` Julien Grall
2013-05-10  2:18 ` [PATCH V3 38/41] xen/arm: Add Exynos 4210 UART support for early printk Julien Grall
2013-05-10  9:49   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 39/41] xen/arm: Add platform specific code for the exynos5 Julien Grall
2013-05-10  9:50   ` Ian Campbell
2013-05-10  2:18 ` [PATCH V3 40/41] xen/arm: WORKAROUND Support kick cpus and switch to hypervisor " Julien Grall
2013-05-10  2:18 ` [PATCH V3 41/41] xen/arm64: Remove hardcoded value for gic in assembly code Julien Grall
2013-05-10  9:48 ` [PATCH V3 00/41] Support multiple ARM platform in Xen George Dunlap
2013-05-10 12:50   ` Julien Grall
2013-05-10 13:34     ` Ian Campbell

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