Merge branch kvm-arm64/misc-5.19 into kvmarm-master/next

* kvm-arm64/misc-5.19:
  : .
  : Misc fixes and general improvements for KVMM/arm64:
  :
  : - Better handle out of sequence sysregs in the global tables
  :
  : - Remove a couple of unnecessary loads from constant pool
  :
  : - Drop unnecessary pKVM checks
  :
  : - Add all known M1 implementations to the SEIS workaround
  :
  : - Cleanup kerneldoc warnings
  : .
  KVM: arm64: vgic-v3: List M1 Pro/Max as requiring the SEIS workaround
  KVM: arm64: pkvm: Don't mask already zeroed FEAT_SVE
  KVM: arm64: pkvm: Drop unnecessary FP/SIMD trap handler
  KVM: arm64: nvhe: Eliminate kernel-doc warnings
  KVM: arm64: Avoid unnecessary absolute addressing via literals
  KVM: arm64: Print emulated register table name when it is unsorted
  KVM: arm64: Don't BUG_ON() if emulated register table is unsorted

Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Marc Zyngier 2022-05-16 17:48:36 +01:00
commit 822ca7f82b
8 changed files with 46 additions and 47 deletions

View file

@ -118,6 +118,10 @@
#define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_ICESTORM 0x022
#define APPLE_CPU_PART_M1_FIRESTORM 0x023 #define APPLE_CPU_PART_M1_FIRESTORM 0x023
#define APPLE_CPU_PART_M1_ICESTORM_PRO 0x024
#define APPLE_CPU_PART_M1_FIRESTORM_PRO 0x025
#define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
#define APPLE_CPU_PART_M1_FIRESTORM_MAX 0x029
#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
@ -164,6 +168,10 @@
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
#define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
#define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
#define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
#define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
#define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
/* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
#define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX #define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX

View file

@ -705,7 +705,7 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu);
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu); void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
void kvm_sys_reg_table_init(void); int kvm_sys_reg_table_init(void);
/* MMIO helpers */ /* MMIO helpers */
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data); void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);

View file

@ -1829,8 +1829,6 @@ static int init_subsystems(void)
kvm_register_perf_callbacks(NULL); kvm_register_perf_callbacks(NULL);
kvm_sys_reg_table_init();
out: out:
if (err || !is_protected_kvm_enabled()) if (err || !is_protected_kvm_enabled())
on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); on_each_cpu(_kvm_arch_hardware_disable, NULL, 1);
@ -2189,6 +2187,12 @@ int kvm_arch_init(void *opaque)
return -ENODEV; return -ENODEV;
} }
err = kvm_sys_reg_table_init();
if (err) {
kvm_info("Error initializing system register tables");
return err;
}
in_hyp_mode = is_kernel_in_hyp_mode(); in_hyp_mode = is_kernel_in_hyp_mode();
if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) || if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||

View file

@ -80,7 +80,7 @@ SYM_FUNC_START(__hyp_do_panic)
mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h) PSR_MODE_EL1h)
msr spsr_el2, lr msr spsr_el2, lr
ldr lr, =nvhe_hyp_panic_handler adr_l lr, nvhe_hyp_panic_handler
hyp_kimg_va lr, x6 hyp_kimg_va lr, x6
msr elr_el2, lr msr elr_el2, lr
@ -125,13 +125,11 @@ alternative_else_nop_endif
add sp, sp, #16 add sp, sp, #16
/* /*
* Compute the idmap address of __kvm_handle_stub_hvc and * Compute the idmap address of __kvm_handle_stub_hvc and
* jump there. Since we use kimage_voffset, do not use the * jump there.
* HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead
* (by loading it from the constant pool).
* *
* Preserve x0-x4, which may contain stub parameters. * Preserve x0-x4, which may contain stub parameters.
*/ */
ldr x5, =__kvm_handle_stub_hvc adr_l x5, __kvm_handle_stub_hvc
hyp_pa x5, x6 hyp_pa x5, x6
br x5 br x5
SYM_FUNC_END(__host_hvc) SYM_FUNC_END(__host_hvc)

View file

@ -150,7 +150,7 @@ static void __hyp_vgic_restore_state(struct kvm_vcpu *vcpu)
} }
} }
/** /*
* Disable host events, enable guest events * Disable host events, enable guest events
*/ */
#ifdef CONFIG_HW_PERF_EVENTS #ifdef CONFIG_HW_PERF_EVENTS
@ -167,7 +167,7 @@ static bool __pmu_switch_to_guest(struct kvm_vcpu *vcpu)
return (pmu->events_host || pmu->events_guest); return (pmu->events_host || pmu->events_guest);
} }
/** /*
* Disable guest events, enable host events * Disable guest events, enable host events
*/ */
static void __pmu_switch_to_host(struct kvm_vcpu *vcpu) static void __pmu_switch_to_host(struct kvm_vcpu *vcpu)
@ -185,7 +185,7 @@ static void __pmu_switch_to_host(struct kvm_vcpu *vcpu)
#define __pmu_switch_to_host(v) do {} while (0) #define __pmu_switch_to_host(v) do {} while (0)
#endif #endif
/** /*
* Handler for protected VM MSR, MRS or System instruction execution in AArch64. * Handler for protected VM MSR, MRS or System instruction execution in AArch64.
* *
* Returns true if the hypervisor has handled the exit, and control should go * Returns true if the hypervisor has handled the exit, and control should go
@ -202,23 +202,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code)
kvm_handle_pvm_sysreg(vcpu, exit_code)); kvm_handle_pvm_sysreg(vcpu, exit_code));
} }
/**
* Handler for protected floating-point and Advanced SIMD accesses.
*
* Returns true if the hypervisor has handled the exit, and control should go
* back to the guest, or false if it hasn't.
*/
static bool kvm_handle_pvm_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
{
/* Linux guests assume support for floating-point and Advanced SIMD. */
BUILD_BUG_ON(!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_FP),
PVM_ID_AA64PFR0_ALLOW));
BUILD_BUG_ON(!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_ASIMD),
PVM_ID_AA64PFR0_ALLOW));
return kvm_hyp_handle_fpsimd(vcpu, exit_code);
}
static const exit_handler_fn hyp_exit_handlers[] = { static const exit_handler_fn hyp_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL, [0 ... ESR_ELx_EC_MAX] = NULL,
[ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32,
@ -234,7 +217,7 @@ static const exit_handler_fn pvm_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL, [0 ... ESR_ELx_EC_MAX] = NULL,
[ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64, [ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64,
[ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted, [ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_FP_ASIMD] = kvm_handle_pvm_fpsimd, [ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd,
[ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low, [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low,
[ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low, [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
[ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth, [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,

View file

@ -90,9 +90,6 @@ static u64 get_pvm_id_aa64pfr0(const struct kvm_vcpu *vcpu)
u64 set_mask = 0; u64 set_mask = 0;
u64 allow_mask = PVM_ID_AA64PFR0_ALLOW; u64 allow_mask = PVM_ID_AA64PFR0_ALLOW;
if (!vcpu_has_sve(vcpu))
allow_mask &= ~ARM64_FEATURE_MASK(ID_AA64PFR0_SVE);
set_mask |= get_restricted_features_unsigned(id_aa64pfr0_el1_sys_val, set_mask |= get_restricted_features_unsigned(id_aa64pfr0_el1_sys_val,
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED); PVM_ID_AA64PFR0_RESTRICT_UNSIGNED);

View file

@ -2198,25 +2198,24 @@ static const struct sys_reg_desc cp15_64_regs[] = {
{ SYS_DESC(SYS_AARCH32_CNTP_CVAL), access_arch_timer }, { SYS_DESC(SYS_AARCH32_CNTP_CVAL), access_arch_timer },
}; };
static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n, static bool check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
bool is_32) bool is_32)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (!is_32 && table[i].reg && !table[i].reset) { if (!is_32 && table[i].reg && !table[i].reset) {
kvm_err("sys_reg table %p entry %d has lacks reset\n", kvm_err("sys_reg table %pS entry %d lacks reset\n", &table[i], i);
table, i); return false;
return 1;
} }
if (i && cmp_sys_reg(&table[i-1], &table[i]) >= 0) { if (i && cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1); kvm_err("sys_reg table %pS entry %d out of order\n", &table[i - 1], i - 1);
return 1; return false;
} }
} }
return 0; return true;
} }
int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu) int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu)
@ -3008,18 +3007,22 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
return write_demux_regids(uindices); return write_demux_regids(uindices);
} }
void kvm_sys_reg_table_init(void) int kvm_sys_reg_table_init(void)
{ {
bool valid = true;
unsigned int i; unsigned int i;
struct sys_reg_desc clidr; struct sys_reg_desc clidr;
/* Make sure tables are unique and in order. */ /* Make sure tables are unique and in order. */
BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs), false)); valid &= check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs), false);
BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs), true)); valid &= check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs), true);
BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs), true)); valid &= check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs), true);
BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs), true)); valid &= check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs), true);
BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs), true)); valid &= check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs), true);
BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs), false)); valid &= check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs), false);
if (!valid)
return -EINVAL;
/* We abuse the reset function to overwrite the table itself. */ /* We abuse the reset function to overwrite the table itself. */
for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++) for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
@ -3042,4 +3045,6 @@ void kvm_sys_reg_table_init(void)
break; break;
/* Clear all higher bits. */ /* Clear all higher bits. */
cache_levels &= (1 << (i*3))-1; cache_levels &= (1 << (i*3))-1;
return 0;
} }

View file

@ -612,6 +612,10 @@ early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
static const struct midr_range broken_seis[] = { static const struct midr_range broken_seis[] = {
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM), MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM), MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
{}, {},
}; };