mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
ANDROID: KVM: arm64: Reset sysregs for protected VMs
Create a framework for resetting protected VM system registers to their architecturally defined reset values. No functional change intended as these are not hooked in yet. Signed-off-by: Fuad Tabba <tabba@google.com> Signed-off-by: Will Deacon <willdeacon@google.com> Bug: 233587962 Change-Id: Id812d1bbe81c7c0a544aba91b35831f486c208ba
This commit is contained in:
@@ -91,6 +91,7 @@ struct pkvm_hyp_vcpu *pkvm_get_loaded_hyp_vcpu(void);
|
||||
u64 pvm_read_id_reg(const struct kvm_vcpu *vcpu, u32 id);
|
||||
bool kvm_handle_pvm_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code);
|
||||
bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
|
||||
void kvm_reset_pvm_sys_regs(struct kvm_vcpu *vcpu);
|
||||
int kvm_check_pvm_sysreg_table(void);
|
||||
|
||||
#endif /* __ARM64_KVM_NVHE_PKVM_H__ */
|
||||
|
||||
@@ -465,8 +465,85 @@ static const struct sys_reg_desc pvm_sys_reg_descs[] = {
|
||||
/* Performance Monitoring Registers are restricted. */
|
||||
};
|
||||
|
||||
/* A structure to track reset values for system registers in protected vcpus. */
|
||||
struct sys_reg_desc_reset {
|
||||
/* Index into sys_reg[]. */
|
||||
int reg;
|
||||
|
||||
/* Reset function. */
|
||||
void (*reset)(struct kvm_vcpu *, const struct sys_reg_desc_reset *);
|
||||
|
||||
/* Reset value. */
|
||||
u64 value;
|
||||
};
|
||||
|
||||
static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc_reset *r)
|
||||
{
|
||||
__vcpu_sys_reg(vcpu, r->reg) = read_sysreg(actlr_el1);
|
||||
}
|
||||
|
||||
static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc_reset *r)
|
||||
{
|
||||
__vcpu_sys_reg(vcpu, r->reg) = read_sysreg(amair_el1);
|
||||
}
|
||||
|
||||
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc_reset *r)
|
||||
{
|
||||
__vcpu_sys_reg(vcpu, r->reg) = calculate_mpidr(vcpu);
|
||||
}
|
||||
|
||||
static void reset_value(struct kvm_vcpu *vcpu, const struct sys_reg_desc_reset *r)
|
||||
{
|
||||
__vcpu_sys_reg(vcpu, r->reg) = r->value;
|
||||
}
|
||||
|
||||
/* Specify the register's reset value. */
|
||||
#define RESET_VAL(REG, RESET_VAL) { REG, reset_value, RESET_VAL }
|
||||
|
||||
/* Specify a function that calculates the register's reset value. */
|
||||
#define RESET_FUNC(REG, RESET_FUNC) { REG, RESET_FUNC, 0 }
|
||||
|
||||
/*
|
||||
* Checks that the sysreg table is unique and in-order.
|
||||
* Architected system registers reset values for Protected VMs.
|
||||
* Important: Must be sorted ascending by REG (index into sys_reg[])
|
||||
*/
|
||||
static const struct sys_reg_desc_reset pvm_sys_reg_reset_vals[] = {
|
||||
RESET_FUNC(MPIDR_EL1, reset_mpidr),
|
||||
RESET_VAL(SCTLR_EL1, 0x00C50078),
|
||||
RESET_FUNC(ACTLR_EL1, reset_actlr),
|
||||
RESET_VAL(CPACR_EL1, 0),
|
||||
RESET_VAL(ZCR_EL1, 0),
|
||||
RESET_VAL(TCR_EL1, 0),
|
||||
RESET_VAL(VBAR_EL1, 0),
|
||||
RESET_VAL(CONTEXTIDR_EL1, 0),
|
||||
RESET_FUNC(AMAIR_EL1, reset_amair_el1),
|
||||
RESET_VAL(CNTKCTL_EL1, 0),
|
||||
RESET_VAL(MDSCR_EL1, 0),
|
||||
RESET_VAL(MDCCINT_EL1, 0),
|
||||
RESET_VAL(DISR_EL1, 0),
|
||||
RESET_VAL(PMCCFILTR_EL0, 0),
|
||||
RESET_VAL(PMUSERENR_EL0, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Sets system registers to reset value
|
||||
*
|
||||
* This function finds the right entry and sets the registers on the protected
|
||||
* vcpu to their architecturally defined reset values.
|
||||
*/
|
||||
void kvm_reset_pvm_sys_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pvm_sys_reg_reset_vals); i++) {
|
||||
const struct sys_reg_desc_reset *r = &pvm_sys_reg_reset_vals[i];
|
||||
|
||||
r->reset(vcpu, r);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks that the sysreg tables are unique and in-order.
|
||||
*
|
||||
* Returns 0 if the table is consistent, or 1 otherwise.
|
||||
*/
|
||||
@@ -479,6 +556,11 @@ int kvm_check_pvm_sysreg_table(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 1; i < ARRAY_SIZE(pvm_sys_reg_reset_vals); i++) {
|
||||
if (pvm_sys_reg_reset_vals[i-1].reg >= pvm_sys_reg_reset_vals[i].reg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user