[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] Merge branch 'arm-next' into staging



=== This changeset includes merge from high-traffic branch ===
Commits on that branch are not reported individually.

commit 65a2c12576a73b67c80a1b4eceff1fa9a4ffa050
Merge: b4ac4bc410222d221dc46a74ac71efaa7b32d57c 
302ba0cee8171ee7c12f100f92e122f269d9f0a7
Author:     Julien Grall <julien.grall@xxxxxxx>
AuthorDate: Wed Jul 4 11:46:11 2018 +0100
Commit:     Julien Grall <julien.grall@xxxxxxx>
CommitDate: Wed Jul 4 11:46:11 2018 +0100

    Merge branch 'arm-next' into staging
 docs/misc/xen-command-line.markdown      |  18 ++
 xen/arch/arm/Kconfig                     |  46 ++---
 xen/arch/arm/alternative.c               |  86 +++++-----
 xen/arch/arm/arm64/asm-offsets.c         |   2 +
 xen/arch/arm/arm64/entry.S               |  48 +++++-
 xen/arch/arm/arm64/smpboot.c             |   2 +-
 xen/arch/arm/arm64/vsysreg.c             |   4 +-
 xen/arch/arm/cpuerrata.c                 | 199 ++++++++++++++++++++++
 xen/arch/arm/cpufeature.c                |  29 ++++
 xen/arch/arm/domain.c                    |   9 +
 xen/arch/arm/gic-vgic.c                  |   2 +-
 xen/arch/arm/gic.c                       |  31 ++++
 xen/arch/arm/irq.c                       |   2 +-
 xen/arch/arm/p2m.c                       |  53 +++++-
 xen/arch/arm/platforms/vexpress.c        |  35 ----
 xen/arch/arm/processor.c                 |   2 +-
 xen/arch/arm/psci.c                      |  13 ++
 xen/arch/arm/setup.c                     |   8 +-
 xen/arch/arm/smpboot.c                   |  42 ++++-
 xen/arch/arm/time.c                      |  45 +++++
 xen/arch/arm/traps.c                     |  58 +++++--
 xen/arch/arm/vgic-v2.c                   |   2 +
 xen/arch/arm/vsmc.c                      |  37 ++++
 xen/common/schedule.c                    |   4 +
 xen/drivers/video/Kconfig                |   3 -
 xen/drivers/video/Makefile               |   1 -
 xen/drivers/video/arm_hdlcd.c            | 281 -------------------------------
 xen/include/asm-arm/alternative.h        |  44 ++++-
 xen/include/asm-arm/arm64/macros.h       |  25 +++
 xen/include/asm-arm/cpuerrata.h          |  42 +++++
 xen/include/asm-arm/cpufeature.h         |   4 +-
 xen/include/asm-arm/current.h            |   6 +-
 xen/include/asm-arm/macros.h             |   2 +-
 xen/include/asm-arm/platforms/vexpress.h |   6 -
 xen/include/asm-arm/procinfo.h           |   4 +-
 xen/include/asm-arm/psci.h               |   1 +
 xen/include/asm-arm/smccc.h              |  13 +-
 xen/include/asm-arm/traps.h              |   4 +
 38 files changed, 785 insertions(+), 428 deletions(-)

diff --git a/docs/misc/xen-command-line.markdown 
b/docs/misc/xen-command-line.markdown
index ff8c7d4c2f..8a832c0f8b 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1758,6 +1758,24 @@ enforces the maximum theoretically necessary timeout of 
670ms. Any number
 is being interpreted as a custom timeout in milliseconds. Zero or boolean
 false disable the quirk workaround, which is also the default.
 
+### spec-ctrl (Arm)
+> `= List of [ ssbd=force-disable|runtime|force-enable ]`
+
+Controls for speculative execution sidechannel mitigations.
+
+The option `ssbd=` is used to control the state of Speculative Store
+Bypass Disable (SSBD) mitigation.
+
+* `ssbd=force-disable` will keep the mitigation permanently off. The guest
+will not be able to control the state of the mitigation.
+* `ssbd=runtime` will always turn on the mitigation when running in the
+hypervisor context. The guest will be to turn on/off the mitigation for
+itself by using the firmware interface ARCH\_WORKAROUND\_2.
+* `ssbd=force-enable` will keep the mitigation permanently on. The guest will
+not be able to control the state of the mitigation.
+
+By default SSBD will be mitigated at runtime (i.e `ssbd=runtime`).
+
 ### spec-ctrl (x86)
 > `= List of [ <bool>, xen=<bool>, {pv,hvm,msr-sc,rsb}=<bool>,
 >              bti-thunk=retpoline|lfence|jmp, 
 > {ibrs,ibpb,ssbd,eager-fpu}=<bool> ]`
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 8174c0c635..06ba4a4d6e 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -17,12 +17,10 @@ config ARM_64
 config ARM
        def_bool y
        select HAS_ALTERNATIVE
-       select HAS_ARM_HDLCD
        select HAS_DEVICE_TREE
        select HAS_MEM_ACCESS
        select HAS_PASSTHROUGH
        select HAS_PDX
-       select VIDEO
 
 config ARCH_DEFCONFIG
        string
@@ -73,6 +71,33 @@ config SBSA_VUART_CONSOLE
          Allows a guest to use SBSA Generic UART as a console. The
          SBSA Generic UART implements a subset of ARM PL011 UART.
 
+config ARM_SSBD
+       bool "Speculative Store Bypass Disable" if EXPERT = "y"
+       depends on HAS_ALTERNATIVE
+       default y
+       help
+         This enables mitigation of bypassing of previous stores by speculative
+         loads.
+
+         If unsure, say Y.
+
+config HARDEN_BRANCH_PREDICTOR
+       bool "Harden the branch predictor against aliasing attacks" if EXPERT = 
"y"
+       default y
+       help
+         Speculation attacks against some high-performance processors rely on
+         being able to manipulate the branch predictor for a victim context by
+         executing aliasing branches in the attacker context.  Such attacks
+         can be partially mitigated against by clearing internal branch
+         predictor state and limiting the prediction logic in some situations.
+
+         This config option will take CPU-specific actions to harden the
+         branch predictor against aliasing attacks and may rely on specific
+         instruction sequences or control bits being set by the system
+         firmware.
+
+         If unsure, say Y.
+
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
@@ -187,23 +212,6 @@ config ARM64_ERRATUM_834220
 
 endmenu
 
-config HARDEN_BRANCH_PREDICTOR
-       bool "Harden the branch predictor against aliasing attacks" if EXPERT
-       default y
-       help
-         Speculation attacks against some high-performance processors rely on
-         being able to manipulate the branch predictor for a victim context by
-         executing aliasing branches in the attacker context.  Such attacks
-         can be partially mitigated against by clearing internal branch
-         predictor state and limiting the prediction logic in some situations.
-
-         This config option will take CPU-specific actions to harden the
-         branch predictor against aliasing attacks and may rely on specific
-         instruction sequences or control bits being set by the system
-         firmware.
-
-         If unsure, say Y.
-
 config ARM64_HARDEN_BRANCH_PREDICTOR
     def_bool y if ARM_64 && HARDEN_BRANCH_PREDICTOR
 
diff --git a/xen/arch/arm/alternative.c b/xen/arch/arm/alternative.c
index 9ffdc475d6..52ed7edf69 100644
--- a/xen/arch/arm/alternative.c
+++ b/xen/arch/arm/alternative.c
@@ -30,6 +30,8 @@
 #include <asm/byteorder.h>
 #include <asm/cpufeature.h>
 #include <asm/insn.h>
+/* XXX: Move ARCH_PATCH_INSN_SIZE out of livepatch.h */
+#include <asm/livepatch.h>
 #include <asm/page.h>
 
 /* Override macros from asm/page.h to make them work with mfn_t */
@@ -94,39 +96,66 @@ static u32 get_alt_insn(const struct alt_instr *alt,
     return insn;
 }
 
+static void patch_alternative(const struct alt_instr *alt,
+                              const uint32_t *origptr,
+                              uint32_t *updptr, int nr_inst)
+{
+    const uint32_t *replptr;
+    unsigned int i;
+
+    replptr = ALT_REPL_PTR(alt);
+    for ( i = 0; i < nr_inst; i++ )
+    {
+        uint32_t insn;
+
+        insn = get_alt_insn(alt, origptr + i, replptr + i);
+        updptr[i] = cpu_to_le32(insn);
+    }
+}
+
 /*
  * The region patched should be read-write to allow __apply_alternatives
  * to replacing the instructions when necessary.
+ *
+ * @update_offset: Offset between the region patched and the writable
+ * region for the update. 0 if the patched region is writable.
  */
-static int __apply_alternatives(const struct alt_region *region)
+static int __apply_alternatives(const struct alt_region *region,
+                                paddr_t update_offset)
 {
     const struct alt_instr *alt;
-    const u32 *replptr;
-    u32 *origptr;
+    const u32 *origptr;
+    u32 *updptr;
+    alternative_cb_t alt_cb;
 
     printk(XENLOG_INFO "alternatives: Patching with alt table %p -> %p\n",
            region->begin, region->end);
 
     for ( alt = region->begin; alt < region->end; alt++ )
     {
-        u32 insn;
-        int i, nr_inst;
+        int nr_inst;
 
-        if ( !cpus_have_cap(alt->cpufeature) )
+        /* Use ARM_CB_PATCH as an unconditional patch */
+        if ( alt->cpufeature < ARM_CB_PATCH &&
+             !cpus_have_cap(alt->cpufeature) )
             continue;
 
-        BUG_ON(alt->alt_len != alt->orig_len);
+        if ( alt->cpufeature == ARM_CB_PATCH )
+            BUG_ON(alt->alt_len != 0);
+        else
+            BUG_ON(alt->alt_len != alt->orig_len);
 
         origptr = ALT_ORIG_PTR(alt);
-        replptr = ALT_REPL_PTR(alt);
+        updptr = (void *)origptr + update_offset;
 
-        nr_inst = alt->alt_len / sizeof(insn);
+        nr_inst = alt->orig_len / ARCH_PATCH_INSN_SIZE;
 
-        for ( i = 0; i < nr_inst; i++ )
-        {
-            insn = get_alt_insn(alt, origptr + i, replptr + i);
-            *(origptr + i) = cpu_to_le32(insn);
-        }
+        if ( alt->cpufeature < ARM_CB_PATCH )
+            alt_cb = patch_alternative;
+        else
+            alt_cb = ALT_REPL_PTR(alt);
+
+        alt_cb(alt, origptr, updptr, nr_inst);
 
         /* Ensure the new instructions reached the memory and nuke */
         clean_and_invalidate_dcache_va_range(origptr,
@@ -162,9 +191,6 @@ static int __apply_alternatives_multi_stop(void *unused)
         paddr_t xen_size = _end - _start;
         unsigned int xen_order = get_order_from_bytes(xen_size);
         void *xenmap;
-        struct virtual_region patch_region = {
-            .list = LIST_HEAD_INIT(patch_region.list),
-        };
 
         BUG_ON(patched);
 
@@ -177,31 +203,13 @@ static int __apply_alternatives_multi_stop(void *unused)
         /* Re-mapping Xen is not expected to fail during boot. */
         BUG_ON(!xenmap);
 
-        /*
-         * If we generate a new branch instruction, the target will be
-         * calculated in this re-mapped Xen region. So we have to register
-         * this re-mapped Xen region as a virtual region temporarily.
-         */
-        patch_region.start = xenmap;
-        patch_region.end = xenmap + xen_size;
-        register_virtual_region(&patch_region);
-
-        /*
-         * Find the virtual address of the alternative region in the new
-         * mapping.
-         * alt_instr contains relative offset, so the function
-         * __apply_alternatives will patch in the re-mapped version of
-         * Xen.
-         */
-        region.begin = (void *)__alt_instructions - (void *)_start + xenmap;
-        region.end = (void *)__alt_instructions_end - (void *)_start + xenmap;
+        region.begin = __alt_instructions;
+        region.end = __alt_instructions_end;
 
-        ret = __apply_alternatives(&region);
+        ret = __apply_alternatives(&region, xenmap - (void *)_start);
         /* The patching is not expected to fail during boot. */
         BUG_ON(ret != 0);
 
-        unregister_virtual_region(&patch_region);
-
         vunmap(xenmap);
 
         /* Barriers provided by the cache flushing */
@@ -235,7 +243,7 @@ int apply_alternatives(const struct alt_instr *start, const 
struct alt_instr *en
         .end = end,
     };
 
-    return __apply_alternatives(&region);
+    return __apply_alternatives(&region, 0);
 }
 
 /*
diff --git a/xen/arch/arm/arm64/asm-offsets.c b/xen/arch/arm/arm64/asm-offsets.c
index ce24e44473..f5c696d092 100644
--- a/xen/arch/arm/arm64/asm-offsets.c
+++ b/xen/arch/arm/arm64/asm-offsets.c
@@ -22,6 +22,7 @@
 void __dummy__(void)
 {
    OFFSET(UREGS_X0, struct cpu_user_regs, x0);
+   OFFSET(UREGS_X1, struct cpu_user_regs, x1);
    OFFSET(UREGS_LR, struct cpu_user_regs, lr);
 
    OFFSET(UREGS_SP, struct cpu_user_regs, sp);
@@ -45,6 +46,7 @@ void __dummy__(void)
    BLANK();
 
    DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
+   OFFSET(CPUINFO_flags, struct cpu_info, flags);
 
    OFFSET(VCPU_arch_saved_context, struct vcpu, arch.saved_context);
 
diff --git a/xen/arch/arm/arm64/entry.S b/xen/arch/arm/arm64/entry.S
index ffa9a1c492..97b05f53ea 100644
--- a/xen/arch/arm/arm64/entry.S
+++ b/xen/arch/arm/arm64/entry.S
@@ -1,4 +1,6 @@
 #include <asm/asm_defns.h>
+#include <asm/current.h>
+#include <asm/macros.h>
 #include <asm/regs.h>
 #include <asm/alternative.h>
 #include <asm/smccc.h>
@@ -226,11 +228,11 @@ guest_sync:
         mrs     x1, esr_el2
         lsr     x1, x1, #HSR_EC_SHIFT           /* x1 = ESR_EL2.EC */
         cmp     x1, #HSR_EC_HVC64
-        b.ne    1f                              /* Not a HVC skip fastpath. */
+        b.ne    guest_sync_slowpath             /* Not a HVC skip fastpath. */
 
         mrs     x1, esr_el2
         and     x1, x1, #0xffff                 /* Check the immediate [0:16] 
*/
-        cbnz    x1, 1f                          /* should be 0 for HVC #0 */
+        cbnz    x1, guest_sync_slowpath         /* should be 0 for HVC #0 */
 
         /*
          * Fastest path possible for ARM_SMCCC_ARCH_WORKAROUND_1.
@@ -241,7 +243,7 @@ guest_sync:
          * be encoded as an immediate for cmp.
          */
         eor     w0, w0, #ARM_SMCCC_ARCH_WORKAROUND_1_FID
-        cbnz    w0, 1f
+        cbnz    w0, check_wa2
 
         /*
          * Clobber both x0 and x1 to prevent leakage. Note that thanks
@@ -250,7 +252,45 @@ guest_sync:
         mov     x1, xzr
         eret
 
-1:
+check_wa2:
+        /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
+        eor     w0, w0, #(ARM_SMCCC_ARCH_WORKAROUND_1_FID ^ 
ARM_SMCCC_ARCH_WORKAROUND_2_FID)
+        cbnz    w0, guest_sync_slowpath
+#ifdef CONFIG_ARM_SSBD
+alternative_cb arm_enable_wa2_handling
+        b       wa2_end
+alternative_cb_end
+        /* Sanitize the argument */
+        mov     x0, #-(UREGS_kernel_sizeof - UREGS_X1)  /* x0 := offset of 
guest's x1 on the stack */
+        ldr     x1, [sp, x0]                            /* Load guest's x1 */
+        cmp     w1, wzr
+        cset    x1, ne
+
+        /*
+         * Update the guest flag. At this stage sp point after the field
+         * guest_cpu_user_regs in cpu_info.
+         */
+        adr_cpu_info x2
+        ldr     x0, [x2, #CPUINFO_flags]
+        bfi     x0, x1, #CPUINFO_WORKAROUND_2_FLAG_SHIFT, #1
+        str     x0, [x2, #CPUINFO_flags]
+
+        /* Check that we actually need to perform the call */
+        ldr_this_cpu x0, ssbd_callback_required, x2
+        cbz     x0, wa2_end
+
+        mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_2_FID
+        smc     #0
+
+wa2_end:
+        /* Don't leak data from the SMC call */
+        mov     x1, xzr
+        mov     x2, xzr
+        mov     x3, xzr
+#endif /* !CONFIG_ARM_SSBD */
+        mov     x0, xzr
+        eret
+guest_sync_slowpath:
         /*
          * x0/x1 may have been scratch by the fast path above, so avoid
          * to save them.
diff --git a/xen/arch/arm/arm64/smpboot.c b/xen/arch/arm/arm64/smpboot.c
index 4fd0ac68b7..694fbf67e6 100644
--- a/xen/arch/arm/arm64/smpboot.c
+++ b/xen/arch/arm/arm64/smpboot.c
@@ -104,7 +104,7 @@ int __init arch_cpu_init(int cpu, struct dt_device_node *dn)
         return smp_psci_init(cpu);
 }
 
-int __init arch_cpu_up(int cpu)
+int arch_cpu_up(int cpu)
 {
     if ( !smp_enable_ops[cpu].prepare_cpu )
         return -ENODEV;
diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
index c57ac12503..6e60824572 100644
--- a/xen/arch/arm/arm64/vsysreg.c
+++ b/xen/arch/arm/arm64/vsysreg.c
@@ -57,13 +57,15 @@ void do_sysreg(struct cpu_user_regs *regs,
      * ARMv8 (DDI 0487A.d): D1-1509 Table D1-58
      *
      * Unhandled:
-     *    OSLSR_EL1
      *    DBGPRCR_EL1
      */
     case HSR_SYSREG_OSLAR_EL1:
         return handle_wo_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
     case HSR_SYSREG_OSDLR_EL1:
         return handle_raz_wi(regs, regidx, hsr.sysreg.read, hsr, 1);
+    case HSR_SYSREG_OSLSR_EL1:
+        return handle_ro_read_val(regs, regidx, hsr.sysreg.read, hsr, 1,
+                                  1 << 3);
 
     /*
      * MDCR_EL2.TDA
diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c
index 1baa20654b..97a118293b 100644
--- a/xen/arch/arm/cpuerrata.c
+++ b/xen/arch/arm/cpuerrata.c
@@ -1,3 +1,4 @@
+#include <xen/cpu.h>
 #include <xen/cpumask.h>
 #include <xen/mm.h>
 #include <xen/sizes.h>
@@ -5,8 +6,10 @@
 #include <xen/spinlock.h>
 #include <xen/vmap.h>
 #include <xen/warning.h>
+#include <xen/notifier.h>
 #include <asm/cpufeature.h>
 #include <asm/cpuerrata.h>
+#include <asm/insn.h>
 #include <asm/psci.h>
 
 /* Override macros from asm/page.h to make them work with mfn_t */
@@ -235,6 +238,148 @@ static int enable_ic_inv_hardening(void *data)
 
 #endif
 
+#ifdef CONFIG_ARM_SSBD
+
+enum ssbd_state ssbd_state = ARM_SSBD_RUNTIME;
+
+static int __init parse_spec_ctrl(const char *s)
+{
+    const char *ss;
+    int rc = 0;
+
+    do {
+        ss = strchr(s, ',');
+        if ( !ss )
+            ss = strchr(s, '\0');
+
+        if ( !strncmp(s, "ssbd=", 5) )
+        {
+            s += 5;
+
+            if ( !strncmp(s, "force-disable", ss - s) )
+                ssbd_state = ARM_SSBD_FORCE_DISABLE;
+            else if ( !strncmp(s, "runtime", ss - s) )
+                ssbd_state = ARM_SSBD_RUNTIME;
+            else if ( !strncmp(s, "force-enable", ss - s) )
+                ssbd_state = ARM_SSBD_FORCE_ENABLE;
+            else
+                rc = -EINVAL;
+        }
+        else
+            rc = -EINVAL;
+
+        s = ss + 1;
+    } while ( *ss );
+
+    return rc;
+}
+custom_param("spec-ctrl", parse_spec_ctrl);
+
+/* Arm64 only for now as for Arm32 the workaround is currently handled in C. */
+#ifdef CONFIG_ARM_64
+void __init arm_enable_wa2_handling(const struct alt_instr *alt,
+                                    const uint32_t *origptr,
+                                    uint32_t *updptr, int nr_inst)
+{
+    BUG_ON(nr_inst != 1);
+
+    /*
+     * Only allow mitigation on guest ARCH_WORKAROUND_2 if the SSBD
+     * state allow it to be flipped.
+     */
+    if ( get_ssbd_state() == ARM_SSBD_RUNTIME )
+        *updptr = aarch64_insn_gen_nop();
+}
+#endif
+
+/*
+ * Assembly code may use the variable directly, so we need to make sure
+ * it fits in a register.
+ */
+DEFINE_PER_CPU_READ_MOSTLY(register_t, ssbd_callback_required);
+
+static bool has_ssbd_mitigation(const struct arm_cpu_capabilities *entry)
+{
+    struct arm_smccc_res res;
+    bool required;
+
+    if ( smccc_ver < SMCCC_VERSION(1, 1) )
+        return false;
+
+    arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FID,
+                      ARM_SMCCC_ARCH_WORKAROUND_2_FID, &res);
+
+    switch ( (int)res.a0 )
+    {
+    case ARM_SMCCC_NOT_SUPPORTED:
+        ssbd_state = ARM_SSBD_UNKNOWN;
+        return false;
+
+    case ARM_SMCCC_NOT_REQUIRED:
+        ssbd_state = ARM_SSBD_MITIGATED;
+        return false;
+
+    case ARM_SMCCC_SUCCESS:
+        required = true;
+        break;
+
+    case 1: /* Mitigation not required on this CPU. */
+        required = false;
+        break;
+
+    default:
+        ASSERT_UNREACHABLE();
+        return false;
+    }
+
+    switch ( ssbd_state )
+    {
+    case ARM_SSBD_FORCE_DISABLE:
+    {
+        static bool once = true;
+
+        if ( once )
+            printk("%s disabled from command-line\n", entry->desc);
+        once = false;
+
+        arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
+        required = false;
+
+        break;
+    }
+
+    case ARM_SSBD_RUNTIME:
+        if ( required )
+        {
+            this_cpu(ssbd_callback_required) = 1;
+            arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
+        }
+
+        break;
+
+    case ARM_SSBD_FORCE_ENABLE:
+    {
+        static bool once = true;
+
+        if ( once )
+            printk("%s forced from command-line\n", entry->desc);
+        once = false;
+
+        arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
+        required = true;
+
+        break;
+    }
+
+    default:
+        ASSERT_UNREACHABLE();
+        return false;
+    }
+
+    return required;
+}
+#endif
+
 #define MIDR_RANGE(model, min, max)     \
     .matches = is_affected_midr_range,  \
     .midr_model = model,                \
@@ -336,6 +481,13 @@ static const struct arm_cpu_capabilities arm_errata[] = {
         .enable = enable_ic_inv_hardening,
     },
 #endif
+#ifdef CONFIG_ARM_SSBD
+    {
+        .desc = "Speculative Store Bypass Disabled",
+        .capability = ARM_SSBD,
+        .matches = has_ssbd_mitigation,
+    },
+#endif
     {},
 };
 
@@ -349,6 +501,53 @@ void __init enable_errata_workarounds(void)
     enable_cpu_capabilities(arm_errata);
 }
 
+static int cpu_errata_callback(struct notifier_block *nfb,
+                               unsigned long action,
+                               void *hcpu)
+{
+    int rc = 0;
+
+    switch ( action )
+    {
+    case CPU_STARTING:
+        /*
+         * At CPU_STARTING phase no notifier shall return an error, because the
+         * system is designed with the assumption that starting a CPU cannot
+         * fail at this point. If an error happens here it will cause Xen to 
hit
+         * the BUG_ON() in notify_cpu_starting(). In future, either this
+         * notifier/enabling capabilities should be fixed to always return
+         * success/void or notify_cpu_starting() and other common code should 
be
+         * fixed to expect an error at CPU_STARTING phase.
+         */
+        ASSERT(system_state != SYS_STATE_boot);
+        rc = enable_nonboot_cpu_caps(arm_errata);
+        break;
+    default:
+        break;
+    }
+
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
+}
+
+static struct notifier_block cpu_errata_nfb = {
+    .notifier_call = cpu_errata_callback,
+};
+
+static int __init cpu_errata_notifier_init(void)
+{
+    register_cpu_notifier(&cpu_errata_nfb);
+
+    return 0;
+}
+/*
+ * Initialization has to be done at init rather than presmp_init phase because
+ * the callback should execute only after the secondary CPUs are initially
+ * booted (in hotplug scenarios when the system state is not boot). On boot,
+ * the enabling of errata workarounds will be triggered by the boot CPU from
+ * start_xen().
+ */
+__initcall(cpu_errata_notifier_init);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c
index 525b45e22f..3aaff4c0e6 100644
--- a/xen/arch/arm/cpufeature.c
+++ b/xen/arch/arm/cpufeature.c
@@ -69,6 +69,35 @@ void __init enable_cpu_capabilities(const struct 
arm_cpu_capabilities *caps)
 }
 
 /*
+ * Run through the enabled capabilities and enable() them on the calling CPU.
+ * If enabling of any capability fails the error is returned. After enabling a
+ * capability fails the error will be remembered into 'rc' and the remaining
+ * capabilities will be enabled. If enabling multiple capabilities fail the
+ * error returned by this function represents the error code of the last
+ * failure.
+ */
+int enable_nonboot_cpu_caps(const struct arm_cpu_capabilities *caps)
+{
+    int rc = 0;
+
+    for ( ; caps->matches; caps++ )
+    {
+        if ( !cpus_have_cap(caps->capability) )
+            continue;
+
+        if ( caps->enable )
+        {
+            int ret = caps->enable((void *)caps);
+
+            if ( ret )
+                rc = ret;
+        }
+    }
+
+    return rc;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index ec0f042bf7..4baecc2447 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -21,6 +21,7 @@
 #include <xen/wait.h>
 
 #include <asm/alternative.h>
+#include <asm/cpuerrata.h>
 #include <asm/cpufeature.h>
 #include <asm/current.h>
 #include <asm/event.h>
@@ -550,6 +551,7 @@ int vcpu_initialise(struct vcpu *v)
     v->arch.cpu_info = (struct cpu_info *)(v->arch.stack
                                            + STACK_SIZE
                                            - sizeof(struct cpu_info));
+    memset(v->arch.cpu_info, 0, sizeof(*v->arch.cpu_info));
 
     memset(&v->arch.saved_context, 0, sizeof(v->arch.saved_context));
     v->arch.saved_context.sp = (register_t)v->arch.cpu_info;
@@ -571,6 +573,13 @@ int vcpu_initialise(struct vcpu *v)
     if ( (rc = vcpu_vtimer_init(v)) != 0 )
         goto fail;
 
+    /*
+     * The workaround 2 (i.e SSBD mitigation) is enabled by default if
+     * supported.
+     */
+    if ( get_ssbd_state() == ARM_SSBD_RUNTIME )
+        v->arch.cpu_info->flags |= CPUINFO_WORKAROUND_2_FLAG;
+
     return rc;
 
 fail:
diff --git a/xen/arch/arm/gic-vgic.c b/xen/arch/arm/gic-vgic.c
index d831b35525..fd63906e9b 100644
--- a/xen/arch/arm/gic-vgic.c
+++ b/xen/arch/arm/gic-vgic.c
@@ -362,7 +362,7 @@ int vgic_vcpu_pending_irq(struct vcpu *v)
     ASSERT(v == current);
 
     mask_priority = gic_hw_ops->read_vmcr_priority();
-    active_priority = find_next_bit(&apr, 32, 0);
+    active_priority = find_first_bit(&apr, 32);
 
     spin_lock_irqsave(&v->arch.vgic.lock, flags);
 
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 653a815127..5474030386 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -27,6 +27,8 @@
 #include <xen/list.h>
 #include <xen/device_tree.h>
 #include <xen/acpi.h>
+#include <xen/cpu.h>
+#include <xen/notifier.h>
 #include <asm/p2m.h>
 #include <asm/domain.h>
 #include <asm/platform.h>
@@ -462,6 +464,35 @@ int gic_iomem_deny_access(const struct domain *d)
     return gic_hw_ops->iomem_deny_access(d);
 }
 
+static int cpu_gic_callback(struct notifier_block *nfb,
+                            unsigned long action,
+                            void *hcpu)
+{
+    switch ( action )
+    {
+    case CPU_DYING:
+        /* This is reverting the work done in init_maintenance_interrupt */
+        release_irq(gic_hw_ops->info->maintenance_irq, NULL);
+        break;
+    default:
+        break;
+    }
+
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_gic_nfb = {
+    .notifier_call = cpu_gic_callback,
+};
+
+static int __init cpu_gic_notifier_init(void)
+{
+    register_cpu_notifier(&cpu_gic_nfb);
+
+    return 0;
+}
+__initcall(cpu_gic_notifier_init);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index aa4e832cae..098281f8ab 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -65,7 +65,7 @@ irq_desc_t *__irq_to_desc(int irq)
     return &irq_desc[irq-NR_LOCAL_IRQS];
 }
 
-int __init arch_init_one_irq_desc(struct irq_desc *desc)
+int arch_init_one_irq_desc(struct irq_desc *desc)
 {
     desc->arch.type = IRQ_TYPE_INVALID;
     return 0;
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index d43c3aa896..14791388ad 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -8,6 +8,8 @@
 #include <xen/iocap.h>
 #include <xen/mem_access.h>
 #include <xen/xmalloc.h>
+#include <xen/cpu.h>
+#include <xen/notifier.h>
 #include <public/vm_event.h>
 #include <asm/flushtlb.h>
 #include <asm/event.h>
@@ -1451,10 +1453,12 @@ err:
     return page;
 }
 
-static void __init setup_virt_paging_one(void *data)
+/* VTCR value to be configured by all CPUs. Set only once by the boot CPU */
+static uint32_t __read_mostly vtcr;
+
+static void setup_virt_paging_one(void *data)
 {
-    unsigned long val = (unsigned long)data;
-    WRITE_SYSREG32(val, VTCR_EL2);
+    WRITE_SYSREG32(vtcr, VTCR_EL2);
     isb();
 }
 
@@ -1538,10 +1542,49 @@ void __init setup_virt_paging(void)
 
     /* It is not allowed to concatenate a level zero root */
     BUG_ON( P2M_ROOT_LEVEL == 0 && P2M_ROOT_ORDER > 0 );
-    setup_virt_paging_one((void *)val);
-    smp_call_function(setup_virt_paging_one, (void *)val, 1);
+    vtcr = val;
+    setup_virt_paging_one(NULL);
+    smp_call_function(setup_virt_paging_one, NULL, 1);
+}
+
+static int cpu_virt_paging_callback(struct notifier_block *nfb,
+                                    unsigned long action,
+                                    void *hcpu)
+{
+    switch ( action )
+    {
+    case CPU_STARTING:
+        ASSERT(system_state != SYS_STATE_boot);
+        setup_virt_paging_one(NULL);
+        break;
+    default:
+        break;
+    }
+
+    return NOTIFY_DONE;
 }
 
+static struct notifier_block cpu_virt_paging_nfb = {
+    .notifier_call = cpu_virt_paging_callback,
+};
+
+static int __init cpu_virt_paging_init(void)
+{
+    register_cpu_notifier(&cpu_virt_paging_nfb);
+
+    return 0;
+}
+/*
+ * Initialization of the notifier has to be done at init rather than 
presmp_init
+ * phase because: the registered notifier is used to setup virtual paging for
+ * non-boot CPUs after the initial virtual paging for all CPUs is already 
setup,
+ * i.e. when a non-boot CPU is hotplugged after the system has booted. In other
+ * words, the notifier should be registered after the virtual paging is
+ * initially setup (setup_virt_paging() is called from start_xen()). This is
+ * required because vtcr config value has to be set before a notifier can fire.
+ */
+__initcall(cpu_virt_paging_init);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/platforms/vexpress.c 
b/xen/arch/arm/platforms/vexpress.c
index 70839d676f..b6193f75b5 100644
--- a/xen/arch/arm/platforms/vexpress.c
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -59,41 +59,6 @@ static inline int vexpress_ctrl_start(uint32_t *syscfg, int 
write,
     return 0;
 }
 
-int vexpress_syscfg(int write, int function, int device, uint32_t *data)
-{
-    uint32_t *syscfg = (uint32_t *) FIXMAP_ADDR(FIXMAP_MISC);
-    int ret = -1;
-
-    set_fixmap(FIXMAP_MISC, maddr_to_mfn(V2M_SYS_MMIO_BASE),
-               PAGE_HYPERVISOR_NOCACHE);
-
-    if ( syscfg[V2M_SYS_CFGCTRL/4] & V2M_SYS_CFG_START )
-        goto out;
-
-    /* clear the complete bit in the V2M_SYS_CFGSTAT status register */
-    syscfg[V2M_SYS_CFGSTAT/4] = 0;
-
-    if ( write )
-    {
-        /* write data */
-        syscfg[V2M_SYS_CFGDATA/4] = *data;
-
-        if ( vexpress_ctrl_start(syscfg, write, function, device) < 0 )
-            goto out;
-    } else {
-        if ( vexpress_ctrl_start(syscfg, write, function, device) < 0 )
-            goto out;
-        else
-            /* read data */
-            *data = syscfg[V2M_SYS_CFGDATA/4];
-    }
-
-    ret = 0;
-out:
-    clear_fixmap(FIXMAP_MISC);
-    return ret;
-}
-
 /*
  * TODO: Get base address from the device tree
  * See arm,vexpress-reset node
diff --git a/xen/arch/arm/processor.c b/xen/arch/arm/processor.c
index ce4385064a..acad8b31d6 100644
--- a/xen/arch/arm/processor.c
+++ b/xen/arch/arm/processor.c
@@ -20,7 +20,7 @@
 
 static DEFINE_PER_CPU(struct processor *, processor);
 
-void __init processor_setup(void)
+void processor_setup(void)
 {
     const struct proc_info_list *procinfo;
 
diff --git a/xen/arch/arm/psci.c b/xen/arch/arm/psci.c
index 94b616df9b..3cf5ecf0f3 100644
--- a/xen/arch/arm/psci.c
+++ b/xen/arch/arm/psci.c
@@ -46,6 +46,19 @@ int call_psci_cpu_on(int cpu)
     return call_smc(psci_cpu_on_nr, cpu_logical_map(cpu), 
__pa(init_secondary), 0);
 }
 
+void call_psci_cpu_off(void)
+{
+    if ( psci_ver > PSCI_VERSION(0, 1) )
+    {
+        int errno;
+
+        /* If successfull the PSCI cpu_off call doesn't return */
+        errno = call_smc(PSCI_0_2_FN32_CPU_OFF, 0, 0, 0);
+        panic("PSCI cpu off failed for CPU%d err=%d\n", smp_processor_id(),
+              errno);
+    }
+}
+
 void call_psci_system_off(void)
 {
     if ( psci_ver > PSCI_VERSION(0, 1) )
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 216572fbb2..3a75cb2a34 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -171,8 +171,6 @@ static void __init processor_id(void)
     }
 
     processor_setup();
-
-    check_local_cpu_errata();
 }
 
 void dt_unreserved_regions(paddr_t s, paddr_t e,
@@ -779,6 +777,12 @@ void __init start_xen(unsigned long boot_phys_offset,
     printk(XENLOG_INFO "SMP: Allowing %u CPUs\n", cpus);
     nr_cpu_ids = cpus;
 
+    /*
+     * Some errata relies on SMCCC version which is detected by psci_init()
+     * (called from smp_init_cpus()).
+     */
+    check_local_cpu_errata();
+
     init_xen_time();
 
     gic_init();
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index b2116f0d2d..cf3a4ce659 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -52,8 +52,8 @@ nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
 static unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
        __attribute__((__aligned__(STACK_SIZE)));
 
-/* Initial boot cpu data */
-struct init_info __initdata init_data =
+/* Boot cpu data */
+struct init_info init_data =
 {
     .stack = cpu0_boot_stack,
 };
@@ -89,6 +89,12 @@ static void setup_cpu_sibling_map(int cpu)
     cpumask_set_cpu(cpu, per_cpu(cpu_core_mask, cpu));
 }
 
+static void remove_cpu_sibling_map(int cpu)
+{
+    free_cpumask_var(per_cpu(cpu_sibling_mask, cpu));
+    free_cpumask_var(per_cpu(cpu_core_mask, cpu));
+}
+
 void __init
 smp_clear_cpu_maps (void)
 {
@@ -395,6 +401,8 @@ void stop_cpu(void)
     /* Make sure the write happens before we sleep forever */
     dsb(sy);
     isb();
+    call_psci_cpu_off();
+
     while ( 1 )
         wfi();
 }
@@ -497,6 +505,36 @@ void __cpu_die(unsigned int cpu)
     smp_mb();
 }
 
+static int cpu_smpboot_callback(struct notifier_block *nfb,
+                                unsigned long action,
+                                void *hcpu)
+{
+    unsigned int cpu = (unsigned long)hcpu;
+
+    switch ( action )
+    {
+    case CPU_DEAD:
+        remove_cpu_sibling_map(cpu);
+        break;
+    default:
+        break;
+    }
+
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_smpboot_nfb = {
+    .notifier_call = cpu_smpboot_callback,
+};
+
+static int __init cpu_smpboot_notifier_init(void)
+{
+    register_cpu_notifier(&cpu_smpboot_nfb);
+
+    return 0;
+}
+presmp_initcall(cpu_smpboot_notifier_init);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index c11fcfeadd..1635c8822d 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -29,6 +29,8 @@
 #include <xen/sched.h>
 #include <xen/event.h>
 #include <xen/acpi.h>
+#include <xen/cpu.h>
+#include <xen/notifier.h>
 #include <asm/system.h>
 #include <asm/time.h>
 #include <asm/vgic.h>
@@ -312,6 +314,21 @@ void init_timer_interrupt(void)
     check_timer_irq_cfg(timer_irq[TIMER_PHYS_NONSECURE_PPI], "NS-physical");
 }
 
+/*
+ * Revert actions done in init_timer_interrupt that are required to properly
+ * disable this CPU.
+ */
+static void deinit_timer_interrupt(void)
+{
+    WRITE_SYSREG32(0, CNTP_CTL_EL0);    /* Disable physical timer */
+    WRITE_SYSREG32(0, CNTHP_CTL_EL2);   /* Disable hypervisor's timer */
+    isb();
+
+    release_irq(timer_irq[TIMER_HYP_PPI], NULL);
+    release_irq(timer_irq[TIMER_VIRT_PPI], NULL);
+    release_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], NULL);
+}
+
 /* Wait a set number of microseconds */
 void udelay(unsigned long usecs)
 {
@@ -340,6 +357,34 @@ void domain_set_time_offset(struct domain *d, int64_t 
time_offset_seconds)
     /* XXX update guest visible wallclock time */
 }
 
+static int cpu_time_callback(struct notifier_block *nfb,
+                             unsigned long action,
+                             void *hcpu)
+{
+    switch ( action )
+    {
+    case CPU_DYING:
+        deinit_timer_interrupt();
+        break;
+    default:
+        break;
+    }
+
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_time_nfb = {
+    .notifier_call = cpu_time_callback,
+};
+
+static int __init cpu_time_notifier_init(void)
+{
+    register_cpu_notifier(&cpu_time_nfb);
+
+    return 0;
+}
+__initcall(cpu_time_notifier_init);
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 5c18e918b0..9ae64ae6fc 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1739,12 +1739,13 @@ void handle_wo_wi(struct cpu_user_regs *regs,
     advance_pc(regs, hsr);
 }
 
-/* Read only as read as zero */
-void handle_ro_raz(struct cpu_user_regs *regs,
-                   int regidx,
-                   bool read,
-                   const union hsr hsr,
-                   int min_el)
+/* Read only as value provided with 'val' argument of this function */
+void handle_ro_read_val(struct cpu_user_regs *regs,
+                        int regidx,
+                        bool read,
+                        const union hsr hsr,
+                        int min_el,
+                        register_t val)
 {
     ASSERT((min_el == 0) || (min_el == 1));
 
@@ -1753,13 +1754,22 @@ void handle_ro_raz(struct cpu_user_regs *regs,
 
     if ( !read )
         return inject_undef_exception(regs, hsr);
-    /* else: raz */
 
-    set_user_reg(regs, regidx, 0);
+    set_user_reg(regs, regidx, val);
 
     advance_pc(regs, hsr);
 }
 
+/* Read only as read as zero */
+inline void handle_ro_raz(struct cpu_user_regs *regs,
+                          int regidx,
+                          bool read,
+                          const union hsr hsr,
+                          int min_el)
+{
+    handle_ro_read_val(regs, regidx, read, hsr, min_el, 0);
+}
+
 void dump_guest_s1_walk(struct domain *d, vaddr_t addr)
 {
     register_t ttbcr = READ_SYSREG(TCR_EL1);
@@ -2011,18 +2021,33 @@ inject_abt:
         inject_iabt_exception(regs, gva, hsr.len);
 }
 
+static inline bool needs_ssbd_flip(struct vcpu *v)
+{
+    if ( !check_workaround_ssbd() )
+        return false;
+
+    return !(v->arch.cpu_info->flags & CPUINFO_WORKAROUND_2_FLAG) &&
+             cpu_require_ssbd_mitigation();
+}
+
 static void enter_hypervisor_head(struct cpu_user_regs *regs)
 {
     if ( guest_mode(regs) )
     {
+        struct vcpu *v = current;
+
+        /* If the guest has disabled the workaround, bring it back on. */
+        if ( needs_ssbd_flip(v) )
+            arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 1, NULL);
+
         /*
          * If we pended a virtual abort, preserve it until it gets cleared.
          * See ARM ARM DDI 0487A.j D1.14.3 (Virtual Interrupts) for details,
          * but the crucial bit is "On taking a vSError interrupt, HCR_EL2.VSE
          * (alias of HCR.VA) is cleared to 0."
          */
-        if ( current->arch.hcr_el2 & HCR_VA )
-            current->arch.hcr_el2 = READ_SYSREG(HCR_EL2);
+        if ( v->arch.hcr_el2 & HCR_VA )
+            v->arch.hcr_el2 = READ_SYSREG(HCR_EL2);
 
 #ifdef CONFIG_NEW_VGIC
         /*
@@ -2032,11 +2057,11 @@ static void enter_hypervisor_head(struct cpu_user_regs 
*regs)
          * TODO: Investigate whether this is necessary to do on every
          * trap and how it can be optimised.
          */
-        vtimer_update_irqs(current);
-        vcpu_update_evtchn_irq(current);
+        vtimer_update_irqs(v);
+        vcpu_update_evtchn_irq(v);
 #endif
 
-        vgic_sync_from_lrs(current);
+        vgic_sync_from_lrs(v);
     }
 }
 
@@ -2260,6 +2285,13 @@ void leave_hypervisor_tail(void)
              */
             SYNCHRONIZE_SERROR(SKIP_SYNCHRONIZE_SERROR_ENTRY_EXIT);
 
+            /*
+             * The hypervisor runs with the workaround always present.
+             * If the guest wants it disabled, so be it...
+             */
+            if ( needs_ssbd_flip(current) )
+                arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2_FID, 0, NULL);
+
             return;
         }
         local_irq_enable();
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 646d1f3d12..f6c11f1e41 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -485,6 +485,8 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, 
mmio_info_t *info,
 
     case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN):
         if ( dabt.size != DABT_WORD ) goto bad_width;
+        if ( r == 0 )
+            goto write_ignore_32;
         printk(XENLOG_G_ERR
                "%pv: vGICD: unhandled word write %#"PRIregister" to 
ISACTIVER%d\n",
                v, r, gicd_reg - GICD_ISACTIVER);
diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
index 40a80d5760..c4ccae6030 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -18,6 +18,7 @@
 #include <xen/lib.h>
 #include <xen/types.h>
 #include <public/arch-arm/smccc.h>
+#include <asm/cpuerrata.h>
 #include <asm/cpufeature.h>
 #include <asm/monitor.h>
 #include <asm/regs.h>
@@ -104,6 +105,23 @@ static bool handle_arch(struct cpu_user_regs *regs)
             if ( cpus_have_cap(ARM_HARDEN_BRANCH_PREDICTOR) )
                 ret = 0;
             break;
+        case ARM_SMCCC_ARCH_WORKAROUND_2_FID:
+            switch ( get_ssbd_state() )
+            {
+            case ARM_SSBD_UNKNOWN:
+            case ARM_SSBD_FORCE_DISABLE:
+                break;
+
+            case ARM_SSBD_RUNTIME:
+                ret = ARM_SMCCC_SUCCESS;
+                break;
+
+            case ARM_SSBD_FORCE_ENABLE:
+            case ARM_SSBD_MITIGATED:
+                ret = ARM_SMCCC_NOT_REQUIRED;
+                break;
+            }
+            break;
         }
 
         set_user_reg(regs, 0, ret);
@@ -114,6 +132,25 @@ static bool handle_arch(struct cpu_user_regs *regs)
     case ARM_SMCCC_ARCH_WORKAROUND_1_FID:
         /* No return value */
         return true;
+
+    case ARM_SMCCC_ARCH_WORKAROUND_2_FID:
+    {
+        bool enable = (uint32_t)get_user_reg(regs, 1);
+
+        /*
+         * ARM_WORKAROUND_2_FID should only be called when mitigation
+         * state can be changed at runtime.
+         */
+        if ( unlikely(get_ssbd_state() != ARM_SSBD_RUNTIME) )
+            return true;
+
+        if ( enable )
+            get_cpu_info()->flags |= CPUINFO_WORKAROUND_2_FLAG;
+        else
+            get_cpu_info()->flags &= ~CPUINFO_WORKAROUND_2_FLAG;
+
+        return true;
+    }
     }
 
     return false;
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 9718ce37fb..05281d6af7 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -737,6 +737,7 @@ void restore_vcpu_affinity(struct domain *d)
     for_each_vcpu ( d, v )
     {
         spinlock_t *lock;
+        unsigned int old_cpu = v->processor;
 
         ASSERT(!vcpu_runnable(v));
 
@@ -769,6 +770,9 @@ void restore_vcpu_affinity(struct domain *d)
         lock = vcpu_schedule_lock_irq(v);
         v->processor = SCHED_OP(vcpu_scheduler(v), pick_cpu, v);
         spin_unlock_irq(lock);
+
+        if ( old_cpu != v->processor )
+            sched_move_irqs(v);
     }
 
     domain_update_node_affinity(d);
diff --git a/xen/drivers/video/Kconfig b/xen/drivers/video/Kconfig
index 52e8ce6c15..41ca503cc9 100644
--- a/xen/drivers/video/Kconfig
+++ b/xen/drivers/video/Kconfig
@@ -11,6 +11,3 @@ config VGA
          Enable VGA output for the Xen hypervisor.
 
          If unsure, say Y.
-
-config HAS_ARM_HDLCD
-       bool
diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile
index 2bb91d62a5..2b3fc76812 100644
--- a/xen/drivers/video/Makefile
+++ b/xen/drivers/video/Makefile
@@ -4,4 +4,3 @@ obj-$(CONFIG_VIDEO) += font_8x16.o
 obj-$(CONFIG_VIDEO) += font_8x8.o
 obj-$(CONFIG_VIDEO) += lfb.o
 obj-$(CONFIG_VGA) += vesa.o
-obj-$(CONFIG_HAS_ARM_HDLCD) += arm_hdlcd.o
diff --git a/xen/drivers/video/arm_hdlcd.c b/xen/drivers/video/arm_hdlcd.c
deleted file mode 100644
index e1174b223f..0000000000
--- a/xen/drivers/video/arm_hdlcd.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * xen/drivers/video/arm_hdlcd.c
- *
- * Driver for ARM HDLCD Controller
- *
- * Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
- * 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/delay.h>
-#include <asm/types.h>
-#include <asm/platforms/vexpress.h>
-#include <xen/device_tree.h>
-#include <xen/libfdt/libfdt.h>
-#include <xen/init.h>
-#include <xen/mm.h>
-#include "font.h"
-#include "lfb.h"
-#include "modelines.h"
-
-#define HDLCD ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_MISC))
-
-#define HDLCD_INTMASK       (0x18/4)
-#define HDLCD_FBBASE        (0x100/4)
-#define HDLCD_LINELENGTH    (0x104/4)
-#define HDLCD_LINECOUNT     (0x108/4)
-#define HDLCD_LINEPITCH     (0x10C/4)
-#define HDLCD_BUS           (0x110/4)
-#define HDLCD_VSYNC         (0x200/4)
-#define HDLCD_VBACK         (0x204/4)
-#define HDLCD_VDATA         (0x208/4)
-#define HDLCD_VFRONT        (0x20C/4)
-#define HDLCD_HSYNC         (0x210/4)
-#define HDLCD_HBACK         (0x214/4)
-#define HDLCD_HDATA         (0x218/4)
-#define HDLCD_HFRONT        (0x21C/4)
-#define HDLCD_POLARITIES    (0x220/4)
-#define HDLCD_COMMAND       (0x230/4)
-#define HDLCD_PF            (0x240/4)
-#define HDLCD_RED           (0x244/4)
-#define HDLCD_GREEN         (0x248/4)
-#define HDLCD_BLUE          (0x24C/4)
-
-struct color_masks {
-    int red_shift;
-    int red_size;
-    int green_shift;
-    int green_size;
-    int blue_shift;
-    int blue_size;
-};
-
-struct pixel_colors {
-    const char* bpp;
-    struct color_masks colors;
-};
-
-struct pixel_colors __initdata colors[] = {
-    { "16", { 0, 5, 11, 5, 6, 5 } },
-    { "24", { 0, 8, 16, 8, 8, 8 } },
-    { "32", { 0, 8, 16, 8, 8, 8 } },
-};
-
-static void vga_noop_puts(const char *s) {}
-void (*video_puts)(const char *) = vga_noop_puts;
-
-static void hdlcd_flush(void)
-{
-    dsb(sy);
-}
-
-static int __init get_color_masks(const char* bpp, struct color_masks **masks)
-{
-    int i;
-    for ( i = 0; i < ARRAY_SIZE(colors); i++ )
-    {
-        if ( !strncmp(colors[i].bpp, bpp, 2) )
-        {
-            *masks = &colors[i].colors;
-            return 0;
-        }
-    }
-    return -1;
-}
-
-static void __init set_pixclock(uint32_t pixclock)
-{
-    if ( dt_find_compatible_node(NULL, NULL, "arm,vexpress") )
-            vexpress_syscfg(1, V2M_SYS_CFG_OSC_FUNC,
-                            V2M_SYS_CFG_OSC5, &pixclock);
-}
-
-void __init video_init(void)
-{
-    struct lfb_prop lfbp;
-    unsigned char *lfb;
-    paddr_t hdlcd_start, hdlcd_size;
-    paddr_t framebuffer_start, framebuffer_size;
-    const char *mode_string;
-    char _mode_string[16];
-    int bytes_per_pixel = 4;
-    struct color_masks *c = NULL;
-    struct modeline *videomode = NULL;
-    int i;
-    const struct dt_device_node *dev;
-    const __be32 *cells;
-    u32 lenp;
-    int res;
-
-    dev = dt_find_compatible_node(NULL, NULL, "arm,hdlcd");
-
-    if ( !dev )
-    {
-        printk("HDLCD: Cannot find node compatible with \"arm,hdcld\"\n");
-        return;
-    }
-
-    res = dt_device_get_address(dev, 0, &hdlcd_start, &hdlcd_size);
-    if ( !res )
-    {
-        printk("HDLCD: Unable to retrieve MMIO base address\n");
-        return;
-    }
-
-    cells = dt_get_property(dev, "framebuffer", &lenp);
-    if ( !cells )
-    {
-        printk("HDLCD: Unable to retrieve framebuffer property\n");
-        return;
-    }
-
-    framebuffer_start = dt_next_cell(dt_n_addr_cells(dev), &cells);
-    framebuffer_size = dt_next_cell(dt_n_size_cells(dev), &cells);
-
-    if ( !hdlcd_start )
-    {
-        printk(KERN_ERR "HDLCD: address missing from device tree, disabling 
driver\n");
-        return;
-    }
-
-    if ( !framebuffer_start )
-    {
-        printk(KERN_ERR "HDLCD: framebuffer address missing from device tree, 
disabling driver\n");
-        return;
-    }
-
-    res = dt_property_read_string(dev, "mode", &mode_string);
-    if ( res )
-    {
-        get_color_masks("32", &c);
-        memcpy(_mode_string, "1280x1024@60", strlen("1280x1024@60") + 1);
-        bytes_per_pixel = 4;
-    }
-    else if ( strlen(mode_string) < strlen("800x600@60") ||
-            strlen(mode_string) > sizeof(_mode_string) - 1 )
-    {
-        printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string);
-        return;
-    } else {
-        char *s = strchr(mode_string, '-');
-        if ( !s )
-        {
-            printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume 32 
bpp\n",
-                         mode_string);
-            get_color_masks("32", &c);
-            memcpy(_mode_string, mode_string, strlen(mode_string) + 1);
-            bytes_per_pixel = 4;
-        } else {
-            if ( strlen(s) < 6 )
-            {
-                printk(KERN_ERR "HDLCD: invalid mode %s\n", mode_string);
-                return;
-            }
-            s++;
-            if ( get_color_masks(s, &c) < 0 )
-            {
-                printk(KERN_WARNING "HDLCD: unsupported bpp %s\n", s);
-                return;
-            }
-            bytes_per_pixel = simple_strtoll(s, NULL, 10) / 8;
-        }
-        i = s - mode_string - 1;
-        memcpy(_mode_string, mode_string, i);
-        memcpy(_mode_string + i, mode_string + i + 3, 4);
-    }
-
-    for ( i = 0; i < ARRAY_SIZE(videomodes); i++ ) {
-        if ( !strcmp(_mode_string, videomodes[i].mode) )
-        {
-            videomode = &videomodes[i];
-            break;
-        }
-    }
-    if ( !videomode )
-    {
-        printk(KERN_WARNING "HDLCD: unsupported videomode %s\n",
-               _mode_string);
-        return;
-    }
-
-    if ( framebuffer_size < bytes_per_pixel * videomode->xres * 
videomode->yres )
-    {
-        printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling the 
HDLCD driver\n");
-        return;
-    }
-
-    printk(KERN_INFO "Initializing HDLCD driver\n");
-
-    lfb = ioremap_wc(framebuffer_start, framebuffer_size);
-    if ( !lfb )
-    {
-        printk(KERN_ERR "Couldn't map the framebuffer\n");
-        return;
-    }
-    memset(lfb, 0x00, bytes_per_pixel * videomode->xres * videomode->yres);
-
-    /* uses FIXMAP_MISC */
-    set_pixclock(videomode->pixclock);
-
-    set_fixmap(FIXMAP_MISC, maddr_to_mfn(hdlcd_start), 
PAGE_HYPERVISOR_NOCACHE);
-    HDLCD[HDLCD_COMMAND] = 0;
-
-    HDLCD[HDLCD_LINELENGTH] = videomode->xres * bytes_per_pixel;
-    HDLCD[HDLCD_LINECOUNT] = videomode->yres - 1;
-    HDLCD[HDLCD_LINEPITCH] = videomode->xres * bytes_per_pixel;
-    HDLCD[HDLCD_PF] = ((bytes_per_pixel - 1) << 3);
-    HDLCD[HDLCD_INTMASK] = 0;
-    HDLCD[HDLCD_FBBASE] = framebuffer_start;
-    HDLCD[HDLCD_BUS] = 0xf00 | (1 << 4);
-    HDLCD[HDLCD_VBACK] = videomode->vback - 1;
-    HDLCD[HDLCD_VSYNC] = videomode->vsync - 1;
-    HDLCD[HDLCD_VDATA] = videomode->yres - 1;
-    HDLCD[HDLCD_VFRONT] = videomode->vfront - 1;
-    HDLCD[HDLCD_HBACK] = videomode->hback - 1;
-    HDLCD[HDLCD_HSYNC] = videomode->hsync - 1;
-    HDLCD[HDLCD_HDATA] = videomode->xres - 1;
-    HDLCD[HDLCD_HFRONT] = videomode->hfront - 1;
-    HDLCD[HDLCD_POLARITIES] = (1 << 2) | (1 << 3);
-    HDLCD[HDLCD_RED] = (c->red_size << 8) | c->red_shift;
-    HDLCD[HDLCD_GREEN] = (c->green_size << 8) | c->green_shift;
-    HDLCD[HDLCD_BLUE] = (c->blue_size << 8) | c->blue_shift;
-    HDLCD[HDLCD_COMMAND] = 1;
-    clear_fixmap(FIXMAP_MISC);
-
-    lfbp.pixel_on = (((1 << c->red_size) - 1) << c->red_shift) |
-        (((1 << c->green_size) - 1) << c->green_shift) |
-        (((1 << c->blue_size) - 1) << c->blue_shift);
-    lfbp.lfb = lfb;
-    lfbp.font = &font_vga_8x16;
-    lfbp.bits_per_pixel = bytes_per_pixel*8;
-    lfbp.bytes_per_line = bytes_per_pixel*videomode->xres;
-    lfbp.width = videomode->xres;
-    lfbp.height = videomode->yres;
-    lfbp.flush = hdlcd_flush;
-    lfbp.text_columns = videomode->xres / 8;
-    lfbp.text_rows = videomode->yres / 16;
-    if ( lfb_init(&lfbp) < 0 )
-            return;
-    video_puts = lfb_scroll_puts;
-}
-
-void __init video_endboot(void) { }
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-arm/alternative.h 
b/xen/include/asm-arm/alternative.h
index 4e33d1cdf7..9b4b02811b 100644
--- a/xen/include/asm-arm/alternative.h
+++ b/xen/include/asm-arm/alternative.h
@@ -3,6 +3,8 @@
 
 #include <asm/cpufeature.h>
 
+#define ARM_CB_PATCH ARM_NCAPS
+
 #ifndef __ASSEMBLY__
 
 #include <xen/init.h>
@@ -18,16 +20,24 @@ struct alt_instr {
 };
 
 /* Xen: helpers used by common code. */
-#define __ALT_PTR(a,f)         ((u32 *)((void *)&(a)->f + (a)->f))
+#define __ALT_PTR(a,f)         ((void *)&(a)->f + (a)->f)
 #define ALT_ORIG_PTR(a)                __ALT_PTR(a, orig_offset)
 #define ALT_REPL_PTR(a)                __ALT_PTR(a, alt_offset)
 
+typedef void (*alternative_cb_t)(const struct alt_instr *alt,
+                                const uint32_t *origptr, uint32_t *updptr,
+                                int nr_inst);
+
 void __init apply_alternatives_all(void);
 int apply_alternatives(const struct alt_instr *start, const struct alt_instr 
*end);
 
-#define ALTINSTR_ENTRY(feature)                                                
      \
+#define ALTINSTR_ENTRY(feature, cb)                                          \
        " .word 661b - .\n"                             /* label           */ \
+       " .if " __stringify(cb) " == 0\n"                                     \
        " .word 663f - .\n"                             /* new instruction */ \
+       " .else\n"                                                            \
+       " .word " __stringify(cb) "- .\n"               /* callback */        \
+       " .endif\n"                                                           \
        " .hword " __stringify(feature) "\n"            /* feature bit     */ \
        " .byte 662b-661b\n"                            /* source len      */ \
        " .byte 664f-663f\n"                            /* replacement len */
@@ -45,15 +55,18 @@ int apply_alternatives(const struct alt_instr *start, const 
struct alt_instr *en
  * but most assemblers die if insn1 or insn2 have a .inst. This should
  * be fixed in a binutils release posterior to 2.25.51.0.2 (anything
  * containing commit 4e4d08cf7399b606 or c1baaddf8861).
+ *
+ * Alternatives with callbacks do not generate replacement instructions.
  */
-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled)    \
+#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb)        
\
        ".if "__stringify(cfg_enabled)" == 1\n"                         \
        "661:\n\t"                                                      \
        oldinstr "\n"                                                   \
        "662:\n"                                                        \
        ".pushsection .altinstructions,\"a\"\n"                         \
-       ALTINSTR_ENTRY(feature)                                         \
+       ALTINSTR_ENTRY(feature,cb)                                      \
        ".popsection\n"                                                 \
+       " .if " __stringify(cb) " == 0\n"                               \
        ".pushsection .altinstr_replacement, \"a\"\n"                   \
        "663:\n\t"                                                      \
        newinstr "\n"                                                   \
@@ -61,11 +74,17 @@ int apply_alternatives(const struct alt_instr *start, const 
struct alt_instr *en
        ".popsection\n\t"                                               \
        ".org   . - (664b-663b) + (662b-661b)\n\t"                      \
        ".org   . - (662b-661b) + (664b-663b)\n"                        \
+       ".else\n\t"                                                     \
+       "663:\n\t"                                                      \
+       "664:\n\t"                                                      \
+       ".endif\n"                                                      \
        ".endif\n"
 
 #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...)        \
-       __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
+       __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0)
 
+#define ALTERNATIVE_CB(oldinstr, cb) \
+       __ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM_CB_PATCH, 1, cb)
 #else
 
 #include <asm/asm_defns.h>
@@ -126,6 +145,14 @@ int apply_alternatives(const struct alt_instr *start, 
const struct alt_instr *en
 663:
 .endm
 
+.macro alternative_cb cb
+       .set .Lasm_alt_mode, 0
+       .pushsection .altinstructions, "a"
+       altinstruction_entry 661f, \cb, ARM_CB_PATCH, 662f-661f, 0
+       .popsection
+661:
+.endm
+
 /*
  * Complete an alternative code sequence.
  */
@@ -135,6 +162,13 @@ int apply_alternatives(const struct alt_instr *start, 
const struct alt_instr *en
        .org    . - (662b-661b) + (664b-663b)
 .endm
 
+/*
+ * Callback-based alternative epilogue
+ */
+.macro alternative_cb_end
+662:
+.endm
+
 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)  \
        alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
 
diff --git a/xen/include/asm-arm/arm64/macros.h 
b/xen/include/asm-arm/arm64/macros.h
new file mode 100644
index 0000000000..9c5e676b37
--- /dev/null
+++ b/xen/include/asm-arm/arm64/macros.h
@@ -0,0 +1,25 @@
+#ifndef __ASM_ARM_ARM64_MACROS_H
+#define __ASM_ARM_ARM64_MACROS_H
+
+    /*
+     * @dst: Result of get_cpu_info()
+     */
+    .macro  adr_cpu_info, dst
+    add     \dst, sp, #STACK_SIZE
+    and     \dst, \dst, #~(STACK_SIZE - 1)
+    sub     \dst, \dst, #CPUINFO_sizeof
+    .endm
+
+    /*
+     * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
+     * @sym: The name of the per-cpu variable
+     * @tmp: scratch register
+     */
+    .macro  ldr_this_cpu, dst, sym, tmp
+    ldr     \dst, =per_cpu__\sym
+    mrs     \tmp, tpidr_el2
+    ldr     \dst, [\dst, \tmp]
+    .endm
+
+#endif /* __ASM_ARM_ARM64_MACROS_H */
+
diff --git a/xen/include/asm-arm/cpuerrata.h b/xen/include/asm-arm/cpuerrata.h
index 4e45b237c8..55ddfda272 100644
--- a/xen/include/asm-arm/cpuerrata.h
+++ b/xen/include/asm-arm/cpuerrata.h
@@ -27,9 +27,51 @@ static inline bool check_workaround_##erratum(void)          
   \
 
 CHECK_WORKAROUND_HELPER(766422, ARM32_WORKAROUND_766422, CONFIG_ARM_32)
 CHECK_WORKAROUND_HELPER(834220, ARM64_WORKAROUND_834220, CONFIG_ARM_64)
+CHECK_WORKAROUND_HELPER(ssbd, ARM_SSBD, CONFIG_ARM_SSBD)
 
 #undef CHECK_WORKAROUND_HELPER
 
+enum ssbd_state
+{
+    ARM_SSBD_UNKNOWN,
+    ARM_SSBD_FORCE_DISABLE,
+    ARM_SSBD_RUNTIME,
+    ARM_SSBD_FORCE_ENABLE,
+    ARM_SSBD_MITIGATED,
+};
+
+#ifdef CONFIG_ARM_SSBD
+
+#include <asm/current.h>
+
+extern enum ssbd_state ssbd_state;
+
+static inline enum ssbd_state get_ssbd_state(void)
+{
+    return ssbd_state;
+}
+
+DECLARE_PER_CPU(register_t, ssbd_callback_required);
+
+static inline bool cpu_require_ssbd_mitigation(void)
+{
+    return this_cpu(ssbd_callback_required);
+}
+
+#else
+
+static inline bool cpu_require_ssbd_mitigation(void)
+{
+    return false;
+}
+
+static inline enum ssbd_state get_ssbd_state(void)
+{
+    return ARM_SSBD_UNKNOWN;
+}
+
+#endif
+
 #endif /* __ARM_CPUERRATA_H__ */
 /*
  * Local variables:
diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h
index e557a095af..3de6b54301 100644
--- a/xen/include/asm-arm/cpufeature.h
+++ b/xen/include/asm-arm/cpufeature.h
@@ -43,8 +43,9 @@
 #define SKIP_SYNCHRONIZE_SERROR_ENTRY_EXIT 5
 #define SKIP_CTXT_SWITCH_SERROR_SYNC 6
 #define ARM_HARDEN_BRANCH_PREDICTOR 7
+#define ARM_SSBD 8
 
-#define ARM_NCAPS           8
+#define ARM_NCAPS           9
 
 #ifndef __ASSEMBLY__
 
@@ -88,6 +89,7 @@ void update_cpu_capabilities(const struct 
arm_cpu_capabilities *caps,
                              const char *info);
 
 void enable_cpu_capabilities(const struct arm_cpu_capabilities *caps);
+int enable_nonboot_cpu_caps(const struct arm_cpu_capabilities *caps);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/xen/include/asm-arm/current.h b/xen/include/asm-arm/current.h
index 7a0971fdea..f9819b34fc 100644
--- a/xen/include/asm-arm/current.h
+++ b/xen/include/asm-arm/current.h
@@ -7,6 +7,10 @@
 #include <asm/percpu.h>
 #include <asm/processor.h>
 
+/* Tell whether the guest vCPU enabled Workaround 2 (i.e variant 4) */
+#define CPUINFO_WORKAROUND_2_FLAG_SHIFT   0
+#define CPUINFO_WORKAROUND_2_FLAG (_AC(1, U) << 
CPUINFO_WORKAROUND_2_FLAG_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 struct vcpu;
@@ -21,7 +25,7 @@ DECLARE_PER_CPU(struct vcpu *, curr_vcpu);
 struct cpu_info {
     struct cpu_user_regs guest_cpu_user_regs;
     unsigned long elr;
-    unsigned int pad;
+    uint32_t flags;
 };
 
 static inline struct cpu_info *get_cpu_info(void)
diff --git a/xen/include/asm-arm/macros.h b/xen/include/asm-arm/macros.h
index 5d837cb38b..1d4bb41d15 100644
--- a/xen/include/asm-arm/macros.h
+++ b/xen/include/asm-arm/macros.h
@@ -8,7 +8,7 @@
 #if defined (CONFIG_ARM_32)
 # include <asm/arm32/macros.h>
 #elif defined(CONFIG_ARM_64)
-/* No specific ARM64 macros for now */
+# include <asm/arm64/macros.h>
 #else
 # error "unknown ARM variant"
 #endif
diff --git a/xen/include/asm-arm/platforms/vexpress.h 
b/xen/include/asm-arm/platforms/vexpress.h
index 5cf3aba6f2..8b45d3a850 100644
--- a/xen/include/asm-arm/platforms/vexpress.h
+++ b/xen/include/asm-arm/platforms/vexpress.h
@@ -26,12 +26,6 @@
 /* Board-specific: base address of system controller */
 #define SP810_ADDRESS 0x1C020000
 
-#ifndef __ASSEMBLY__
-#include <xen/inttypes.h>
-
-int vexpress_syscfg(int write, int function, int device, uint32_t *data);
-#endif
-
 #endif /* __ASM_ARM_PLATFORMS_VEXPRESS_H */
 /*
  * Local variables:
diff --git a/xen/include/asm-arm/procinfo.h b/xen/include/asm-arm/procinfo.h
index 26306b35f8..02be56e348 100644
--- a/xen/include/asm-arm/procinfo.h
+++ b/xen/include/asm-arm/procinfo.h
@@ -35,9 +35,9 @@ struct proc_info_list {
     struct processor    *processor;
 };
 
-const __init struct proc_info_list *lookup_processor_type(void);
+const struct proc_info_list *lookup_processor_type(void);
 
-void __init processor_setup(void);
+void processor_setup(void);
 void processor_vcpu_initialise(struct vcpu *v);
 
 #endif
diff --git a/xen/include/asm-arm/psci.h b/xen/include/asm-arm/psci.h
index 9ac820e94a..832f77afff 100644
--- a/xen/include/asm-arm/psci.h
+++ b/xen/include/asm-arm/psci.h
@@ -20,6 +20,7 @@ extern uint32_t psci_ver;
 
 int psci_init(void);
 int call_psci_cpu_on(int cpu);
+void call_psci_cpu_off(void);
 void call_psci_system_off(void);
 void call_psci_system_reset(void);
 
diff --git a/xen/include/asm-arm/smccc.h b/xen/include/asm-arm/smccc.h
index 8342cc33fe..74c13f8419 100644
--- a/xen/include/asm-arm/smccc.h
+++ b/xen/include/asm-arm/smccc.h
@@ -254,11 +254,18 @@ struct arm_smccc_res {
 
 #define ARM_SMCCC_ARCH_WORKAROUND_1_FID             \
     ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,         \
-                      ARM_SMCCC_CONV_32,            \
-                      ARM_SMCCC_OWNER_ARCH,         \
-                      0x8000)
+                       ARM_SMCCC_CONV_32,           \
+                       ARM_SMCCC_OWNER_ARCH,        \
+                       0x8000)
+
+#define ARM_SMCCC_ARCH_WORKAROUND_2_FID             \
+    ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,         \
+                       ARM_SMCCC_CONV_32,           \
+                       ARM_SMCCC_OWNER_ARCH,        \
+                       0x7FFF)
 
 /* SMCCC error codes */
+#define ARM_SMCCC_NOT_REQUIRED          (-2)
 #define ARM_SMCCC_ERR_UNKNOWN_FUNCTION  (-1)
 #define ARM_SMCCC_NOT_SUPPORTED         (-1)
 #define ARM_SMCCC_SUCCESS               (0)
diff --git a/xen/include/asm-arm/traps.h b/xen/include/asm-arm/traps.h
index a0e5e92ebb..70b52d1d16 100644
--- a/xen/include/asm-arm/traps.h
+++ b/xen/include/asm-arm/traps.h
@@ -27,6 +27,10 @@ void handle_wo_wi(struct cpu_user_regs *regs, int regidx, 
bool read,
 void handle_ro_raz(struct cpu_user_regs *regs, int regidx, bool read,
                    const union hsr hsr, int min_el);
 
+/* Read only as value provided with 'val' argument */
+void handle_ro_read_val(struct cpu_user_regs *regs, int regidx, bool read,
+                        const union hsr hsr, int min_el, register_t val);
+
 /* Co-processor registers emulation (see arch/arm/vcpreg.c). */
 void do_cp15_32(struct cpu_user_regs *regs, const union hsr hsr);
 void do_cp15_64(struct cpu_user_regs *regs, const union hsr hsr);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.