From: Peng Fan <[email protected]>

To boot jailhouse before linux, we need a preloader to initialize
GIC, boot up all cores, did basic EL2 initialization, then kick
inmate/root cell.

This patchset only supports ARM64 with GICv3 and tested on
i.MX8MM EVK board.

The gicv3 initialization is mostly reused from Linux Kernel.

The images are all packed into a FIT image, and U-Boot load
the FIT images. When bootm, U-Boot will parse the FIT image and
copy payload to address specific in fit image.

The fit file in the patch is fit.its, currently the address are
hardcoded. Later, a script would be used to automatic generate it.

The script to generate the FIT image for U-Boot

cp hypervisor/jailhouse.bin loader/
cp configs/arm64/imx8mm.cell loader/
cp configs/arm64/imx8mm-gic-demo.cell loader/
cp inmates/demos/arm64/gic-demo.bin loader/
cp <Linux>/arch/arm64/boot/dts/freescale/imx8mm-evk-root.dtb ./loader
cd loader
mkimage -E -f fit.its loader.itb
cd -

The boot command:
=>run mmcargs
=>dhcp 0x404800000 Image
=>fatload mmc 1:1 0x60000000 loader.itb
=>bootm 0x60000000

Signed-off-by: Peng Fan <[email protected]>
---
 Kbuild                                            |   4 +
 bootloader/8mm.its                                |  75 +++
 bootloader/Makefile                               |  68 +++
 bootloader/arch/arm-common/Kbuild                 |  17 +
 bootloader/arch/arm-common/gic-common.c           |  34 ++
 bootloader/arch/arm-common/gic-v3.c               | 127 ++++
 bootloader/arch/arm-common/include/gic-common.h   |   2 +
 bootloader/arch/arm64/Kbuild                      |  21 +
 bootloader/arch/arm64/Makefile                    |  15 +
 bootloader/arch/arm64/head.S                      | 201 +++++++
 bootloader/arch/arm64/inmate.c                    |  53 ++
 bootloader/arch/arm64/main.c                      | 218 +++++++
 bootloader/include/bootloader.h                   |   5 +
 bootloader/include/config.h                       |   5 +
 bootloader/include/fls.h                          |  42 ++
 bootloader/include/linux/irqchip/arm-gic-common.h |  21 +
 bootloader/include/linux/irqchip/arm-gic-v3.h     | 674 ++++++++++++++++++++++
 bootloader/include/linux/irqchip/arm-gic.h        |  34 ++
 bootloader/loader.lds                             |  22 +
 hypervisor/arch/arm-common/include/asm/psci.h     |  10 +
 hypervisor/arch/arm64/include/asm/sysregs.h       |  13 +
 21 files changed, 1661 insertions(+)
 create mode 100644 bootloader/8mm.its
 create mode 100644 bootloader/Makefile
 create mode 100644 bootloader/arch/arm-common/Kbuild
 create mode 100644 bootloader/arch/arm-common/gic-common.c
 create mode 100644 bootloader/arch/arm-common/gic-v3.c
 create mode 100644 bootloader/arch/arm-common/include/gic-common.h
 create mode 100644 bootloader/arch/arm64/Kbuild
 create mode 100644 bootloader/arch/arm64/Makefile
 create mode 100644 bootloader/arch/arm64/head.S
 create mode 100644 bootloader/arch/arm64/inmate.c
 create mode 100644 bootloader/arch/arm64/main.c
 create mode 100644 bootloader/include/bootloader.h
 create mode 100644 bootloader/include/config.h
 create mode 100644 bootloader/include/fls.h
 create mode 100644 bootloader/include/linux/irqchip/arm-gic-common.h
 create mode 100644 bootloader/include/linux/irqchip/arm-gic-v3.h
 create mode 100644 bootloader/include/linux/irqchip/arm-gic.h
 create mode 100644 bootloader/loader.lds

diff --git a/Kbuild b/Kbuild
index dc6423ad..db746a64 100644
--- a/Kbuild
+++ b/Kbuild
@@ -52,6 +52,9 @@ $(GEN_PCI_DEFS_PY): $(src)/scripts/gen_pci_defs.sh
        $(call if_changed,gen_pci_defs)
 
 subdir-y := hypervisor configs inmates tools libbaremetal
+ifeq ($(SRCARCH), arm64)
+subdir-y += bootloader
+endif
 
 subdir-ccflags-y := -Werror
 
@@ -63,6 +66,7 @@ ifeq ($(filter %/Makefile.clean,$(MAKEFILE_LIST)),)
 $(obj)/driver $(addprefix $(obj)/,$(subdir-y)): $(GEN_CONFIG_MK)
 
 $(addprefix $(obj)/,inmates): $(addprefix $(obj)/,libbaremetal)
+$(addprefix $(obj)/,bootloader): $(addprefix $(obj)/,libbaremetal)
 
 $(obj)/driver $(obj)/hypervisor: $(GEN_VERSION_H)
 
diff --git a/bootloader/8mm.its b/bootloader/8mm.its
new file mode 100644
index 00000000..55d215fc
--- /dev/null
+++ b/bootloader/8mm.its
@@ -0,0 +1,75 @@
+/dts-v1/;
+
+/ {
+       description = "Configuration to load Images";
+
+       images {
+               kernel {
+                       description = "linux";
+                       os = "Linux";
+                       data = /incbin/("loader.bin");
+                       type = "kernel";
+                       arch = "arm64";
+                       compression = "none";
+                       load = <0x40000000>;
+                       entry = <0x40000000>;
+               };
+
+               hypervisor {
+                       description = "Jailhouse hypervisor";
+                       os = "jailhouse";
+                       data = /incbin/("jailhouse.bin");
+                       type = "standalone";
+                       arch = "arm64";
+                       compression = "none";
+                       load = <0x40200000>;
+               };
+
+               cell@1 {
+                       description = "i.MX8MM cell";
+                       data = /incbin/("imx8mm.cell");
+                       arch = "arm64";
+                       type = "standalone";
+                       compression = "none";
+                       load = <0x40300000>;
+               };
+
+               cell@2 {
+                       description = "i.MX8MM GIC-CELL";
+                       data = /incbin/("imx8mm-gic-demo.cell");
+                       arch = "arm64";
+                       type = "standalone";
+                       compression = "none";
+                       load = <0x40310000>;
+               };
+
+               inmate@2 {
+                       description = "i.MX8MM GIC-DEMO";
+                       data = /incbin/("gic-demo.bin");
+                       arch = "arm64";
+                       type = "standalone";
+                       compression = "none";
+                       load = <0xb3c00000>;
+               };
+
+               fdt {
+                       description = "fdt";
+                       data = /incbin/("imx8mm-evk-root.dtb");
+                       type = "flat_dt";
+                       compression = "none";
+                       arch = "arm64";
+                       load = <0x43000000>;
+               };
+       };
+
+       configurations {
+               default = "config@1";
+
+               config@1 {
+                       description = "imx8mp-evk";
+                       kernel = "kernel";
+                       fdt = "fdt";
+                       loadables = "hypervisor", "cell@1", "cell@2", 
"inmate@2";
+               };
+       };
+};
diff --git a/bootloader/Makefile b/bootloader/Makefile
new file mode 100644
index 00000000..63114fa3
--- /dev/null
+++ b/bootloader/Makefile
@@ -0,0 +1,68 @@
+-include $(GEN_CONFIG_MK)
+
+BAREMETAL_LIB = $(src)/../libbaremetal/$(SRCARCH)
+export BAREMETAL_LIB
+
+INCLUDES := -I$(BAREMETAL_LIB)/include \
+           -I$(src)/../include/arch/$(SRCARCH) \
+           -I$(src)/../include \
+           -I$(src)/include    \
+           -I$(src)/../libbaremetal/include \
+           -I$(src)/../hypervisor/arch/$(SRCARCH)/include \
+           -I$(src)/../hypervisor/include
+
+
+ifeq ($(subst arm64,arm,$(SRCARCH)),arm)
+INCLUDES += -I$(src)/../hypervisor/arch/arm-common/include
+INCLUDES += -I$(src)/../libbaremetal/arm-common/include
+INCLUDES += -I$(src)/arch/arm-common/include
+endif
+
+LINUXINCLUDE  := $(INCLUDES)
+KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE
+KBUILD_CFLAGS := -g -Os -Wall -Wstrict-prototypes -Wtype-limits \
+                -Wmissing-declarations -Wmissing-prototypes \
+                -fno-strict-aliasing -fno-pic -fno-common \
+                -fno-stack-protector -fno-builtin-ffsl \
+                -D__LINUX_COMPILER_TYPES_H -mstrict-align
+
+CORE_OBJECTS := arch/$(SRCARCH)/head.o
+
+ifneq ($(wildcard $(INC_CONFIG_H)),)
+KBUILD_CFLAGS += -include $(INC_CONFIG_H)
+endif
+
+#ccflags-y := -I$(src)/../hypervisor/arch/$(SRCARCH)/include \
+#           -I$(src)/../hypervisor/include \
+#           -I$(src)/../include/arch/$(SRCARCH) \
+#           -I$(src)/../include
+
+always :=
+
+subdir-y := arch/$(SRCARCH)
+
+define BUILD_loader_template
+always += loader$(1).bin
+
+$$(obj)/arch/$$(SRCARCH)/lib$(1).a: $$(obj)/arch/$$(SRCARCH)
+       @true
+
+loader$(1)-y := arch/$$(SRCARCH)/lib$(1).a $$(CORE_OBJECTS) loader.lds
+targets += $$(loader$(1)-y)
+
+loader$(1)_OBJS = $$(addprefix $$(obj)/,$$(loader$(1)-y))
+
+LDFLAGS_loader$(1).o := --whole-archive -T
+
+targets += loader$(1).o
+$$(obj)/loader$(1).o: $$(src)/loader.lds $$(loader$(1)_OBJS) 
$(BAREMETAL_LIB)/lib.a
+       $$(call if_changed,ld)
+
+OBJCOPYFLAGS_loader$(1).bin := -O binary -R .eh_frame
+
+targets += loader$(1).bin
+$$(obj)/loader$(1).bin: $$(obj)/loader$(1).o
+       $$(call if_changed,objcopy)
+endef
+
+$(eval $(call BUILD_loader_template,))
diff --git a/bootloader/arch/arm-common/Kbuild 
b/bootloader/arch/arm-common/Kbuild
new file mode 100644
index 00000000..6e291f69
--- /dev/null
+++ b/bootloader/arch/arm-common/Kbuild
@@ -0,0 +1,17 @@
+#
+# Jailhouse, a Linux-based partitioning hypervisor
+#
+# Copyright (c) Siemens AG, 2013-2017
+#
+# Authors:
+#  Jan Kiszka <[email protected]>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+
+-include $(GEN_CONFIG_MK)
+
+objs-y += gic-common.o gic-v3.o
+
+common-objs-y = $(addprefix ../arm-common/,$(objs-y))
diff --git a/bootloader/arch/arm-common/gic-common.c 
b/bootloader/arch/arm-common/gic-common.c
new file mode 100644
index 00000000..104d7d10
--- /dev/null
+++ b/bootloader/arch/arm-common/gic-common.c
@@ -0,0 +1,34 @@
+#include <jailhouse/types.h>
+#include <gic-common.h>
+#include <mmio.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/arm-gic-common.h>
+
+void gic_dist_config(void *base, int gic_irqs, void (*sync_access)(void))
+{
+       unsigned int i;
+
+       /*
+        * Set all global interrupts to be level triggered, active low.
+        */
+       for (i = 32; i < gic_irqs; i += 16)
+               mmio_write32(base + GIC_DIST_CONFIG + i / 4, 0);
+
+       /*
+        * Set priority on all global interrupts.
+        */
+       for (i = 32; i < gic_irqs; i += 4)
+               mmio_write32(base + GIC_DIST_PRI + i, GICD_INT_DEF_PRI_X4);
+
+       /*
+        * Deactivate and disable all SPIs. Leave the PPI and SGIs
+        * alone as they are in the redistributor registers on GICv3.
+        */
+       for (i = 32; i < gic_irqs; i += 32) {
+               mmio_write32(base + GIC_DIST_ACTIVE_CLEAR + i / 8, 
GICD_INT_EN_CLR_X32);
+               mmio_write32(base + GIC_DIST_ENABLE_CLEAR + i / 8, 
GICD_INT_EN_CLR_X32);
+       }
+
+       if (sync_access)
+               sync_access();
+}
diff --git a/bootloader/arch/arm-common/gic-v3.c 
b/bootloader/arch/arm-common/gic-v3.c
new file mode 100644
index 00000000..39b1e1fc
--- /dev/null
+++ b/bootloader/arch/arm-common/gic-v3.c
@@ -0,0 +1,127 @@
+#include <jailhouse/types.h>
+#include <jailhouse/mmio.h>
+#include <gic-common.h>
+#include <linux/irqchip/arm-gic-common.h>
+#include <linux/irqchip/arm-gic-v3.h>
+
+#include <asm/sysregs.h>
+#include <asm/processor.h>
+#include <mmio.h>
+
+#define GICD_INT_DEF_PRI                0xa0
+#define GICD_INT_DEF_PRI_X4             ((GICD_INT_DEF_PRI << 24) |\
+                                        (GICD_INT_DEF_PRI << 16) |\
+                                        (GICD_INT_DEF_PRI << 8) |\
+                                        GICD_INT_DEF_PRI)
+struct rdists {
+       unsigned int    gicd_typer;
+       bool            has_vlpis;
+       bool            has_direct_lpi;
+};
+
+struct gic_chip_data {
+       void            *dist_base;
+       struct rdists   rdists;
+};
+
+static struct gic_chip_data gic_data;
+
+#define GICD_TYPER_ESPI                        (1U << 8)
+
+#define GICD_TYPER_SPIS(typer)         ((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_ESPIS(typer)                                                
\
+       (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
+
+#define min(x, y)      ((x) < (y) ? (x) : (y))
+#define GIC_LINE_NR    min(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
+#define GIC_ESPI_NR    GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
+
+
+static void gic_do_wait_for_rwp(void *base)
+{
+       u32 count = 1000000000; /* 1s! */
+
+       while (mmio_read32(base + GICD_CTLR) & GICD_CTLR_RWP) {
+               count--;
+               if (!count) {
+                       return;
+               }
+               cpu_relax();
+#if 0
+               udelay(1);
+#endif
+       }
+}
+
+/* Wait for completion of a distributor change */
+static void gic_dist_wait_for_rwp(void)
+{
+       gic_do_wait_for_rwp(gic_data.dist_base);
+}
+
+static unsigned long phys_processor_id(void)
+{
+       unsigned long mpidr;
+
+       arm_read_sysreg(MPIDR_EL1, mpidr);
+
+       return mpidr & MPIDR_CPUID_MASK;
+}
+
+void gic_dist_init(void *base)
+{
+       unsigned int i;
+       u64 affinity;
+       u32 typer;
+
+       gic_data.dist_base = base;
+
+       typer = mmio_read32(gic_data.dist_base + GICD_TYPER);
+       gic_data.rdists.gicd_typer = typer;
+
+       /* Disable the distributor */
+       mmio_write32(base + GICD_CTLR, 0);
+       gic_dist_wait_for_rwp();
+
+       /*
+        * Configure SPIs as non-secure Group-1. This will only matter
+        * if the GIC only has a single security state. This will not
+        * do the right thing if the kernel is running in secure mode,
+        * but that's not the intended use case anyway.
+        */
+       for (i = 32; i < GIC_LINE_NR; i += 32)
+               mmio_write32(base + GICD_IGROUPR + i / 8, ~0U);
+
+       /* Extended SPI range, not handled by the GICv2/GICv3 common code */
+       for (i = 0; i < GIC_ESPI_NR; i += 32) {
+               mmio_write32(base + GICD_ICENABLERnE + i / 8, ~0U);
+               mmio_write32(base + GICD_ICACTIVERnE + i / 8, ~0U);
+       }
+
+       for (i = 0; i < GIC_ESPI_NR; i += 32)
+               mmio_write32(base + GICD_IGROUPRnE + i / 8, ~0U);
+
+       for (i = 0; i < GIC_ESPI_NR; i += 16)
+               mmio_write32(base + GICD_ICFGRnE + i / 4, 0);
+
+       for (i = 0; i < GIC_ESPI_NR; i += 4)
+               mmio_write32(base + GICD_IPRIORITYRnE + i, GICD_INT_DEF_PRI_X4);
+
+       /* Now do the common stuff, and wait for the distributor to drain */
+       gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
+
+       /* Enable distributor with ARE, Group1 */
+       mmio_write32(base + GICD_CTLR,
+                    GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | 
GICD_CTLR_ENABLE_G1);
+
+       /*
+        * Set all global interrupts to the boot CPU only. ARE must be
+        * enabled.
+        */
+       affinity = phys_processor_id();
+       for (i = 32; i < GIC_LINE_NR; i++)
+               mmio_write64(base + GICD_IROUTER + i * 8, affinity);
+
+       for (i = 0; i < GIC_ESPI_NR; i++)
+               mmio_write64(base + GICD_IROUTERnE + i * 8, affinity);
+}
diff --git a/bootloader/arch/arm-common/include/gic-common.h 
b/bootloader/arch/arm-common/include/gic-common.h
new file mode 100644
index 00000000..7c239f3e
--- /dev/null
+++ b/bootloader/arch/arm-common/include/gic-common.h
@@ -0,0 +1,2 @@
+void gic_dist_config(void *base, int gic_irqs, void (*sync_access)(void));
+void gic_dist_init(void *base);
diff --git a/bootloader/arch/arm64/Kbuild b/bootloader/arch/arm64/Kbuild
new file mode 100644
index 00000000..4b5c9a5a
--- /dev/null
+++ b/bootloader/arch/arm64/Kbuild
@@ -0,0 +1,21 @@
+#
+# Jailhouse AArch64 support
+#
+# Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+# Copyright (c) Siemens AG, 2016
+#
+# Authors:
+#  Antonios Motakis <[email protected]>
+#  Jan Kiszka <[email protected]>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+
+include $(src)/../arm-common/Kbuild
+
+always := lib.a
+
+lib-y := main.o inmate.o
+lib-y += $(common-objs-y)
+obj-y := head.o
diff --git a/bootloader/arch/arm64/Makefile b/bootloader/arch/arm64/Makefile
new file mode 100644
index 00000000..0718994d
--- /dev/null
+++ b/bootloader/arch/arm64/Makefile
@@ -0,0 +1,15 @@
+#
+# Jailhouse AArch64 support
+#
+# Copyright (C) 2015 Huawei Technologies Duesseldorf GmbH
+#
+# Authors:
+#  Antonios Motakis <[email protected]>
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+
+LINUXINCLUDE += -I$(src)/arch/arm-common/include
+
+KBUILD_CFLAGS += -march=armv8-a+nofp
diff --git a/bootloader/arch/arm64/head.S b/bootloader/arch/arm64/head.S
new file mode 100644
index 00000000..7c289ad8
--- /dev/null
+++ b/bootloader/arch/arm64/head.S
@@ -0,0 +1,201 @@
+/*
+ * Jailhouse AArch64 support
+ *
+ * Copyright (C) 2015-2016 Huawei Technologies Duesseldorf GmbH
+ * Copyright (c) 2016 Siemens AG
+ * Copyright (C) 1994-2002 Russell King
+ * Copyright (C) 2003-2012 ARM Ltd.
+ * Copyright 2020 NXP
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <asm/sysregs.h>
+
+       .section ".header", "ax"
+       .global secondary_entry
+
+el2_entry:
+       /* Clear BSS */
+       adr     x8, __cpu_id
+       adr     x9, __stack_pool
+       sub     x9, x9, x8
+       lsr     x9, x9, #3
+1:     str     xzr, [x8], #0x8
+       sub     x9, x9, #1
+       cmp     x9, #0
+       b.ne    1b
+
+       /*
+        * args in bss area, so put after bss clearing
+        * Store bootargs
+        */
+       adr     x8, args
+       stp     x0, x1, [x8]
+       add     x8, x8, #16
+       stp     x2, x3, [x8]
+
+       .align 4
+secondary_entry:
+       msr     SPsel, #1
+       mrs     x0, CurrentEL
+       cmp     x0, #CurrentEL_EL2
+       b.eq    2f
+       b       .
+
+2:     ldr     x0, =SCTLR_EL2_RES1
+       msr     sctlr_el2, x0
+
+       mov     x2, xzr
+
+       /* Hyp configuration. */
+       ldr     x0, =HCR_HOST_NVHE_FLAGS
+       msr     hcr_el2, x0
+       isb
+
+       /*
+        * Allow Non-secure EL1 and EL0 to access physical timer and counter.
+        * This is not necessary for VHE, since the host kernel runs in EL2,
+        * and EL0 accesses are configured in the later stage of boot process.
+        * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
+        * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
+        * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
+        * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
+        * EL2.
+        */
+       cbnz    x2, 1f
+       mrs     x0, cnthctl_el2
+       orr     x0, x0, #3                      // Enable EL1 physical timers
+       msr     cnthctl_el2, x0
+1:
+       msr     cntvoff_el2, xzr                // Clear virtual offset
+
+#ifdef CONFIG_ARM_GIC_V3
+       /* GICv3 system register access */
+       mrs     x0, id_aa64pfr0_el1
+       ubfx    x0, x0, #ID_AA64PFR0_GIC_SHIFT, #4
+       cbz     x0, 3f
+
+       mrs     x0, SYS_ICC_SRE_EL2
+       orr     x0, x0, #ICC_SRE_EL2_SRE        // Set ICC_SRE_EL2.SRE==1
+       orr     x0, x0, #ICC_SRE_EL2_ENABLE     // Set ICC_SRE_EL2.Enable==1
+       msr     SYS_ICC_SRE_EL2, x0
+       isb                                     // Make sure SRE is now set
+       mrs     x0, SYS_ICC_SRE_EL2             // Read SRE back,
+       tbz     x0, #0, 3f                      // and check that it sticks
+       msr     SYS_ICH_HCR_EL2, xzr            // Reset ICC_HCR_EL2 to defaults
+
+3:
+#endif
+
+       /* Populate ID registers. */
+       mrs     x0, midr_el1
+       mrs     x1, mpidr_el1
+       msr     vpidr_el2, x0
+       msr     vmpidr_el2, x1
+
+#ifdef CONFIG_COMPAT
+       msr     hstr_el2, xzr                   // Disable CP15 traps to EL2
+#endif
+
+1:
+       /* Stage-2 translation */
+       msr     vttbr_el2, xzr
+
+       cbz     x2, install_el2_stub
+
+       isb
+       ret
+
+install_el2_stub:
+       ldr     x0, =SCTLR_EL1_RES1
+       msr     sctlr_el1, x0
+
+       /* Coprocessor traps. */
+       mov     x0, #0x33ff
+       msr     cptr_el2, x0                    // Disable copro. traps to EL2
+
+       /* SVE register access */
+       mrs     x1, id_aa64pfr0_el1
+       ubfx    x1, x1, #ID_AA64PFR0_SVE_SHIFT, #4
+       cbz     x1, 7f
+
+       bic     x0, x0, #CPTR_EL2_TZ            // Also disable SVE traps
+       msr     cptr_el2, x0                    // Disable copro. traps to EL2
+       isb
+       mov     x1, #ZCR_ELx_LEN_MASK           // SVE: Enable full vector
+       msr     SYS_ZCR_EL2, x1                 // length for EL1.
+
+       /* Hypervisor stub */
+7:     adr     x0, __hyp_stub_vectors
+       msr     vbar_el2, x0
+
+       /*
+        * Set Stack
+        * We are not able to get a software friend cpu id, so
+        * use smp_cores to count how many cores runs into el2_entry,
+        * and set stack for the core. There is no concurrent access.
+        * And smp_cores - 1 will be used as cpuid when entry
+        * Stack size as 0x400
+        */
+       mov     x7, #0x400
+       adr     x9, smp_cores
+       ldr     x8, [x9]
+       add     x8, x8, #1
+       str     x8, [x9]
+       adr     x10, __stack_pool
+       madd    x10, x8, x7, x10
+       msr     sp_el1, x10
+
+       adr     x1, entry
+       mov     x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
+                     PSR_MODE_EL1h)
+       msr     spsr_el2, x0
+       msr     elr_el2, x1
+       adr     x9, smp_cores
+       ldr     x0, [x9]
+       sub     x0, x0, #1
+       eret
+
+.macro ventry  label
+       .align  7
+       b       \label
+.endm
+       .align 11
+
+       .global __hyp_stub_vectors
+__hyp_stub_vectors:
+       ventry  .
+       ventry  .
+       ventry  .
+       ventry  .
+
+       ventry  .
+       ventry  .
+       ventry  .
+       ventry  .
+
+       ventry  el1_sync                        // Synchronous 64-bit EL1
+       ventry  .
+       ventry  .
+       ventry  .
+
+       ventry  .
+       ventry  .
+       ventry  .
+       ventry  .
+
+
+       .align 11
+
+#define HVC_SET_VECTORS 0
+
+el1_sync:
+       cmp     x0, #HVC_SET_VECTORS
+       b.ne    9f
+       msr     vbar_el2, x1
+       b       9f
+9:     mov     x0, xzr
+       eret
+       .ltorg
diff --git a/bootloader/arch/arm64/inmate.c b/bootloader/arch/arm64/inmate.c
new file mode 100644
index 00000000..136dba71
--- /dev/null
+++ b/bootloader/arch/arm64/inmate.c
@@ -0,0 +1,53 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright 2020 NXP
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <bootloader.h>
+#include <config.h>
+#include <string.h>
+#include <jailhouse/types.h>
+#include <jailhouse/cell-config.h>
+#include <jailhouse/header.h>
+#include <jailhouse/hypercall.h>
+#include <generated/version.h>
+
+int kick_inmate_cell(void)
+{
+       struct jailhouse_cell_desc *config;
+       int i, err;
+
+       /* Ignore ROOT CELL */
+       for (i = 1; i < MAX_CELL; i++) {
+               config = (struct jailhouse_cell_desc *)(START_ADDR_CELL + i * 
STRIDE_CELL);
+               if (memcmp(config->signature,
+                          JAILHOUSE_CELL_DESC_SIGNATURE, 
sizeof(config->signature)) != 0)
+                       break;
+
+               if (config->revision != JAILHOUSE_CONFIG_REVISION)
+                       break;
+
+               config->name[JAILHOUSE_CELL_NAME_MAXLEN] = 0;
+
+               /* Start from high end */
+               config->id = 256 - i;
+
+               err = jailhouse_call_arg1(JAILHOUSE_HC_CELL_CREATE, (unsigned 
long)config);
+               if (err)
+                       return err;
+
+               err = jailhouse_call_arg1(JAILHOUSE_HC_CELL_SET_LOADABLE, 
config->id);
+               if (err)
+                       return err;
+
+               err = jailhouse_call_arg1(JAILHOUSE_HC_CELL_START, config->id);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
diff --git a/bootloader/arch/arm64/main.c b/bootloader/arch/arm64/main.c
new file mode 100644
index 00000000..3381ca7e
--- /dev/null
+++ b/bootloader/arch/arm64/main.c
@@ -0,0 +1,218 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright 2020 NXP
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/types.h>
+
+#include <asm/sysregs.h>
+#include <asm/psci.h>
+#include <bootloader.h>
+#include <config.h>
+#include <fls.h>
+#include <gic-common.h>
+#include <string.h>
+#include <jailhouse/cell-config.h>
+#include <jailhouse/header.h>
+#include <jailhouse/hypercall.h>
+#include <generated/version.h>
+
+unsigned long __attribute__((aligned(64))) smp_cores = 0UL;
+unsigned long __attribute__((aligned(64))) args[4];
+
+struct jailhouse_header *header;
+struct jailhouse_system *config_header;
+struct jailhouse_system *config;
+struct jailhouse_memory *hv_mem;
+static unsigned long hv_core_and_percpu_size;
+unsigned long config_size;
+void *hypervisor_mem;
+long max_cpus;
+
+static unsigned long call_smcc64(unsigned long fid, unsigned long a0,
+                                unsigned long a1, unsigned long a2,
+                                unsigned long a3, unsigned long a4,
+                                unsigned long a5, unsigned long *ret)
+{
+       register unsigned long x0 asm("x0") = fid;
+       register unsigned long x1 asm("x1") = a0;
+       register unsigned long x2 asm("x2") = a1;
+       register unsigned long x3 asm("x3") = a2;
+       register unsigned long x4 asm("x4") = a3;
+       register unsigned long x5 asm("x5") = a4;
+       register unsigned long x6 asm("x6") = a5;
+
+       asm volatile ("smc #0\n"
+                     : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3),
+                     "+r" (x4), "+r" (x5), "+r" (x6)
+                     :
+                     : "x7", "x8", "x9", "x10", "x11", "x12",
+                     "x13", "x14", "x15", "x16", "x17" );
+
+       if (ret) {
+               ret[0] = x0;
+               ret[1] = x1;
+               ret[2] = x2;
+               ret[3] = x3;
+       }
+
+       return x0;
+}
+
+static int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
+{
+       int err;
+       u32 fn;
+
+       fn = PSCI_0_2_FN64_CPU_ON;
+       err = call_smcc64(fn, cpuid, entry_point, 0, 0, 0, 0, NULL);
+       return err;
+}
+
+static int psci_cpu_off(void)
+{
+       u32 fn;
+
+       fn = PSCI_0_2_FN_CPU_OFF;
+       u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN <<
+                   PSCI_0_2_POWER_STATE_TYPE_SHIFT;
+
+       call_smcc64(fn, state, 0, 0, 0, 0, 0, NULL);
+
+       return 0;
+}
+
+static int psci_cpu_affinity(unsigned int cpuid)
+{
+       u32 fn;
+
+       fn = PSCI_0_2_FN64_AFFINITY_INFO;
+
+       return call_smcc64(fn, cpuid, 0, 0, 0, 0, 0, NULL);
+}
+
+/* Run in EL1 mode */
+static void enter_hypervisor(void *info, int cpu)
+{
+       struct jailhouse_header *header = info;
+       int (*entry)(unsigned int);
+
+       entry = header->entry + (unsigned long) hypervisor_mem;
+
+       entry(cpu);
+}
+
+static long get_max_cpus(u32 cpu_set_size, const struct jailhouse_system 
*system_config)
+{
+       u8 *cpu_set = (u8 *)jailhouse_cell_cpu_set((const struct 
jailhouse_cell_desc *)&system_config->root_cell);
+       unsigned int pos = cpu_set_size;
+       long max_cpu_id;
+       u8 bitmap;
+
+       while (pos-- > 0) {
+               bitmap = *(cpu_set + pos);
+               max_cpu_id = fls(bitmap);
+               if (max_cpu_id > 0) {
+                       return pos * 8 + max_cpu_id;
+               }
+       }
+       return -2;
+}
+
+static void panic(void)
+{
+       /* TODO */
+       asm volatile("b .\r\n");
+}
+
+int entry(unsigned int cpuid)
+{
+       int i, ret;
+       void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, void 
*res2);
+       unsigned long mpidr;
+       void *gicd_base;
+
+       arm_read_sysreg(MPIDR_EL1, mpidr);
+
+       if (cpuid) {
+               __cpu_id[cpuid << 1] = cpuid;
+               /* Used by psci affinity */
+               __cpu_id[(cpuid << 1) + 1] = mpidr & MPIDR_CPUID_MASK;
+               enter_hypervisor(header, cpuid);
+               psci_cpu_off();
+       }
+
+       header = (struct jailhouse_header *)JAILHOUSE_ADDR;
+       config_header = (struct jailhouse_system *)START_ADDR_CELL;
+       hv_mem = &config_header->hypervisor_memory;
+       gicd_base = (void *)(unsigned 
long)config_header->platform_info.arm.gicd_base;
+
+       if (config_header->platform_info.arm.gic_version != 3)
+               panic();
+
+       max_cpus = get_max_cpus(config_header->root_cell.cpu_set_size, 
config_header);
+       if (memcmp(header->signature, JAILHOUSE_SIGNATURE, 
sizeof(header->signature)) != 0)
+               panic();
+
+       hv_core_and_percpu_size = header->core_size +
+               max_cpus * header->percpu_size;
+
+       config_size = jailhouse_system_config_size(config_header);
+
+       if (hv_core_and_percpu_size >= hv_mem->size ||
+           config_size >= hv_mem->size - hv_core_and_percpu_size)
+               panic();
+
+       hypervisor_mem = (void *)config_header->hypervisor_memory.phys_start;
+       /*
+        * Copy hypervisor's binary image at beginning of the memory region
+        * and clear the rest to zero.
+        */
+       memcpy(hypervisor_mem, header, header->console_page);
+       memset(hypervisor_mem + header->console_page, 0,
+              hv_mem->size - header->console_page);
+
+       header = (struct jailhouse_header *)hypervisor_mem;
+       header->max_cpus = max_cpus;
+       header->arm_linux_hyp_vectors = (unsigned long long)__hyp_stub_vectors;
+       header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE;
+
+       header->online_cpus = max_cpus;
+
+       config = (struct jailhouse_system *)(hypervisor_mem + 
hv_core_and_percpu_size);
+       memcpy(config, config_header, config_size);
+
+       /* Init GIC */
+       gic_dist_init(gicd_base);
+
+       /* PSCI CPU ON */
+       for (i = 1; i < max_cpus; i++) {
+               ret = psci_cpu_on(i, (unsigned long)secondary_entry);
+               if (ret)
+                       panic();
+       }
+
+       enter_hypervisor(header, cpuid);
+
+       for (i = 1; i < max_cpus; i++) {
+               do {
+                       /* Wait until off */
+                       ret = psci_cpu_affinity(__cpu_id[(i << 1) + 1]);
+               } while (ret == PSCI_CPU_IS_ON);
+       }
+
+       /* Create inmate cells */
+       ret = kick_inmate_cell();
+       if (ret)
+               panic();
+
+       /* Jump to Kernel */
+       kernel_entry = (void (*)(void *, void *, void *, void *))KERNEL_ADDR;
+       kernel_entry((void *)args[0], (void *)args[1], (void *)args[2], (void 
*)args[3]);
+
+       return 0;
+}
diff --git a/bootloader/include/bootloader.h b/bootloader/include/bootloader.h
new file mode 100644
index 00000000..ba2f626e
--- /dev/null
+++ b/bootloader/include/bootloader.h
@@ -0,0 +1,5 @@
+int kick_inmate_cell(void);
+int entry(unsigned int);
+void secondary_entry(void);
+extern void *__hyp_stub_vectors;
+extern unsigned long __cpu_id[];
diff --git a/bootloader/include/config.h b/bootloader/include/config.h
new file mode 100644
index 00000000..d815f71e
--- /dev/null
+++ b/bootloader/include/config.h
@@ -0,0 +1,5 @@
+#define MAX_CELL       16
+#define STRIDE_CELL    0x10000
+#define START_ADDR_CELL        0x40300000ULL
+#define JAILHOUSE_ADDR 0x40200000ULL
+#define KERNEL_ADDR    0x40480000ULL
diff --git a/bootloader/include/fls.h b/bootloader/include/fls.h
new file mode 100644
index 00000000..e170738d
--- /dev/null
+++ b/bootloader/include/fls.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS_FLS_H_
+
+/**
+ * fls - find last (most-significant) bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static int fls(unsigned int x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+
+#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
diff --git a/bootloader/include/linux/irqchip/arm-gic-common.h 
b/bootloader/include/linux/irqchip/arm-gic-common.h
new file mode 100644
index 00000000..e274ee6c
--- /dev/null
+++ b/bootloader/include/linux/irqchip/arm-gic-common.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * include/linux/irqchip/arm-gic-common.h
+ *
+ * Copyright (C) 2016 ARM Limited, All Rights Reserved.
+ */
+#ifndef __LINUX_IRQCHIP_ARM_GIC_COMMON_H
+#define __LINUX_IRQCHIP_ARM_GIC_COMMON_H
+
+#define GICD_INT_DEF_PRI               0xa0
+#define GICD_INT_DEF_PRI_X4            ((GICD_INT_DEF_PRI << 24) |\
+                                       (GICD_INT_DEF_PRI << 16) |\
+                                       (GICD_INT_DEF_PRI << 8) |\
+                                       GICD_INT_DEF_PRI)
+
+enum gic_type {
+       GIC_V2,
+       GIC_V3,
+};
+
+#endif /* __LINUX_IRQCHIP_ARM_GIC_COMMON_H */
diff --git a/bootloader/include/linux/irqchip/arm-gic-v3.h 
b/bootloader/include/linux/irqchip/arm-gic-v3.h
new file mode 100644
index 00000000..2a2ba056
--- /dev/null
+++ b/bootloader/include/linux/irqchip/arm-gic-v3.h
@@ -0,0 +1,674 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <[email protected]>
+ */
+#ifndef __LINUX_IRQCHIP_ARM_GIC_V3_H
+#define __LINUX_IRQCHIP_ARM_GIC_V3_H
+
+/*
+ * Distributor registers. We assume we're running non-secure, with ARE
+ * being set. Secure-only and non-ARE registers are not described.
+ */
+#define GICD_CTLR                      0x0000
+#define GICD_TYPER                     0x0004
+#define GICD_IIDR                      0x0008
+#define GICD_TYPER2                    0x000C
+#define GICD_STATUSR                   0x0010
+#define GICD_SETSPI_NSR                        0x0040
+#define GICD_CLRSPI_NSR                        0x0048
+#define GICD_SETSPI_SR                 0x0050
+#define GICD_CLRSPI_SR                 0x0058
+#define GICD_SEIR                      0x0068
+#define GICD_IGROUPR                   0x0080
+#define GICD_ISENABLER                 0x0100
+#define GICD_ICENABLER                 0x0180
+#define GICD_ISPENDR                   0x0200
+#define GICD_ICPENDR                   0x0280
+#define GICD_ISACTIVER                 0x0300
+#define GICD_ICACTIVER                 0x0380
+#define GICD_IPRIORITYR                        0x0400
+#define GICD_ICFGR                     0x0C00
+#define GICD_IGRPMODR                  0x0D00
+#define GICD_NSACR                     0x0E00
+#define GICD_IGROUPRnE                 0x1000
+#define GICD_ISENABLERnE               0x1200
+#define GICD_ICENABLERnE               0x1400
+#define GICD_ISPENDRnE                 0x1600
+#define GICD_ICPENDRnE                 0x1800
+#define GICD_ISACTIVERnE               0x1A00
+#define GICD_ICACTIVERnE               0x1C00
+#define GICD_IPRIORITYRnE              0x2000
+#define GICD_ICFGRnE                   0x3000
+#define GICD_IROUTER                   0x6000
+#define GICD_IROUTERnE                 0x8000
+#define GICD_IDREGS                    0xFFD0
+#define GICD_PIDR2                     0xFFE8
+
+#define ESPI_BASE_INTID                        4096
+
+/*
+ * Those registers are actually from GICv2, but the spec demands that they
+ * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
+ */
+#define GICD_ITARGETSR                 0x0800
+#define GICD_SGIR                      0x0F00
+#define GICD_CPENDSGIR                 0x0F10
+#define GICD_SPENDSGIR                 0x0F20
+
+#define GICD_CTLR_RWP                  (1U << 31)
+#define GICD_CTLR_nASSGIreq            (1U << 8)
+#define GICD_CTLR_DS                   (1U << 6)
+#define GICD_CTLR_ARE_NS               (1U << 4)
+#define GICD_CTLR_ENABLE_G1A           (1U << 1)
+#define GICD_CTLR_ENABLE_G1            (1U << 0)
+
+#define GICD_IIDR_IMPLEMENTER_SHIFT    0
+#define GICD_IIDR_IMPLEMENTER_MASK     (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT)
+#define GICD_IIDR_REVISION_SHIFT       12
+#define GICD_IIDR_REVISION_MASK                (0xf << 
GICD_IIDR_REVISION_SHIFT)
+#define GICD_IIDR_VARIANT_SHIFT                16
+#define GICD_IIDR_VARIANT_MASK         (0xf << GICD_IIDR_VARIANT_SHIFT)
+#define GICD_IIDR_PRODUCT_ID_SHIFT     24
+#define GICD_IIDR_PRODUCT_ID_MASK      (0xff << GICD_IIDR_PRODUCT_ID_SHIFT)
+
+
+/*
+ * In systems with a single security state (what we emulate in KVM)
+ * the meaning of the interrupt group enable bits is slightly different
+ */
+#define GICD_CTLR_ENABLE_SS_G1         (1U << 1)
+#define GICD_CTLR_ENABLE_SS_G0         (1U << 0)
+
+#define GICD_TYPER_RSS                 (1U << 26)
+#define GICD_TYPER_LPIS                        (1U << 17)
+#define GICD_TYPER_MBIS                        (1U << 16)
+#define GICD_TYPER_ESPI                        (1U << 8)
+
+#define GICD_TYPER_ID_BITS(typer)      ((((typer) >> 19) & 0x1f) + 1)
+#define GICD_TYPER_NUM_LPIS(typer)     ((((typer) >> 11) & 0x1f) + 1)
+#define GICD_TYPER_SPIS(typer)         ((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_ESPIS(typer)                                                
\
+       (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
+
+#define GICD_TYPER2_nASSGIcap          (1U << 8)
+#define GICD_TYPER2_VIL                        (1U << 7)
+#define GICD_TYPER2_VID                        GENMASK(4, 0)
+
+#define GICD_IROUTER_SPI_MODE_ONE      (0U << 31)
+#define GICD_IROUTER_SPI_MODE_ANY      (1U << 31)
+
+#define GIC_PIDR2_ARCH_MASK            0xf0
+#define GIC_PIDR2_ARCH_GICv3           0x30
+#define GIC_PIDR2_ARCH_GICv4           0x40
+
+#define GIC_V3_DIST_SIZE               0x10000
+
+#define GIC_PAGE_SIZE_4K               0ULL
+#define GIC_PAGE_SIZE_16K              1ULL
+#define GIC_PAGE_SIZE_64K              2ULL
+#define GIC_PAGE_SIZE_MASK             3ULL
+
+/*
+ * Re-Distributor registers, offsets from RD_base
+ */
+#define GICR_CTLR                      GICD_CTLR
+#define GICR_IIDR                      0x0004
+#define GICR_TYPER                     0x0008
+#define GICR_STATUSR                   GICD_STATUSR
+#define GICR_WAKER                     0x0014
+#define GICR_SETLPIR                   0x0040
+#define GICR_CLRLPIR                   0x0048
+#define GICR_SEIR                      GICD_SEIR
+#define GICR_PROPBASER                 0x0070
+#define GICR_PENDBASER                 0x0078
+#define GICR_INVLPIR                   0x00A0
+#define GICR_INVALLR                   0x00B0
+#define GICR_SYNCR                     0x00C0
+#define GICR_MOVLPIR                   0x0100
+#define GICR_MOVALLR                   0x0110
+#define GICR_IDREGS                    GICD_IDREGS
+#define GICR_PIDR2                     GICD_PIDR2
+
+#define GICR_CTLR_ENABLE_LPIS          (1UL << 0)
+#define GICR_CTLR_RWP                  (1UL << 3)
+
+#define GICR_TYPER_CPU_NUMBER(r)       (((r) >> 8) & 0xffff)
+
+#define EPPI_BASE_INTID                        1056
+
+#define GICR_TYPER_NR_PPIS(r)                                          \
+       ({                                                              \
+               unsigned int __ppinum = ((r) >> 27) & 0x1f;             \
+               unsigned int __nr_ppis = 16;                            \
+               if (__ppinum == 1 || __ppinum == 2)                     \
+                       __nr_ppis +=  __ppinum * 32;                    \
+                                                                       \
+               __nr_ppis;                                              \
+        })
+
+#define GICR_WAKER_ProcessorSleep      (1U << 1)
+#define GICR_WAKER_ChildrenAsleep      (1U << 2)
+
+#define GIC_BASER_CACHE_nCnB           0ULL
+#define GIC_BASER_CACHE_SameAsInner    0ULL
+#define GIC_BASER_CACHE_nC             1ULL
+#define GIC_BASER_CACHE_RaWt           2ULL
+#define GIC_BASER_CACHE_RaWb           3ULL
+#define GIC_BASER_CACHE_WaWt           4ULL
+#define GIC_BASER_CACHE_WaWb           5ULL
+#define GIC_BASER_CACHE_RaWaWt         6ULL
+#define GIC_BASER_CACHE_RaWaWb         7ULL
+#define GIC_BASER_CACHE_MASK           7ULL
+#define GIC_BASER_NonShareable         0ULL
+#define GIC_BASER_InnerShareable       1ULL
+#define GIC_BASER_OuterShareable       2ULL
+#define GIC_BASER_SHAREABILITY_MASK    3ULL
+
+#define GIC_BASER_CACHEABILITY(reg, inner_outer, type)                 \
+       (GIC_BASER_CACHE_##type << reg##_##inner_outer##_CACHEABILITY_SHIFT)
+
+#define GIC_BASER_SHAREABILITY(reg, type)                              \
+       (GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
+
+/* encode a size field of width @w containing @n - 1 units */
+#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 
0))
+
+#define GICR_PROPBASER_SHAREABILITY_SHIFT              (10)
+#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT                (7)
+#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT                (56)
+#define GICR_PROPBASER_SHAREABILITY_MASK                               \
+       GIC_BASER_SHAREABILITY(GICR_PROPBASER, SHAREABILITY_MASK)
+#define GICR_PROPBASER_INNER_CACHEABILITY_MASK                         \
+       GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, MASK)
+#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK                         \
+       GIC_BASER_CACHEABILITY(GICR_PROPBASER, OUTER, MASK)
+#define GICR_PROPBASER_CACHEABILITY_MASK GICR_PROPBASER_INNER_CACHEABILITY_MASK
+
+#define GICR_PROPBASER_InnerShareable                                  \
+       GIC_BASER_SHAREABILITY(GICR_PROPBASER, InnerShareable)
+
+#define GICR_PROPBASER_nCnB    GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
nCnB)
+#define GICR_PROPBASER_nC      GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
nC)
+#define GICR_PROPBASER_RaWt    GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWt)
+#define GICR_PROPBASER_RaWb    GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWb)
+#define GICR_PROPBASER_WaWt    GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
WaWt)
+#define GICR_PROPBASER_WaWb    GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
WaWb)
+#define GICR_PROPBASER_RaWaWt  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWaWt)
+#define GICR_PROPBASER_RaWaWb  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWaWb)
+
+#define GICR_PROPBASER_IDBITS_MASK                     (0x1f)
+#define GICR_PROPBASER_ADDRESS(x)      ((x) & GENMASK_ULL(51, 12))
+#define GICR_PENDBASER_ADDRESS(x)      ((x) & GENMASK_ULL(51, 16))
+
+#define GICR_PENDBASER_SHAREABILITY_SHIFT              (10)
+#define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT                (7)
+#define GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT                (56)
+#define GICR_PENDBASER_SHAREABILITY_MASK                               \
+       GIC_BASER_SHAREABILITY(GICR_PENDBASER, SHAREABILITY_MASK)
+#define GICR_PENDBASER_INNER_CACHEABILITY_MASK                         \
+       GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, MASK)
+#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK                         \
+       GIC_BASER_CACHEABILITY(GICR_PENDBASER, OUTER, MASK)
+#define GICR_PENDBASER_CACHEABILITY_MASK GICR_PENDBASER_INNER_CACHEABILITY_MASK
+
+#define GICR_PENDBASER_InnerShareable                                  \
+       GIC_BASER_SHAREABILITY(GICR_PENDBASER, InnerShareable)
+
+#define GICR_PENDBASER_nCnB    GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
nCnB)
+#define GICR_PENDBASER_nC      GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
nC)
+#define GICR_PENDBASER_RaWt    GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWt)
+#define GICR_PENDBASER_RaWb    GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWb)
+#define GICR_PENDBASER_WaWt    GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
WaWt)
+#define GICR_PENDBASER_WaWb    GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
WaWb)
+#define GICR_PENDBASER_RaWaWt  GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWaWt)
+#define GICR_PENDBASER_RaWaWb  GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWaWb)
+
+#define GICR_PENDBASER_PTZ                             BIT_ULL(62)
+
+/*
+ * Re-Distributor registers, offsets from SGI_base
+ */
+#define GICR_IGROUPR0                  GICD_IGROUPR
+#define GICR_ISENABLER0                        GICD_ISENABLER
+#define GICR_ICENABLER0                        GICD_ICENABLER
+#define GICR_ISPENDR0                  GICD_ISPENDR
+#define GICR_ICPENDR0                  GICD_ICPENDR
+#define GICR_ISACTIVER0                        GICD_ISACTIVER
+#define GICR_ICACTIVER0                        GICD_ICACTIVER
+#define GICR_IPRIORITYR0               GICD_IPRIORITYR
+#define GICR_ICFGR0                    GICD_ICFGR
+#define GICR_IGRPMODR0                 GICD_IGRPMODR
+#define GICR_NSACR                     GICD_NSACR
+
+#define GICR_TYPER_PLPIS               (1U << 0)
+#define GICR_TYPER_VLPIS               (1U << 1)
+#define GICR_TYPER_DIRTY               (1U << 2)
+#define GICR_TYPER_DirectLPIS          (1U << 3)
+#define GICR_TYPER_LAST                        (1U << 4)
+#define GICR_TYPER_RVPEID              (1U << 7)
+#define GICR_TYPER_COMMON_LPI_AFF      GENMASK_ULL(25, 24)
+#define GICR_TYPER_AFFINITY            GENMASK_ULL(63, 32)
+
+#define GICR_INVLPIR_INTID             GENMASK_ULL(31, 0)
+#define GICR_INVLPIR_VPEID             GENMASK_ULL(47, 32)
+#define GICR_INVLPIR_V                 GENMASK_ULL(63, 63)
+
+#define GICR_INVALLR_VPEID             GICR_INVLPIR_VPEID
+#define GICR_INVALLR_V                 GICR_INVLPIR_V
+
+#define GIC_V3_REDIST_SIZE             0x20000
+
+#define LPI_PROP_GROUP1                        (1 << 1)
+#define LPI_PROP_ENABLED               (1 << 0)
+
+/*
+ * Re-Distributor registers, offsets from VLPI_base
+ */
+#define GICR_VPROPBASER                        0x0070
+
+#define GICR_VPROPBASER_IDBITS_MASK    0x1f
+
+#define GICR_VPROPBASER_SHAREABILITY_SHIFT             (10)
+#define GICR_VPROPBASER_INNER_CACHEABILITY_SHIFT       (7)
+#define GICR_VPROPBASER_OUTER_CACHEABILITY_SHIFT       (56)
+
+#define GICR_VPROPBASER_SHAREABILITY_MASK                              \
+       GIC_BASER_SHAREABILITY(GICR_VPROPBASER, SHAREABILITY_MASK)
+#define GICR_VPROPBASER_INNER_CACHEABILITY_MASK                                
\
+       GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, MASK)
+#define GICR_VPROPBASER_OUTER_CACHEABILITY_MASK                                
\
+       GIC_BASER_CACHEABILITY(GICR_VPROPBASER, OUTER, MASK)
+#define GICR_VPROPBASER_CACHEABILITY_MASK                              \
+       GICR_VPROPBASER_INNER_CACHEABILITY_MASK
+
+#define GICR_VPROPBASER_InnerShareable                                 \
+       GIC_BASER_SHAREABILITY(GICR_VPROPBASER, InnerShareable)
+
+#define GICR_VPROPBASER_nCnB   GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
nCnB)
+#define GICR_VPROPBASER_nC     GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
nC)
+#define GICR_VPROPBASER_RaWt   GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
RaWt)
+#define GICR_VPROPBASER_RaWb   GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
RaWb)
+#define GICR_VPROPBASER_WaWt   GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
WaWt)
+#define GICR_VPROPBASER_WaWb   GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
WaWb)
+#define GICR_VPROPBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
RaWaWt)
+#define GICR_VPROPBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, 
RaWaWb)
+
+/*
+ * GICv4.1 VPROPBASER reinvention. A subtle mix between the old
+ * VPROPBASER and ITS_BASER. Just not quite any of the two.
+ */
+#define GICR_VPROPBASER_4_1_VALID      (1ULL << 63)
+#define GICR_VPROPBASER_4_1_ENTRY_SIZE GENMASK_ULL(61, 59)
+#define GICR_VPROPBASER_4_1_INDIRECT   (1ULL << 55)
+#define GICR_VPROPBASER_4_1_PAGE_SIZE  GENMASK_ULL(54, 53)
+#define GICR_VPROPBASER_4_1_Z          (1ULL << 52)
+#define GICR_VPROPBASER_4_1_ADDR       GENMASK_ULL(51, 12)
+#define GICR_VPROPBASER_4_1_SIZE       GENMASK_ULL(6, 0)
+
+#define GICR_VPENDBASER                        0x0078
+
+#define GICR_VPENDBASER_SHAREABILITY_SHIFT             (10)
+#define GICR_VPENDBASER_INNER_CACHEABILITY_SHIFT       (7)
+#define GICR_VPENDBASER_OUTER_CACHEABILITY_SHIFT       (56)
+#define GICR_VPENDBASER_SHAREABILITY_MASK                              \
+       GIC_BASER_SHAREABILITY(GICR_VPENDBASER, SHAREABILITY_MASK)
+#define GICR_VPENDBASER_INNER_CACHEABILITY_MASK                                
\
+       GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, MASK)
+#define GICR_VPENDBASER_OUTER_CACHEABILITY_MASK                                
\
+       GIC_BASER_CACHEABILITY(GICR_VPENDBASER, OUTER, MASK)
+#define GICR_VPENDBASER_CACHEABILITY_MASK                              \
+       GICR_VPENDBASER_INNER_CACHEABILITY_MASK
+
+#define GICR_VPENDBASER_NonShareable                                   \
+       GIC_BASER_SHAREABILITY(GICR_VPENDBASER, NonShareable)
+
+#define GICR_VPENDBASER_InnerShareable                                 \
+       GIC_BASER_SHAREABILITY(GICR_VPENDBASER, InnerShareable)
+
+#define GICR_VPENDBASER_nCnB   GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
nCnB)
+#define GICR_VPENDBASER_nC     GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
nC)
+#define GICR_VPENDBASER_RaWt   GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
RaWt)
+#define GICR_VPENDBASER_RaWb   GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
RaWb)
+#define GICR_VPENDBASER_WaWt   GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
WaWt)
+#define GICR_VPENDBASER_WaWb   GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
WaWb)
+#define GICR_VPENDBASER_RaWaWt GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
RaWaWt)
+#define GICR_VPENDBASER_RaWaWb GIC_BASER_CACHEABILITY(GICR_VPENDBASER, INNER, 
RaWaWb)
+
+#define GICR_VPENDBASER_Dirty          (1ULL << 60)
+#define GICR_VPENDBASER_PendingLast    (1ULL << 61)
+#define GICR_VPENDBASER_IDAI           (1ULL << 62)
+#define GICR_VPENDBASER_Valid          (1ULL << 63)
+
+/*
+ * GICv4.1 VPENDBASER, used for VPE residency. On top of these fields,
+ * also use the above Valid, PendingLast and Dirty.
+ */
+#define GICR_VPENDBASER_4_1_DB         (1ULL << 62)
+#define GICR_VPENDBASER_4_1_VGRP0EN    (1ULL << 59)
+#define GICR_VPENDBASER_4_1_VGRP1EN    (1ULL << 58)
+#define GICR_VPENDBASER_4_1_VPEID      GENMASK_ULL(15, 0)
+
+#define GICR_VSGIR                     0x0080
+
+#define GICR_VSGIR_VPEID               GENMASK(15, 0)
+
+#define GICR_VSGIPENDR                 0x0088
+
+#define GICR_VSGIPENDR_BUSY            (1U << 31)
+#define GICR_VSGIPENDR_PENDING         GENMASK(15, 0)
+
+/*
+ * ITS registers, offsets from ITS_base
+ */
+#define GITS_CTLR                      0x0000
+#define GITS_IIDR                      0x0004
+#define GITS_TYPER                     0x0008
+#define GITS_MPIDR                     0x0018
+#define GITS_CBASER                    0x0080
+#define GITS_CWRITER                   0x0088
+#define GITS_CREADR                    0x0090
+#define GITS_BASER                     0x0100
+#define GITS_IDREGS_BASE               0xffd0
+#define GITS_PIDR0                     0xffe0
+#define GITS_PIDR1                     0xffe4
+#define GITS_PIDR2                     GICR_PIDR2
+#define GITS_PIDR4                     0xffd0
+#define GITS_CIDR0                     0xfff0
+#define GITS_CIDR1                     0xfff4
+#define GITS_CIDR2                     0xfff8
+#define GITS_CIDR3                     0xfffc
+
+#define GITS_TRANSLATER                        0x10040
+
+#define GITS_SGIR                      0x20020
+
+#define GITS_SGIR_VPEID                        GENMASK_ULL(47, 32)
+#define GITS_SGIR_VINTID               GENMASK_ULL(3, 0)
+
+#define GITS_CTLR_ENABLE               (1U << 0)
+#define GITS_CTLR_ImDe                 (1U << 1)
+#define        GITS_CTLR_ITS_NUMBER_SHIFT      4
+#define        GITS_CTLR_ITS_NUMBER            (0xFU << 
GITS_CTLR_ITS_NUMBER_SHIFT)
+#define GITS_CTLR_QUIESCENT            (1U << 31)
+
+#define GITS_TYPER_PLPIS               (1UL << 0)
+#define GITS_TYPER_VLPIS               (1UL << 1)
+#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT        4
+#define GITS_TYPER_ITT_ENTRY_SIZE      GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS_SHIFT                8
+#define GITS_TYPER_DEVBITS_SHIFT       13
+#define GITS_TYPER_DEVBITS             GENMASK_ULL(17, 13)
+#define GITS_TYPER_PTA                 (1UL << 19)
+#define GITS_TYPER_HCC_SHIFT           24
+#define GITS_TYPER_HCC(r)              (((r) >> GITS_TYPER_HCC_SHIFT) & 0xff)
+#define GITS_TYPER_VMOVP               (1ULL << 37)
+#define GITS_TYPER_VMAPP               (1ULL << 40)
+#define GITS_TYPER_SVPET               GENMASK_ULL(42, 41)
+
+#define GITS_IIDR_REV_SHIFT            12
+#define GITS_IIDR_REV_MASK             (0xf << GITS_IIDR_REV_SHIFT)
+#define GITS_IIDR_REV(r)               (((r) >> GITS_IIDR_REV_SHIFT) & 0xf)
+#define GITS_IIDR_PRODUCTID_SHIFT      24
+
+#define GITS_CBASER_VALID                      (1ULL << 63)
+#define GITS_CBASER_SHAREABILITY_SHIFT         (10)
+#define GITS_CBASER_INNER_CACHEABILITY_SHIFT   (59)
+#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT   (53)
+#define GITS_CBASER_SHAREABILITY_MASK                                  \
+       GIC_BASER_SHAREABILITY(GITS_CBASER, SHAREABILITY_MASK)
+#define GITS_CBASER_INNER_CACHEABILITY_MASK                            \
+       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, MASK)
+#define GITS_CBASER_OUTER_CACHEABILITY_MASK                            \
+       GIC_BASER_CACHEABILITY(GITS_CBASER, OUTER, MASK)
+#define GITS_CBASER_CACHEABILITY_MASK GITS_CBASER_INNER_CACHEABILITY_MASK
+
+#define GITS_CBASER_InnerShareable                                     \
+       GIC_BASER_SHAREABILITY(GITS_CBASER, InnerShareable)
+
+#define GITS_CBASER_nCnB       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB)
+#define GITS_CBASER_nC         GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
+#define GITS_CBASER_RaWt       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
+#define GITS_CBASER_RaWb       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWb)
+#define GITS_CBASER_WaWt       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
+#define GITS_CBASER_WaWb       GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
+#define GITS_CBASER_RaWaWt     GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, 
RaWaWt)
+#define GITS_CBASER_RaWaWb     GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, 
RaWaWb)
+
+#define GITS_CBASER_ADDRESS(cbaser)    ((cbaser) & GENMASK_ULL(51, 12))
+
+#define GITS_BASER_NR_REGS             8
+
+#define GITS_BASER_VALID                       (1ULL << 63)
+#define GITS_BASER_INDIRECT                    (1ULL << 62)
+
+#define GITS_BASER_INNER_CACHEABILITY_SHIFT    (59)
+#define GITS_BASER_OUTER_CACHEABILITY_SHIFT    (53)
+#define GITS_BASER_INNER_CACHEABILITY_MASK                             \
+       GIC_BASER_CACHEABILITY(GITS_BASER, INNER, MASK)
+#define GITS_BASER_CACHEABILITY_MASK           
GITS_BASER_INNER_CACHEABILITY_MASK
+#define GITS_BASER_OUTER_CACHEABILITY_MASK                             \
+       GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, MASK)
+#define GITS_BASER_SHAREABILITY_MASK                                   \
+       GIC_BASER_SHAREABILITY(GITS_BASER, SHAREABILITY_MASK)
+
+#define GITS_BASER_nCnB                GIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, nCnB)
+#define GITS_BASER_nC          GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
+#define GITS_BASER_RaWt                GIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, RaWt)
+#define GITS_BASER_RaWb                GIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, RaWb)
+#define GITS_BASER_WaWt                GIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, WaWt)
+#define GITS_BASER_WaWb                GIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, WaWb)
+#define GITS_BASER_RaWaWt      GIC_BASER_CACHEABILITY(GITS_BASER, INNER, 
RaWaWt)
+#define GITS_BASER_RaWaWb      GIC_BASER_CACHEABILITY(GITS_BASER, INNER, 
RaWaWb)
+
+#define GITS_BASER_TYPE_SHIFT                  (56)
+#define GITS_BASER_TYPE(r)             (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
+#define GITS_BASER_ENTRY_SIZE_SHIFT            (48)
+#define GITS_BASER_ENTRY_SIZE(r)       ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) 
& 0x1f) + 1)
+#define GITS_BASER_ENTRY_SIZE_MASK     GENMASK_ULL(52, 48)
+#define GITS_BASER_PHYS_52_to_48(phys)                                 \
+       (((phys) & GENMASK_ULL(47, 16)) | (((phys) >> 48) & 0xf) << 12)
+#define GITS_BASER_ADDR_48_to_52(baser)                                        
\
+       (((baser) & GENMASK_ULL(47, 16)) | (((baser) >> 12) & 0xf) << 48)
+
+#define GITS_BASER_SHAREABILITY_SHIFT  (10)
+#define GITS_BASER_InnerShareable                                      \
+       GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
+#define GITS_BASER_PAGE_SIZE_SHIFT     (8)
+#define __GITS_BASER_PSZ(sz)           (GIC_PAGE_SIZE_ ## sz << 
GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_4K                __GITS_BASER_PSZ(4K)
+#define GITS_BASER_PAGE_SIZE_16K       __GITS_BASER_PSZ(16K)
+#define GITS_BASER_PAGE_SIZE_64K       __GITS_BASER_PSZ(64K)
+#define GITS_BASER_PAGE_SIZE_MASK      __GITS_BASER_PSZ(MASK)
+#define GITS_BASER_PAGES_MAX           256
+#define GITS_BASER_PAGES_SHIFT         (0)
+#define GITS_BASER_NR_PAGES(r)         (((r) & 0xff) + 1)
+
+#define GITS_BASER_TYPE_NONE           0
+#define GITS_BASER_TYPE_DEVICE         1
+#define GITS_BASER_TYPE_VCPU           2
+#define GITS_BASER_TYPE_RESERVED3      3
+#define GITS_BASER_TYPE_COLLECTION     4
+#define GITS_BASER_TYPE_RESERVED5      5
+#define GITS_BASER_TYPE_RESERVED6      6
+#define GITS_BASER_TYPE_RESERVED7      7
+
+#define GITS_LVL1_ENTRY_SIZE           (8UL)
+
+/*
+ * ITS commands
+ */
+#define GITS_CMD_MAPD                  0x08
+#define GITS_CMD_MAPC                  0x09
+#define GITS_CMD_MAPTI                 0x0a
+#define GITS_CMD_MAPI                  0x0b
+#define GITS_CMD_MOVI                  0x01
+#define GITS_CMD_DISCARD               0x0f
+#define GITS_CMD_INV                   0x0c
+#define GITS_CMD_MOVALL                        0x0e
+#define GITS_CMD_INVALL                        0x0d
+#define GITS_CMD_INT                   0x03
+#define GITS_CMD_CLEAR                 0x04
+#define GITS_CMD_SYNC                  0x05
+
+/*
+ * GICv4 ITS specific commands
+ */
+#define GITS_CMD_GICv4(x)              ((x) | 0x20)
+#define GITS_CMD_VINVALL               GITS_CMD_GICv4(GITS_CMD_INVALL)
+#define GITS_CMD_VMAPP                 GITS_CMD_GICv4(GITS_CMD_MAPC)
+#define GITS_CMD_VMAPTI                        GITS_CMD_GICv4(GITS_CMD_MAPTI)
+#define GITS_CMD_VMOVI                 GITS_CMD_GICv4(GITS_CMD_MOVI)
+#define GITS_CMD_VSYNC                 GITS_CMD_GICv4(GITS_CMD_SYNC)
+/* VMOVP, VSGI and INVDB are the odd ones, as they dont have a physical 
counterpart */
+#define GITS_CMD_VMOVP                 GITS_CMD_GICv4(2)
+#define GITS_CMD_VSGI                  GITS_CMD_GICv4(3)
+#define GITS_CMD_INVDB                 GITS_CMD_GICv4(0xe)
+
+/*
+ * ITS error numbers
+ */
+#define E_ITS_MOVI_UNMAPPED_INTERRUPT          0x010107
+#define E_ITS_MOVI_UNMAPPED_COLLECTION         0x010109
+#define E_ITS_INT_UNMAPPED_INTERRUPT           0x010307
+#define E_ITS_CLEAR_UNMAPPED_INTERRUPT         0x010507
+#define E_ITS_MAPD_DEVICE_OOR                  0x010801
+#define E_ITS_MAPD_ITTSIZE_OOR                 0x010802
+#define E_ITS_MAPC_PROCNUM_OOR                 0x010902
+#define E_ITS_MAPC_COLLECTION_OOR              0x010903
+#define E_ITS_MAPTI_UNMAPPED_DEVICE            0x010a04
+#define E_ITS_MAPTI_ID_OOR                     0x010a05
+#define E_ITS_MAPTI_PHYSICALID_OOR             0x010a06
+#define E_ITS_INV_UNMAPPED_INTERRUPT           0x010c07
+#define E_ITS_INVALL_UNMAPPED_COLLECTION       0x010d09
+#define E_ITS_MOVALL_PROCNUM_OOR               0x010e01
+#define E_ITS_DISCARD_UNMAPPED_INTERRUPT       0x010f07
+
+/*
+ * CPU interface registers
+ */
+#define ICC_CTLR_EL1_EOImode_SHIFT     (1)
+#define ICC_CTLR_EL1_EOImode_drop_dir  (0U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_drop      (1U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_MASK      (1 << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_CBPR_SHIFT                0
+#define ICC_CTLR_EL1_CBPR_MASK         (1 << ICC_CTLR_EL1_CBPR_SHIFT)
+#define ICC_CTLR_EL1_PMHE_SHIFT                6
+#define ICC_CTLR_EL1_PMHE_MASK         (1 << ICC_CTLR_EL1_PMHE_SHIFT)
+#define ICC_CTLR_EL1_PRI_BITS_SHIFT    8
+#define ICC_CTLR_EL1_PRI_BITS_MASK     (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
+#define ICC_CTLR_EL1_ID_BITS_SHIFT     11
+#define ICC_CTLR_EL1_ID_BITS_MASK      (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
+#define ICC_CTLR_EL1_SEIS_SHIFT                14
+#define ICC_CTLR_EL1_SEIS_MASK         (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
+#define ICC_CTLR_EL1_A3V_SHIFT         15
+#define ICC_CTLR_EL1_A3V_MASK          (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
+#define ICC_CTLR_EL1_RSS               (0x1 << 18)
+#define ICC_CTLR_EL1_ExtRange          (0x1 << 19)
+#define ICC_PMR_EL1_SHIFT              0
+#define ICC_PMR_EL1_MASK               (0xff << ICC_PMR_EL1_SHIFT)
+#define ICC_BPR0_EL1_SHIFT             0
+#define ICC_BPR0_EL1_MASK              (0x7 << ICC_BPR0_EL1_SHIFT)
+#define ICC_BPR1_EL1_SHIFT             0
+#define ICC_BPR1_EL1_MASK              (0x7 << ICC_BPR1_EL1_SHIFT)
+#define ICC_IGRPEN0_EL1_SHIFT          0
+#define ICC_IGRPEN0_EL1_MASK           (1 << ICC_IGRPEN0_EL1_SHIFT)
+#define ICC_IGRPEN1_EL1_SHIFT          0
+#define ICC_IGRPEN1_EL1_MASK           (1 << ICC_IGRPEN1_EL1_SHIFT)
+#define ICC_SRE_EL1_DIB                        (1U << 2)
+#define ICC_SRE_EL1_DFB                        (1U << 1)
+#define ICC_SRE_EL1_SRE                        (1U << 0)
+
+/*
+ * Hypervisor interface registers (SRE only)
+ */
+#define ICH_LR_VIRTUAL_ID_MASK         ((1ULL << 32) - 1)
+
+#define ICH_LR_EOI                     (1ULL << 41)
+#define ICH_LR_GROUP                   (1ULL << 60)
+#define ICH_LR_HW                      (1ULL << 61)
+#define ICH_LR_STATE                   (3ULL << 62)
+#define ICH_LR_PENDING_BIT             (1ULL << 62)
+#define ICH_LR_ACTIVE_BIT              (1ULL << 63)
+#define ICH_LR_PHYS_ID_SHIFT           32
+#define ICH_LR_PHYS_ID_MASK            (0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT          48
+#define ICH_LR_PRIORITY_MASK           (0xffULL << ICH_LR_PRIORITY_SHIFT)
+
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID              (0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT     (10)
+#define GICH_LR_PHYSID_CPUID           (7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
+#define ICH_MISR_EOI                   (1 << 0)
+#define ICH_MISR_U                     (1 << 1)
+
+#define ICH_HCR_EN                     (1 << 0)
+#define ICH_HCR_UIE                    (1 << 1)
+#define ICH_HCR_NPIE                   (1 << 3)
+#define ICH_HCR_TC                     (1 << 10)
+#define ICH_HCR_TALL0                  (1 << 11)
+#define ICH_HCR_TALL1                  (1 << 12)
+#define ICH_HCR_EOIcount_SHIFT         27
+#define ICH_HCR_EOIcount_MASK          (0x1f << ICH_HCR_EOIcount_SHIFT)
+
+#define ICH_VMCR_ACK_CTL_SHIFT         2
+#define ICH_VMCR_ACK_CTL_MASK          (1 << ICH_VMCR_ACK_CTL_SHIFT)
+#define ICH_VMCR_FIQ_EN_SHIFT          3
+#define ICH_VMCR_FIQ_EN_MASK           (1 << ICH_VMCR_FIQ_EN_SHIFT)
+#define ICH_VMCR_CBPR_SHIFT            4
+#define ICH_VMCR_CBPR_MASK             (1 << ICH_VMCR_CBPR_SHIFT)
+#define ICH_VMCR_EOIM_SHIFT            9
+#define ICH_VMCR_EOIM_MASK             (1 << ICH_VMCR_EOIM_SHIFT)
+#define ICH_VMCR_BPR1_SHIFT            18
+#define ICH_VMCR_BPR1_MASK             (7 << ICH_VMCR_BPR1_SHIFT)
+#define ICH_VMCR_BPR0_SHIFT            21
+#define ICH_VMCR_BPR0_MASK             (7 << ICH_VMCR_BPR0_SHIFT)
+#define ICH_VMCR_PMR_SHIFT             24
+#define ICH_VMCR_PMR_MASK              (0xffUL << ICH_VMCR_PMR_SHIFT)
+#define ICH_VMCR_ENG0_SHIFT            0
+#define ICH_VMCR_ENG0_MASK             (1 << ICH_VMCR_ENG0_SHIFT)
+#define ICH_VMCR_ENG1_SHIFT            1
+#define ICH_VMCR_ENG1_MASK             (1 << ICH_VMCR_ENG1_SHIFT)
+
+#define ICH_VTR_PRI_BITS_SHIFT         29
+#define ICH_VTR_PRI_BITS_MASK          (7 << ICH_VTR_PRI_BITS_SHIFT)
+#define ICH_VTR_ID_BITS_SHIFT          23
+#define ICH_VTR_ID_BITS_MASK           (7 << ICH_VTR_ID_BITS_SHIFT)
+#define ICH_VTR_SEIS_SHIFT             22
+#define ICH_VTR_SEIS_MASK              (1 << ICH_VTR_SEIS_SHIFT)
+#define ICH_VTR_A3V_SHIFT              21
+#define ICH_VTR_A3V_MASK               (1 << ICH_VTR_A3V_SHIFT)
+
+#define ICC_IAR1_EL1_SPURIOUS          0x3ff
+
+#define ICC_SRE_EL2_SRE                        (1 << 0)
+#define ICC_SRE_EL2_ENABLE             (1 << 3)
+
+#define ICC_SGI1R_TARGET_LIST_SHIFT    0
+#define ICC_SGI1R_TARGET_LIST_MASK     (0xffff << ICC_SGI1R_TARGET_LIST_SHIFT)
+#define ICC_SGI1R_AFFINITY_1_SHIFT     16
+#define ICC_SGI1R_AFFINITY_1_MASK      (0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
+#define ICC_SGI1R_SGI_ID_SHIFT         24
+#define ICC_SGI1R_SGI_ID_MASK          (0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
+#define ICC_SGI1R_AFFINITY_2_SHIFT     32
+#define ICC_SGI1R_AFFINITY_2_MASK      (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT)
+#define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40
+#define ICC_SGI1R_RS_SHIFT             44
+#define ICC_SGI1R_RS_MASK              (0xfULL << ICC_SGI1R_RS_SHIFT)
+#define ICC_SGI1R_AFFINITY_3_SHIFT     48
+#define ICC_SGI1R_AFFINITY_3_MASK      (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT)
+
+#include <asm/arch_gicv3.h>
+
+#ifndef __ASSEMBLY__
+
+/*
+ * We need a value to serve as a irq-type for LPIs. Choose one that will
+ * hopefully pique the interest of the reviewer.
+ */
+#define GIC_IRQ_TYPE_LPI               0xa110c8ed
+
+#endif
+
+#endif
diff --git a/bootloader/include/linux/irqchip/arm-gic.h 
b/bootloader/include/linux/irqchip/arm-gic.h
new file mode 100644
index 00000000..df0394ae
--- /dev/null
+++ b/bootloader/include/linux/irqchip/arm-gic.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ *  include/linux/irqchip/arm-gic.h
+ *
+ *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
+ */
+#ifndef __LINUX_IRQCHIP_ARM_GIC_H
+#define __LINUX_IRQCHIP_ARM_GIC_H
+
+#define GIC_DIST_CTRL                  0x000
+#define GIC_DIST_CTR                   0x004
+#define GIC_DIST_IIDR                  0x008
+#define GIC_DIST_IGROUP                        0x080
+#define GIC_DIST_ENABLE_SET            0x100
+#define GIC_DIST_ENABLE_CLEAR          0x180
+#define GIC_DIST_PENDING_SET           0x200
+#define GIC_DIST_PENDING_CLEAR         0x280
+#define GIC_DIST_ACTIVE_SET            0x300
+#define GIC_DIST_ACTIVE_CLEAR          0x380
+#define GIC_DIST_PRI                   0x400
+#define GIC_DIST_TARGET                        0x800
+#define GIC_DIST_CONFIG                        0xc00
+#define GIC_DIST_SOFTINT               0xf00
+#define GIC_DIST_SGI_PENDING_CLEAR     0xf10
+#define GIC_DIST_SGI_PENDING_SET       0xf20
+
+#define GICD_ENABLE                    0x1
+#define GICD_DISABLE                   0x0
+#define GICD_INT_ACTLOW_LVLTRIG                0x0
+#define GICD_INT_EN_CLR_X32            0xffffffff
+#define GICD_INT_EN_SET_SGI            0x0000ffff
+#define GICD_INT_EN_CLR_PPI            0xffff0000
+
+#endif
diff --git a/bootloader/loader.lds b/bootloader/loader.lds
new file mode 100644
index 00000000..fccc7910
--- /dev/null
+++ b/bootloader/loader.lds
@@ -0,0 +1,22 @@
+SECTIONS
+{
+ . = 0x40000000;
+ .header : { *(.header) }
+ . = ALIGN(16);
+ .text : {
+  __text_start = .;
+  *(.text)
+ }
+ . = ALIGN(16);
+ .rodata : { *(.rodata) }
+ . = ALIGN(16);
+ .data : { *(.data) }
+ . = ALIGN((1 << 12));
+ __cpu_id = .;
+ . += 0x400;
+ __bss_start = .;
+ .bss : { *(.bss*) }
+ . = ALIGN(16);
+ __stack_pool = .;
+ .eh_frame : { *(.eh_frame*) }
+}
diff --git a/hypervisor/arch/arm-common/include/asm/psci.h 
b/hypervisor/arch/arm-common/include/asm/psci.h
index 4b724877..0b400771 100644
--- a/hypervisor/arch/arm-common/include/asm/psci.h
+++ b/hypervisor/arch/arm-common/include/asm/psci.h
@@ -31,6 +31,16 @@
 #define PSCI_CPU_OFF_V0_1_UBOOT                0x95c1ba5f
 #define PSCI_CPU_ON_V0_1_UBOOT         0x95c1ba60
 
+/* PSCI v0.2 power state encoding for CPU_SUSPEND function */
+#define PSCI_POWER_STATE_TYPE_POWER_DOWN        1
+
+#define PSCI_0_2_POWER_STATE_ID_MASK           0xffff
+#define PSCI_0_2_POWER_STATE_ID_SHIFT          0
+#define PSCI_0_2_POWER_STATE_TYPE_SHIFT                16
+#define PSCI_0_2_POWER_STATE_TYPE_MASK         (0x1 << 
PSCI_0_2_POWER_STATE_TYPE_SHIFT)
+#define PSCI_0_2_POWER_STATE_AFFL_SHIFT                24
+#define PSCI_0_2_POWER_STATE_AFFL_MASK         (0x3 << 
PSCI_0_2_POWER_STATE_AFFL_SHIFT)
+
 #define PSCI_SUCCESS                   0
 #define PSCI_NOT_SUPPORTED             (-1)
 #define PSCI_INVALID_PARAMETERS                (-2)
diff --git a/hypervisor/arch/arm64/include/asm/sysregs.h 
b/hypervisor/arch/arm64/include/asm/sysregs.h
index a7370373..597b643d 100644
--- a/hypervisor/arch/arm64/include/asm/sysregs.h
+++ b/hypervisor/arch/arm64/include/asm/sysregs.h
@@ -68,6 +68,8 @@
 #define SCTLR_EL2_RES1 ((3 << 4) | (1 << 11) | (1 << 16) | (1 << 18)   \
                        | (3 << 22) | (3 << 28))
 
+#define HCR_APK_BIT    (1uL << 40)
+#define HCR_API_BIT    (1uL << 41)
 #define HCR_MIOCNCE_BIT        (1u << 38)
 #define HCR_ID_BIT     (1u << 33)
 #define HCR_CD_BIT     (1u << 32)
@@ -106,6 +108,8 @@
 #define HCR_SWIO_BIT   (1u << 1)
 #define HCR_VM_BIT     (1u << 0)
 
+#define HCR_HOST_NVHE_FLAGS (HCR_RW_BIT | HCR_API_BIT | HCR_APK_BIT)
+
 /* exception class */
 #define ESR_EC_SHIFT           (26)
 #define ESR_EC(esr)            GET_FIELD((esr), 31, ESR_EC_SHIFT)
@@ -159,6 +163,15 @@
 /* exception level in SPSR_ELx */
 #define SPSR_EL(spsr)          (((spsr) & 0xc) >> 2)
 
+#define CurrentEL_EL2          (2 << 2)
+#define CPTR_EL2_TZ            (1 << 8)
+#define ZCR_ELx_LEN_MASK       0x1ff
+
+#define ID_AA64PFR0_GIC_SHIFT           24
+#define ID_AA64PFR0_SVE_SHIFT          32
+
+#define SYS_ZCR_EL2                    S3_4_C1_C2_0
+
 #ifndef __ASSEMBLY__
 
 #include <jailhouse/string.h>
-- 
2.16.4

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20200807030632.28259-10-peng.fan%40nxp.com.

Reply via email to