target/arm: Implement ARMv8.5-RNG

Use the newly introduced infrastructure for guest random numbers.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2019-03-12 21:57:35 -07:00
parent 108b3ba891
commit de39064567
3 changed files with 50 additions and 0 deletions

View File

@ -3521,6 +3521,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

@ -310,6 +310,7 @@ static void aarch64_max_initfn(Object *obj)
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

@ -22,6 +22,8 @@
#include "fpu/softfloat.h"
#include "qemu/range.h"
#include "qapi/qapi-commands-target.h"
#include "qapi/error.h"
#include "qemu/guest-random.h"
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@ -5746,6 +5748,45 @@ static const ARMCPRegInfo pauth_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, keys.apib.hi) },
REGINFO_SENTINEL
};
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
{
Error *err = NULL;
uint64_t ret;
/* Success sets NZCV = 0000. */
env->NF = env->CF = env->VF = 0, env->ZF = 1;
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;
}
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,
@ -6690,6 +6731,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
/*