KVM/ARM Fixes for Linux v4.6-rc2.

Fixes a bug that corrupts stage-2 translationson 16-bit VMID equipped systems
 and fixes CPU PM and Hotplug after the EL2 init code has been moved to C.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJW/jk7AAoJEEtpOizt6ddyL1EH/RcWeOllk64dLpFouig8F+Oe
 Lm7b6okB8qJjZdpyStqWYGEWjd2kwZ5buUqmCf8kNPrQ143c3xwKAeb3hBly+6vK
 RDbef6nZqqPihbYTohFzquQKOY8haselciYwmW6+Lkq8uaZ6jNSTbDKwjtDI8rry
 +1FuSZKrUVz5xaj5qn4gDJjTmnZbX5rcdtwN3S9/AikPDtNZFZHcj8Qn/ps9jjLP
 jB2XCIRXFZdxxYOAlYbRx+sTVEnsTBYAwCrvFErJAfBH8m0QR94mn1epU7QzdrKN
 dnKbG4IYy19aPmOpfhGuQrUZ1G09QNSWQQ+BhG0pvq0/GBD0exkMdRssp11AXoI=
 =XE1Y
 -----END PGP SIGNATURE-----

Merge tag 'kvm-arm-for-4.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD

KVM/ARM Fixes for Linux v4.6-rc2.

Fixes a bug that corrupts stage-2 translationson 16-bit VMID equipped systems
and fixes CPU PM and Hotplug after the EL2 init code has been moved to C.
This commit is contained in:
Paolo Bonzini 2016-04-01 12:10:06 +02:00
commit c26e5f303a
4 changed files with 43 additions and 22 deletions

View File

@ -1061,15 +1061,27 @@ static void cpu_init_hyp_mode(void *dummy)
kvm_arm_init_debug(); kvm_arm_init_debug();
} }
static void cpu_hyp_reinit(void)
{
if (is_kernel_in_hyp_mode()) {
/*
* cpu_init_stage2() is safe to call even if the PM
* event was cancelled before the CPU was reset.
*/
cpu_init_stage2(NULL);
} else {
if (__hyp_get_vectors() == hyp_default_vectors)
cpu_init_hyp_mode(NULL);
}
}
static int hyp_init_cpu_notify(struct notifier_block *self, static int hyp_init_cpu_notify(struct notifier_block *self,
unsigned long action, void *cpu) unsigned long action, void *cpu)
{ {
switch (action) { switch (action) {
case CPU_STARTING: case CPU_STARTING:
case CPU_STARTING_FROZEN: case CPU_STARTING_FROZEN:
if (__hyp_get_vectors() == hyp_default_vectors) cpu_hyp_reinit();
cpu_init_hyp_mode(NULL);
break;
} }
return NOTIFY_OK; return NOTIFY_OK;
@ -1084,9 +1096,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
unsigned long cmd, unsigned long cmd,
void *v) void *v)
{ {
if (cmd == CPU_PM_EXIT && if (cmd == CPU_PM_EXIT) {
__hyp_get_vectors() == hyp_default_vectors) { cpu_hyp_reinit();
cpu_init_hyp_mode(NULL);
return NOTIFY_OK; return NOTIFY_OK;
} }
@ -1127,6 +1138,22 @@ static int init_subsystems(void)
{ {
int err; int err;
/*
* Register CPU Hotplug notifier
*/
cpu_notifier_register_begin();
err = __register_cpu_notifier(&hyp_init_cpu_nb);
cpu_notifier_register_done();
if (err) {
kvm_err("Cannot register KVM init CPU notifier (%d)\n", err);
return err;
}
/*
* Register CPU lower-power notifier
*/
hyp_cpu_pm_init();
/* /*
* Init HYP view of VGIC * Init HYP view of VGIC
*/ */
@ -1270,19 +1297,6 @@ static int init_hyp_mode(void)
free_boot_hyp_pgd(); free_boot_hyp_pgd();
#endif #endif
cpu_notifier_register_begin();
err = __register_cpu_notifier(&hyp_init_cpu_nb);
cpu_notifier_register_done();
if (err) {
kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
goto out_err;
}
hyp_cpu_pm_init();
/* set size of VMID supported by CPU */ /* set size of VMID supported by CPU */
kvm_vmid_bits = kvm_get_vmid_bits(); kvm_vmid_bits = kvm_get_vmid_bits();
kvm_info("%d-bit VMID\n", kvm_vmid_bits); kvm_info("%d-bit VMID\n", kvm_vmid_bits);

View File

@ -124,7 +124,9 @@
#define VTCR_EL2_SL0_LVL1 (1 << 6) #define VTCR_EL2_SL0_LVL1 (1 << 6)
#define VTCR_EL2_T0SZ_MASK 0x3f #define VTCR_EL2_T0SZ_MASK 0x3f
#define VTCR_EL2_T0SZ_40B 24 #define VTCR_EL2_T0SZ_40B 24
#define VTCR_EL2_VS 19 #define VTCR_EL2_VS_SHIFT 19
#define VTCR_EL2_VS_8BIT (0 << VTCR_EL2_VS_SHIFT)
#define VTCR_EL2_VS_16BIT (1 << VTCR_EL2_VS_SHIFT)
/* /*
* We configure the Stage-2 page tables to always restrict the IPA space to be * We configure the Stage-2 page tables to always restrict the IPA space to be

View File

@ -141,6 +141,9 @@
#define ID_AA64MMFR1_VMIDBITS_SHIFT 4 #define ID_AA64MMFR1_VMIDBITS_SHIFT 4
#define ID_AA64MMFR1_HADBS_SHIFT 0 #define ID_AA64MMFR1_HADBS_SHIFT 0
#define ID_AA64MMFR1_VMIDBITS_8 0
#define ID_AA64MMFR1_VMIDBITS_16 2
/* id_aa64mmfr2 */ /* id_aa64mmfr2 */
#define ID_AA64MMFR2_UAO_SHIFT 4 #define ID_AA64MMFR2_UAO_SHIFT 4

View File

@ -36,8 +36,10 @@ void __hyp_text __init_stage2_translation(void)
* Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
* bit in VTCR_EL2. * bit in VTCR_EL2.
*/ */
tmp = (read_sysreg(id_aa64mmfr1_el1) >> 4) & 0xf; tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_VMIDBITS_SHIFT) & 0xf;
val |= (tmp == 2) ? VTCR_EL2_VS : 0; val |= (tmp == ID_AA64MMFR1_VMIDBITS_16) ?
VTCR_EL2_VS_16BIT :
VTCR_EL2_VS_8BIT;
write_sysreg(val, vtcr_el2); write_sysreg(val, vtcr_el2);
} }