summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/arm/spitz.c108
-rw-r--r--hw/arm/vexpress.c10
-rw-r--r--hw/arm/virt.c16
-rw-r--r--hw/block/pflash_cfi01.c20
-rw-r--r--hw/intc/armv7m_nvic.c5
-rw-r--r--kvm-all.c16
-rw-r--r--target-arm/cpu-qom.h9
-rw-r--r--target-arm/cpu.c1
-rw-r--r--target-arm/cpu.h16
-rw-r--r--target-arm/helper.c64
-rw-r--r--target-arm/kvm.c11
-rw-r--r--target-arm/kvm32.c16
-rw-r--r--target-arm/kvm64.c26
-rw-r--r--target-arm/kvm_arm.h12
-rw-r--r--target-arm/translate-a64.c5
15 files changed, 246 insertions, 89 deletions
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 5455dbf326..45e75081e8 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -285,9 +285,9 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
     spitz_keyboard_sense_update(s);
 }
 
-#define MOD_SHIFT   (1 << 7)
-#define MOD_CTRL    (1 << 8)
-#define MOD_FN      (1 << 9)
+#define SPITZ_MOD_SHIFT   (1 << 7)
+#define SPITZ_MOD_CTRL    (1 << 8)
+#define SPITZ_MOD_FN      (1 << 9)
 
 #define QUEUE_KEY(c)	s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
 
@@ -324,21 +324,26 @@ static void spitz_keyboard_handler(void *opaque, int keycode)
     }
 
     code = s->pre_map[mapcode = ((s->modifiers & 3) ?
-            (keycode | MOD_SHIFT) :
-            (keycode & ~MOD_SHIFT))];
+            (keycode | SPITZ_MOD_SHIFT) :
+            (keycode & ~SPITZ_MOD_SHIFT))];
 
     if (code != mapcode) {
 #if 0
-        if ((code & MOD_SHIFT) && !(s->modifiers & 1))
+        if ((code & SPITZ_MOD_SHIFT) && !(s->modifiers & 1)) {
             QUEUE_KEY(0x2a | (keycode & 0x80));
-        if ((code & MOD_CTRL ) && !(s->modifiers & 4))
+        }
+        if ((code & SPITZ_MOD_CTRL) && !(s->modifiers & 4)) {
             QUEUE_KEY(0x1d | (keycode & 0x80));
-        if ((code & MOD_FN   ) && !(s->modifiers & 8))
+        }
+        if ((code & SPITZ_MOD_FN) && !(s->modifiers & 8)) {
             QUEUE_KEY(0x38 | (keycode & 0x80));
-        if ((code & MOD_FN   ) && (s->modifiers & 1))
+        }
+        if ((code & SPITZ_MOD_FN) && (s->modifiers & 1)) {
             QUEUE_KEY(0x2a | (~keycode & 0x80));
-        if ((code & MOD_FN   ) && (s->modifiers & 2))
+        }
+        if ((code & SPITZ_MOD_FN) && (s->modifiers & 2)) {
             QUEUE_KEY(0x36 | (~keycode & 0x80));
+        }
 #else
         if (keycode & 0x80) {
             if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
@@ -353,24 +358,27 @@ static void spitz_keyboard_handler(void *opaque, int keycode)
                 QUEUE_KEY(0x36);
             s->imodifiers = 0;
         } else {
-            if ((code & MOD_SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
+            if ((code & SPITZ_MOD_SHIFT) &&
+                !((s->modifiers | s->imodifiers) & 1)) {
                 QUEUE_KEY(0x2a);
                 s->imodifiers |= 1;
             }
-            if ((code & MOD_CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
+            if ((code & SPITZ_MOD_CTRL) &&
+                !((s->modifiers | s->imodifiers) & 4)) {
                 QUEUE_KEY(0x1d);
                 s->imodifiers |= 4;
             }
-            if ((code & MOD_FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
+            if ((code & SPITZ_MOD_FN) &&
+                !((s->modifiers | s->imodifiers) & 8)) {
                 QUEUE_KEY(0x38);
                 s->imodifiers |= 8;
             }
-            if ((code & MOD_FN   ) && (s->modifiers & 1) &&
+            if ((code & SPITZ_MOD_FN) && (s->modifiers & 1) &&
                             !(s->imodifiers & 0x10)) {
                 QUEUE_KEY(0x2a | 0x80);
                 s->imodifiers |= 0x10;
             }
-            if ((code & MOD_FN   ) && (s->modifiers & 2) &&
+            if ((code & SPITZ_MOD_FN) && (s->modifiers & 2) &&
                             !(s->imodifiers & 0x20)) {
                 QUEUE_KEY(0x36 | 0x80);
                 s->imodifiers |= 0x20;
@@ -402,38 +410,38 @@ static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
     int i;
     for (i = 0; i < 0x100; i ++)
         s->pre_map[i] = i;
-    s->pre_map[0x02 | MOD_SHIFT	] = 0x02 | MOD_SHIFT;	/* exclam */
-    s->pre_map[0x28 | MOD_SHIFT	] = 0x03 | MOD_SHIFT;	/* quotedbl */
-    s->pre_map[0x04 | MOD_SHIFT	] = 0x04 | MOD_SHIFT;	/* numbersign */
-    s->pre_map[0x05 | MOD_SHIFT	] = 0x05 | MOD_SHIFT;	/* dollar */
-    s->pre_map[0x06 | MOD_SHIFT	] = 0x06 | MOD_SHIFT;	/* percent */
-    s->pre_map[0x08 | MOD_SHIFT	] = 0x07 | MOD_SHIFT;	/* ampersand */
-    s->pre_map[0x28		] = 0x08 | MOD_SHIFT;	/* apostrophe */
-    s->pre_map[0x0a | MOD_SHIFT	] = 0x09 | MOD_SHIFT;	/* parenleft */
-    s->pre_map[0x0b | MOD_SHIFT	] = 0x0a | MOD_SHIFT;	/* parenright */
-    s->pre_map[0x29 | MOD_SHIFT	] = 0x0b | MOD_SHIFT;	/* asciitilde */
-    s->pre_map[0x03 | MOD_SHIFT	] = 0x0c | MOD_SHIFT;	/* at */
-    s->pre_map[0xd3		] = 0x0e | MOD_FN;	/* Delete */
-    s->pre_map[0x3a		] = 0x0f | MOD_FN;	/* Caps_Lock */
-    s->pre_map[0x07 | MOD_SHIFT	] = 0x11 | MOD_FN;	/* asciicircum */
-    s->pre_map[0x0d		] = 0x12 | MOD_FN;	/* equal */
-    s->pre_map[0x0d | MOD_SHIFT	] = 0x13 | MOD_FN;	/* plus */
-    s->pre_map[0x1a		] = 0x14 | MOD_FN;	/* bracketleft */
-    s->pre_map[0x1b		] = 0x15 | MOD_FN;	/* bracketright */
-    s->pre_map[0x1a | MOD_SHIFT	] = 0x16 | MOD_FN;	/* braceleft */
-    s->pre_map[0x1b | MOD_SHIFT	] = 0x17 | MOD_FN;	/* braceright */
-    s->pre_map[0x27		] = 0x22 | MOD_FN;	/* semicolon */
-    s->pre_map[0x27 | MOD_SHIFT	] = 0x23 | MOD_FN;	/* colon */
-    s->pre_map[0x09 | MOD_SHIFT	] = 0x24 | MOD_FN;	/* asterisk */
-    s->pre_map[0x2b		] = 0x25 | MOD_FN;	/* backslash */
-    s->pre_map[0x2b | MOD_SHIFT	] = 0x26 | MOD_FN;	/* bar */
-    s->pre_map[0x0c | MOD_SHIFT	] = 0x30 | MOD_FN;	/* underscore */
-    s->pre_map[0x33 | MOD_SHIFT	] = 0x33 | MOD_FN;	/* less */
-    s->pre_map[0x35		] = 0x33 | MOD_SHIFT;	/* slash */
-    s->pre_map[0x34 | MOD_SHIFT	] = 0x34 | MOD_FN;	/* greater */
-    s->pre_map[0x35 | MOD_SHIFT	] = 0x34 | MOD_SHIFT;	/* question */
-    s->pre_map[0x49		] = 0x48 | MOD_FN;	/* Page_Up */
-    s->pre_map[0x51		] = 0x50 | MOD_FN;	/* Page_Down */
+    s->pre_map[0x02 | SPITZ_MOD_SHIFT] = 0x02 | SPITZ_MOD_SHIFT; /* exclam */
+    s->pre_map[0x28 | SPITZ_MOD_SHIFT] = 0x03 | SPITZ_MOD_SHIFT; /* quotedbl */
+    s->pre_map[0x04 | SPITZ_MOD_SHIFT] = 0x04 | SPITZ_MOD_SHIFT; /* # */
+    s->pre_map[0x05 | SPITZ_MOD_SHIFT] = 0x05 | SPITZ_MOD_SHIFT; /* dollar */
+    s->pre_map[0x06 | SPITZ_MOD_SHIFT] = 0x06 | SPITZ_MOD_SHIFT; /* percent */
+    s->pre_map[0x08 | SPITZ_MOD_SHIFT] = 0x07 | SPITZ_MOD_SHIFT; /* ampersand */
+    s->pre_map[0x28]                   = 0x08 | SPITZ_MOD_SHIFT; /* ' */
+    s->pre_map[0x0a | SPITZ_MOD_SHIFT] = 0x09 | SPITZ_MOD_SHIFT; /* ( */
+    s->pre_map[0x0b | SPITZ_MOD_SHIFT] = 0x0a | SPITZ_MOD_SHIFT; /* ) */
+    s->pre_map[0x29 | SPITZ_MOD_SHIFT] = 0x0b | SPITZ_MOD_SHIFT; /* tilde */
+    s->pre_map[0x03 | SPITZ_MOD_SHIFT] = 0x0c | SPITZ_MOD_SHIFT; /* at */
+    s->pre_map[0xd3]                   = 0x0e | SPITZ_MOD_FN;    /* Delete */
+    s->pre_map[0x3a]                   = 0x0f | SPITZ_MOD_FN;    /* Caps_Lock */
+    s->pre_map[0x07 | SPITZ_MOD_SHIFT] = 0x11 | SPITZ_MOD_FN;    /* ^ */
+    s->pre_map[0x0d]                   = 0x12 | SPITZ_MOD_FN;    /* equal */
+    s->pre_map[0x0d | SPITZ_MOD_SHIFT] = 0x13 | SPITZ_MOD_FN;    /* plus */
+    s->pre_map[0x1a]                   = 0x14 | SPITZ_MOD_FN;    /* [ */
+    s->pre_map[0x1b]                   = 0x15 | SPITZ_MOD_FN;    /* ] */
+    s->pre_map[0x1a | SPITZ_MOD_SHIFT] = 0x16 | SPITZ_MOD_FN;    /* { */
+    s->pre_map[0x1b | SPITZ_MOD_SHIFT] = 0x17 | SPITZ_MOD_FN;    /* } */
+    s->pre_map[0x27]                   = 0x22 | SPITZ_MOD_FN;    /* semicolon */
+    s->pre_map[0x27 | SPITZ_MOD_SHIFT] = 0x23 | SPITZ_MOD_FN;    /* colon */
+    s->pre_map[0x09 | SPITZ_MOD_SHIFT] = 0x24 | SPITZ_MOD_FN;    /* asterisk */
+    s->pre_map[0x2b]                   = 0x25 | SPITZ_MOD_FN;    /* backslash */
+    s->pre_map[0x2b | SPITZ_MOD_SHIFT] = 0x26 | SPITZ_MOD_FN;    /* bar */
+    s->pre_map[0x0c | SPITZ_MOD_SHIFT] = 0x30 | SPITZ_MOD_FN;    /* _ */
+    s->pre_map[0x33 | SPITZ_MOD_SHIFT] = 0x33 | SPITZ_MOD_FN;    /* less */
+    s->pre_map[0x35]                   = 0x33 | SPITZ_MOD_SHIFT; /* slash */
+    s->pre_map[0x34 | SPITZ_MOD_SHIFT] = 0x34 | SPITZ_MOD_FN;    /* greater */
+    s->pre_map[0x35 | SPITZ_MOD_SHIFT] = 0x34 | SPITZ_MOD_SHIFT; /* question */
+    s->pre_map[0x49]                   = 0x48 | SPITZ_MOD_FN;    /* Page_Up */
+    s->pre_map[0x51]                   = 0x50 | SPITZ_MOD_FN;    /* Page_Down */
 
     s->modifiers = 0;
     s->imodifiers = 0;
@@ -441,9 +449,9 @@ static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
     s->fifolen = 0;
 }
 
-#undef MOD_SHIFT
-#undef MOD_CTRL
-#undef MOD_FN
+#undef SPITZ_MOD_SHIFT
+#undef SPITZ_MOD_CTRL
+#undef SPITZ_MOD_FN
 
 static int spitz_keyboard_post_load(void *opaque, int version_id)
 {
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index f311595d67..3d83e6c98d 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -533,7 +533,15 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
      * If a bios file was provided, attempt to map it into memory
      */
     if (bios_name) {
-        const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        const char *fn;
+
+        if (drive_get(IF_PFLASH, 0, 0)) {
+            error_report("The contents of the first flash device may be "
+                         "specified with -bios or with -drive if=pflash... "
+                         "but you cannot use both options at once");
+            exit(1);
+        }
+        fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (!fn || load_image_targphys(fn, map[VE_NORFLASH0],
                                        VEXPRESS_FLASH_SIZE) < 0) {
             error_report("Could not load ROM image '%s'", bios_name);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 3b55a4bf7d..72fe030e93 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -180,10 +180,23 @@ static void create_fdt(VirtBoardInfo *vbi)
                                 "clk24mhz");
     qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle);
 
+}
+
+static void fdt_add_psci_node(const VirtBoardInfo *vbi)
+{
+    void *fdt = vbi->fdt;
+    ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
+
     /* No PSCI for TCG yet */
     if (kvm_enabled()) {
         qemu_fdt_add_subnode(fdt, "/psci");
-        qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+        if (armcpu->psci_version == 2) {
+            const char comp[] = "arm,psci-0.2\0arm,psci";
+            qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
+        } else {
+            qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+        }
+
         qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc");
         qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend",
                                   PSCI_FN_CPU_SUSPEND);
@@ -446,6 +459,7 @@ static void machvirt_init(MachineState *machine)
         object_property_set_bool(cpuobj, true, "realized", NULL);
     }
     fdt_add_cpu_nodes(vbi);
+    fdt_add_psci_node(vbi);
 
     memory_region_init_ram(ram, NULL, "mach-virt.ram", machine->ram_size);
     vmstate_register_ram_global(ram);
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 0c95d53dca..f9507b4e5a 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -748,9 +748,18 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
     pflash_t *pfl = CFI_PFLASH01(dev);
     uint64_t total_len;
     int ret;
+    uint64_t blocks_per_device, device_len;
+    int num_devices;
 
     total_len = pfl->sector_len * pfl->nb_blocs;
 
+    /* These are only used to expose the parameters of each device
+     * in the cfi_table[].
+     */
+    num_devices = pfl->device_width ? (pfl->bank_width / pfl->device_width) : 1;
+    blocks_per_device = pfl->nb_blocs / num_devices;
+    device_len = pfl->sector_len * blocks_per_device;
+
     /* XXX: to be fixed */
 #if 0
     if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
@@ -838,7 +847,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
     /* Max timeout for chip erase */
     pfl->cfi_table[0x26] = 0x00;
     /* Device size */
-    pfl->cfi_table[0x27] = ctz32(total_len); // + 1;
+    pfl->cfi_table[0x27] = ctz32(device_len); /* + 1; */
     /* Flash device interface (8 & 16 bits) */
     pfl->cfi_table[0x28] = 0x02;
     pfl->cfi_table[0x29] = 0x00;
@@ -854,8 +863,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
     /* Number of erase block regions (uniform) */
     pfl->cfi_table[0x2C] = 0x01;
     /* Erase block region 1 */
-    pfl->cfi_table[0x2D] = pfl->nb_blocs - 1;
-    pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8;
+    pfl->cfi_table[0x2D] = blocks_per_device - 1;
+    pfl->cfi_table[0x2E] = (blocks_per_device - 1) >> 8;
     pfl->cfi_table[0x2F] = pfl->sector_len >> 8;
     pfl->cfi_table[0x30] = pfl->sector_len >> 16;
 
@@ -882,6 +891,11 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
 
 static Property pflash_cfi01_properties[] = {
     DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
+    /* num-blocks is the number of blocks actually visible to the guest,
+     * ie the total size of the device divided by the sector length.
+     * If we're emulating flash devices wired in parallel the actual
+     * number of blocks per indvidual device will differ.
+     */
     DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
     DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
     /* width here is the overall width of this QEMU device in bytes.
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 75d9c6e41e..1a7af450a7 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -211,7 +211,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
         cpu = ARM_CPU(current_cpu);
         return cpu->env.v7m.vecbase;
     case 0xd0c: /* Application Interrupt/Reset Control.  */
-        return 0xfa05000;
+        return 0xfa050000;
     case 0xd10: /* System Control.  */
         /* TODO: Implement SLEEPONEXIT.  */
         return 0;
@@ -346,6 +346,9 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
             if (value & 5) {
                 qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
             }
+            if (value & 0x700) {
+                qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
+            }
         }
         break;
     case 0xd10: /* System Control.  */
diff --git a/kvm-all.c b/kvm-all.c
index 4e19eff0ef..ef9f0f2213 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1751,6 +1751,22 @@ int kvm_cpu_exec(CPUState *cpu)
         case KVM_EXIT_INTERNAL_ERROR:
             ret = kvm_handle_internal_error(cpu, run);
             break;
+        case KVM_EXIT_SYSTEM_EVENT:
+            switch (run->system_event.type) {
+            case KVM_SYSTEM_EVENT_SHUTDOWN:
+                qemu_system_shutdown_request();
+                ret = EXCP_INTERRUPT;
+                break;
+            case KVM_SYSTEM_EVENT_RESET:
+                qemu_system_reset_request();
+                ret = EXCP_INTERRUPT;
+                break;
+            default:
+                DPRINTF("kvm_arch_handle_exit\n");
+                ret = kvm_arch_handle_exit(cpu, run);
+                break;
+            }
+            break;
         default:
             DPRINTF("kvm_arch_handle_exit\n");
             ret = kvm_arch_handle_exit(cpu, run);
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index edc7f262fc..eaee9447ee 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -94,6 +94,12 @@ typedef struct ARMCPU {
     /* 'compatible' string for this CPU for Linux device trees */
     const char *dtb_compatible;
 
+    /* PSCI version for this CPU
+     * Bits[31:16] = Major Version
+     * Bits[15:0] = Minor Version
+     */
+    uint32_t psci_version;
+
     /* Should CPU start in PSCI powered-off state? */
     bool start_powered_off;
 
@@ -102,6 +108,9 @@ typedef struct ARMCPU {
      */
     uint32_t kvm_target;
 
+    /* KVM init features for this CPU */
+    uint32_t kvm_init_features[7];
+
     /* The instance init functions for implementation-specific subclasses
      * set these fields to specify the implementation-dependent values of
      * various constant registers and reset values of non-constant
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index b8778350f7..05e52e0e83 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -260,6 +260,7 @@ static void arm_cpu_initfn(Object *obj)
      * picky DTB consumer will also provide a helpful error message.
      */
     cpu->dtb_compatible = "qemu,unknown";
+    cpu->psci_version = 1; /* By default assume PSCI v0.1 */
     cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
 
     if (tcg_enabled() && !inited) {
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 79e7f82515..369d4727ae 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -430,6 +430,22 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
 /* Execution state bits.  MRS read as zero, MSR writes ignored.  */
 #define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J)
 
+#define TTBCR_N      (7U << 0) /* TTBCR.EAE==0 */
+#define TTBCR_T0SZ   (7U << 0) /* TTBCR.EAE==1 */
+#define TTBCR_PD0    (1U << 4)
+#define TTBCR_PD1    (1U << 5)
+#define TTBCR_EPD0   (1U << 7)
+#define TTBCR_IRGN0  (3U << 8)
+#define TTBCR_ORGN0  (3U << 10)
+#define TTBCR_SH0    (3U << 12)
+#define TTBCR_T1SZ   (3U << 16)
+#define TTBCR_A1     (1U << 22)
+#define TTBCR_EPD1   (1U << 23)
+#define TTBCR_IRGN1  (3U << 24)
+#define TTBCR_ORGN1  (3U << 26)
+#define TTBCR_SH1    (1U << 28)
+#define TTBCR_EAE    (1U << 31)
+
 /* Bit definitions for ARMv8 SPSR (PSTATE) format.
  * Only these are valid when in AArch64 mode; in
  * AArch32 mode SPSRs are basically CPSR-format.
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 050c40981b..ed4d2bb419 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -312,7 +312,7 @@ static inline bool extended_addresses_enabled(CPUARMState *env)
 {
     return arm_el_is_aa64(env, 1)
         || ((arm_feature(env, ARM_FEATURE_LPAE)
-             && (env->cp15.c2_control & (1U << 31))));
+             && (env->cp15.c2_control & TTBCR_EAE)));
 }
 
 static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
@@ -1413,11 +1413,22 @@ static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     int maskshift = extract32(value, 0, 3);
 
-    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
-        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
-    } else {
-        value &= 7;
+    if (!arm_feature(env, ARM_FEATURE_V8)) {
+        if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) {
+            /* Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when
+             * using Long-desciptor translation table format */
+            value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
+        } else if (arm_feature(env, ARM_FEATURE_EL3)) {
+            /* In an implementation that includes the Security Extensions
+             * TTBCR has additional fields PD0 [4] and PD1 [5] for
+             * Short-descriptor translation table format.
+             */
+            value &= TTBCR_PD1 | TTBCR_PD0 | TTBCR_N;
+        } else {
+            value &= TTBCR_N;
+        }
     }
+
     /* Note that we always calculate c2_mask and c2_base_mask, but
      * they are only used for short-descriptor tables (ie if EAE is 0);
      * for long-descriptor tables the TTBCR fields are used differently
@@ -3540,17 +3551,24 @@ static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
   }
 }
 
-static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
+static bool get_level1_table_address(CPUARMState *env, uint32_t *table,
+                                         uint32_t address)
 {
-    uint32_t table;
-
-    if (address & env->cp15.c2_mask)
-        table = env->cp15.ttbr1_el1 & 0xffffc000;
-    else
-        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
-
-    table |= (address >> 18) & 0x3ffc;
-    return table;
+    if (address & env->cp15.c2_mask) {
+        if ((env->cp15.c2_control & TTBCR_PD1)) {
+            /* Translation table walk disabled for TTBR1 */
+            return false;
+        }
+        *table = env->cp15.ttbr1_el1 & 0xffffc000;
+    } else {
+        if ((env->cp15.c2_control & TTBCR_PD0)) {
+            /* Translation table walk disabled for TTBR0 */
+            return false;
+        }
+        *table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
+    }
+    *table |= (address >> 18) & 0x3ffc;
+    return true;
 }
 
 static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
@@ -3563,13 +3581,17 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
     uint32_t desc;
     int type;
     int ap;
-    int domain;
+    int domain = 0;
     int domain_prot;
     hwaddr phys_addr;
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
@@ -3667,7 +3689,11 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
-    table = get_level1_table_address(env, address);
+    if (!get_level1_table_address(env, &table, address)) {
+        /* Section translation fault if page walk is disabled by PD0 or PD1 */
+        code = 5;
+        goto do_fault;
+    }
     desc = ldl_phys(cs->as, table);
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
@@ -3926,7 +3952,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
          * These are basically the same thing, although the number
          * of bits we pull in from the vaddr varies.
          */
-        page_size = (1 << ((granule_sz * (4 - level)) + 3));
+        page_size = (1ULL << ((granule_sz * (4 - level)) + 3));
         descaddr |= (address & (page_size - 1));
         /* Extract attributes from the descriptor and merge with table attrs */
         attrs = extract64(descriptor, 2, 10)
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 39202d7eea..319784d689 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -27,6 +27,17 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+int kvm_arm_vcpu_init(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    struct kvm_vcpu_init init;
+
+    init.target = cpu->kvm_target;
+    memcpy(init.features, cpu->kvm_init_features, sizeof(init.features));
+
+    return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+}
+
 bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
                                       int *fdarray,
                                       struct kvm_vcpu_init *init)
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index b79750c57e..068af7db57 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -166,7 +166,6 @@ static int compare_u64(const void *a, const void *b)
 
 int kvm_arch_init_vcpu(CPUState *cs)
 {
-    struct kvm_vcpu_init init;
     int i, ret, arraylen;
     uint64_t v;
     struct kvm_one_reg r;
@@ -179,15 +178,22 @@ int kvm_arch_init_vcpu(CPUState *cs)
         return -EINVAL;
     }
 
-    init.target = cpu->kvm_target;
-    memset(init.features, 0, sizeof(init.features));
+    /* Determine init features for this CPU */
+    memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
     if (cpu->start_powered_off) {
-        init.features[0] = 1 << KVM_ARM_VCPU_POWER_OFF;
+        cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
+    }
+    if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
+        cpu->psci_version = 2;
+        cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
     }
-    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+
+    /* Do KVM_ARM_VCPU_INIT ioctl */
+    ret = kvm_arm_vcpu_init(cs);
     if (ret) {
         return ret;
     }
+
     /* Query the kernel to make sure it supports 32 VFP
      * registers: QEMU's "cortex-a15" CPU is always a
      * VFP-D32 core. The simplest way to do this is just
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
index 70f311bed6..5d217ca2ad 100644
--- a/target-arm/kvm64.c
+++ b/target-arm/kvm64.c
@@ -77,9 +77,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
 
 int kvm_arch_init_vcpu(CPUState *cs)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    struct kvm_vcpu_init init;
     int ret;
+    ARMCPU *cpu = ARM_CPU(cs);
 
     if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
         !arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
@@ -87,16 +86,25 @@ int kvm_arch_init_vcpu(CPUState *cs)
         return -EINVAL;
     }
 
-    init.target = cpu->kvm_target;
-    memset(init.features, 0, sizeof(init.features));
+    /* Determine init features for this CPU */
+    memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
     if (cpu->start_powered_off) {
-        init.features[0] = 1 << KVM_ARM_VCPU_POWER_OFF;
+        cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
+    }
+    if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
+        cpu->psci_version = 2;
+        cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
+    }
+
+    /* Do KVM_ARM_VCPU_INIT ioctl */
+    ret = kvm_arm_vcpu_init(cs);
+    if (ret) {
+        return ret;
     }
-    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
 
     /* TODO : support for save/restore/reset of system regs via tuple list */
 
-    return ret;
+    return 0;
 }
 
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
@@ -262,4 +270,8 @@ int kvm_arch_get_registers(CPUState *cs)
 
 void kvm_arm_reset_vcpu(ARMCPU *cpu)
 {
+    /* Re-init VCPU so that all registers are set to
+     * their respective reset values.
+     */
+    kvm_arm_vcpu_init(CPU(cpu));
 }
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index dc4e2336fa..af93105517 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -15,6 +15,18 @@
 #include "exec/memory.h"
 
 /**
+ * kvm_arm_vcpu_init:
+ * @cs: CPUState
+ *
+ * Initialize (or reinitialize) the VCPU by invoking the
+ * KVM_ARM_VCPU_INIT ioctl with the CPU type and feature
+ * bitmask specified in the CPUState.
+ *
+ * Returns: 0 if success else < 0 error code
+ */
+int kvm_arm_vcpu_init(CPUState *cs);
+
+/**
  * kvm_arm_register_device:
  * @mr: memory region for this device
  * @devid: the KVM device ID
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 63ad787e9f..33b5025fee 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -6539,7 +6539,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
     tcg_shift = tcg_const_i32(fracbits);
 
     if (is_double) {
-        int maxpass = is_scalar ? 1 : is_q ? 2 : 1;
+        int maxpass = is_scalar ? 1 : 2;
 
         for (pass = 0; pass < maxpass; pass++) {
             TCGv_i64 tcg_op = tcg_temp_new_i64();
@@ -9052,7 +9052,8 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
     }
 
     if (size == 3) {
-        for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
+        assert(is_q);
+        for (pass = 0; pass < 2; pass++) {
             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
             TCGv_i64 tcg_res = tcg_temp_new_i64();