target/arm: Implement ARMv8.5-RNG

Use the newly introduced infrastructure for guest random numbers.

Backports commit de390645675966cce113bf5394445bc1f8d07c85 from qemu

(with the actual RNG portion disabled to preserve determinism for the
time being).
This commit is contained in:
Richard Henderson 2019-05-23 15:01:37 -04:00 committed by Lioncash
parent a8df33c37c
commit 3dd7358a53
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 53 additions and 0 deletions

View file

@ -3474,6 +3474,11 @@ static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
}
static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0;
}
static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;

View file

@ -268,6 +268,7 @@ static void aarch64_max_initfn(struct uc_struct *uc, Object *obj, void *opaque)
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);
cpu->isar.id_aa64isar0 = t;
t = cpu->isar.id_aa64isar1;

View file

@ -5559,6 +5559,50 @@ static const ARMCPRegInfo pauth_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
REGINFO_SENTINEL
};
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
{
uint64_t ret = 0;
/* Success sets NZCV = 0000. */
env->NF = env->CF = env->VF = 0, env->ZF = 1;
// Unicorn: commented out.
// Currently we don't rely on host state.
#if 0
Error *err = NULL;
if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
/*
* ??? Failed, for unknown reasons in the crypto subsystem.
* The best we can do is log the reason and return the
* timed-out indication to the guest. There is no reason
* we know to expect this failure to be transitory, so the
* guest may well hang retrying the operation.
*/
qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s",
ri->name, error_get_pretty(err));
error_free(err);
env->ZF = 0; /* NZCF = 0100 */
return 0;
}
#endif
return ret;
}
/* We do not support re-seeding, so the two registers operate the same. */
static const ARMCPRegInfo rndr_reginfo[] = {
{ .name = "RNDR", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 0,
.access = PL0_R, .readfn = rndr_readfn },
{ .name = "RNDRRS", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO,
.opc0 = 3, .opc1 = 3, .crn = 2, .crm = 4, .opc2 = 1,
.access = PL0_R, .readfn = rndr_readfn },
REGINFO_SENTINEL
};
#endif
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
@ -6503,6 +6547,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (cpu_isar_feature(aa64_pauth, cpu)) {
define_arm_cp_regs(cpu, pauth_reginfo);
}
if (cpu_isar_feature(aa64_rndr, cpu)) {
define_arm_cp_regs(cpu, rndr_reginfo);
}
#endif
/*