@@ -197,8 +197,17 @@ typedef enum {
197
197
EDN_ERROR , /* illegal state reached and hang */
198
198
} OtEDNFsmState ;
199
199
200
+ typedef enum {
201
+ CSRNG_STATUS_SUCCESS ,
202
+ CSRNG_STATUS_INVALID_ACMD ,
203
+ CSRNG_STATUS_INVALID_GEN_CMD ,
204
+ CSRNG_STATUS_INVALID_CMD_SEQ ,
205
+ CSRNG_STATUS_RESEED_CNT_EXCEEDED ,
206
+ } OtCSRNGCmdStatus ;
207
+
200
208
typedef struct {
201
209
OtCSRNGState * device ; /* CSRNG instance */
210
+ OtCSRNGCmdStatus last_cmd_status ; /* status of the last CSRNG command */
202
211
qemu_irq genbits_ready ; /* Set when ready to receive entropy */
203
212
uint32_t appid ; /* unique HW application id to identify on CSRNG */
204
213
bool instantiated ; /* instantiated state, not yet uninstantiated */
@@ -234,7 +243,6 @@ struct OtEDNState {
234
243
uint32_t * regs ;
235
244
236
245
unsigned reseed_counter ; /* track remaining requests before reseeding */
237
- bool last_cmd_failed ; /* status of the last CSRNG command */
238
246
bool sw_cmd_ready ; /* ready to receive command in SW port mode */
239
247
OtEDNFsmState state ; /* Main FSM state */
240
248
OtEDNCSRNG rng ;
@@ -440,12 +448,12 @@ static OtCsrngCmd ot_edn_get_last_csrng_command(OtEDNState *s)
440
448
}
441
449
}
442
450
443
- static bool ot_edn_is_cmd_rdy (OtEDNState * s )
451
+ static bool ot_edn_is_cmd_rdy (OtEDNState * s , bool check_fifo )
444
452
{
445
453
if (!ot_edn_is_enabled (s )) {
446
454
return false;
447
455
}
448
- if (ot_fifo32_is_full (& s -> rng .sw_cmd_fifo )) {
456
+ if (check_fifo && ot_fifo32_is_full (& s -> rng .sw_cmd_fifo )) {
449
457
return false;
450
458
}
451
459
switch (s -> state ) {
@@ -508,6 +516,7 @@ static int ot_edn_push_csrng_request(OtEDNState *s)
508
516
& ot_edn_fill_bits , s );
509
517
g_assert (c -> genbits_ready );
510
518
}
519
+ s -> regs [R_SW_CMD_STS ] |= R_SW_CMD_STS_CMD_ACK_MASK ;
511
520
int res = ot_csrng_push_command (c -> device , c -> appid , c -> buffer );
512
521
if (res ) {
513
522
xtrace_ot_edn_error (c -> appid , "CSRNG rejected command" );
@@ -834,7 +843,7 @@ static void ot_edn_clean_up(OtEDNState *s, bool discard_requests)
834
843
835
844
c -> instantiated = false;
836
845
s -> sw_cmd_ready = false;
837
- s -> last_cmd_failed = false ;
846
+ s -> rng . last_cmd_status = CSRNG_STATUS_SUCCESS ;
838
847
s -> reseed_counter = 0 ;
839
848
memset (c -> buffer , 0 , sizeof (* c -> buffer ));
840
849
ot_fifo32_reset (& c -> bits_fifo );
@@ -994,7 +1003,8 @@ static void ot_edn_csrng_ack_irq(void *opaque, int n, int level)
994
1003
*/
995
1004
memset (c -> buffer , 0 , sizeof (* c -> buffer ));
996
1005
997
- s -> last_cmd_failed = level != 0 ;
1006
+ c -> last_cmd_status =
1007
+ level != 0 ? CSRNG_STATUS_INVALID_ACMD : CSRNG_STATUS_SUCCESS ;
998
1008
999
1009
if (level ) {
1000
1010
xtrace_ot_edn_error (c -> appid , "last command failed" );
@@ -1074,12 +1084,15 @@ static uint64_t ot_edn_regs_read(void *opaque, hwaddr addr, unsigned size)
1074
1084
case R_ERR_CODE_TEST :
1075
1085
val32 = s -> regs [reg ];
1076
1086
break ;
1077
- case R_SW_CMD_STS :
1078
- val32 =
1079
- FIELD_DP32 (0 , SW_CMD_STS , CMD_STS , (uint32_t )s -> last_cmd_failed );
1080
- val32 = FIELD_DP32 (val32 , SW_CMD_STS , CMD_RDY ,
1081
- (uint32_t )ot_edn_is_cmd_rdy (s ));
1087
+ case R_SW_CMD_STS : {
1088
+ uint32_t rdy = (uint32_t ) ot_edn_is_cmd_rdy (s , false);
1089
+ uint32_t reg_rdy = (uint32_t ) ot_edn_is_cmd_rdy (s , true);
1090
+ val32 = s -> regs [R_SW_CMD_STS ];
1091
+ val32 = FIELD_DP32 (val32 , SW_CMD_STS , CMD_STS , s -> rng .last_cmd_status );
1092
+ val32 = FIELD_DP32 (val32 , SW_CMD_STS , CMD_RDY , rdy );
1093
+ val32 = FIELD_DP32 (val32 , SW_CMD_STS , CMD_REG_RDY , reg_rdy );
1082
1094
break ;
1095
+ }
1083
1096
case R_MAIN_SM_STATE :
1084
1097
switch (s -> state ) {
1085
1098
case EDN_IDLE ... EDN_ERROR :
@@ -1205,6 +1218,7 @@ static void ot_edn_regs_write(void *opaque, hwaddr addr, uint64_t val64,
1205
1218
s -> regs [reg ] = val32 ;
1206
1219
break ;
1207
1220
case R_SW_CMD_REQ :
1221
+ s -> regs [R_SW_CMD_STS ] &= ~R_SW_CMD_STS_CMD_ACK_MASK ;
1208
1222
/* ignore all sw commands in auto req mode once instantiated */
1209
1223
if (ot_edn_is_auto_req_mode (s ) && c -> instantiated ) {
1210
1224
xtrace_ot_edn_dinfo (c -> appid , "ignore SW REQ" , c -> appid );
0 commit comments