@@ -742,11 +742,13 @@ struct OtFlashState {
742742 struct {
743743 OtFlashOperation kind ;
744744 unsigned count ;
745+ unsigned remaining ;
745746 unsigned address ;
746747 unsigned info_sel ;
747748 bool info_part ;
748749 bool prog_sel ;
749750 bool erase_sel ;
751+ bool failed ;
750752 } op ;
751753 OtFifo32 rd_fifo ;
752754 OtFifo32 prog_fifo ;
@@ -818,7 +820,6 @@ static void ot_flash_update_prog_watermark(OtFlashState *s)
818820}
819821
820822
821-
822823static void ot_flash_op_signal (void * opaque )
823824{
824825 OtFlashState * s = opaque ;
@@ -908,78 +909,105 @@ static void ot_flash_op_complete(OtFlashState *s)
908909 ot_flash_update_irqs (s );
909910}
910911
912+ static unsigned ot_flash_next_info_address (OtFlashState * s )
913+ {
914+ OtFlashStorage * storage = & s -> flash ;
915+ unsigned bank_size = storage -> data_size ;
916+ unsigned info_partition = s -> op .info_sel ;
917+
918+ /* offset the address by the number of processed ops to get next addr */
919+ unsigned op_offset = (s -> op .count - s -> op .remaining ) * sizeof (uint32_t );
920+ unsigned op_address = s -> op .address + op_offset ;
921+
922+ if (info_partition >= storage -> info_part_count ) {
923+ qemu_log_mask (LOG_GUEST_ERROR , "%s: invalid info partition: %u\n" ,
924+ __func__ , s -> op .info_sel );
925+ ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , op_address );
926+ s -> op .failed = true;
927+ return op_address ;
928+ }
929+
930+ /* extract the bank & bank-relative address from the address */
931+ unsigned bank = op_address / bank_size ;
932+ if (bank >= storage -> bank_count ) {
933+ qemu_log_mask (LOG_GUEST_ERROR , "%s: invalid bank: %d\n" , __func__ ,
934+ bank );
935+ ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , op_address );
936+ s -> op .failed = true;
937+ return op_address ;
938+ }
939+ unsigned address_in_bank = op_address % bank_size ;
940+ if (address_in_bank >= storage -> info_parts [info_partition ].size ) {
941+ /*
942+ * Purposefuly do not check the whole transaction's address width here:
943+ * the RTL only errors when it attempts to read an invalid address.
944+ */
945+ qemu_log_mask (LOG_GUEST_ERROR ,
946+ "%s: invalid address in partition: %u %u\n" , __func__ ,
947+ op_address , info_partition );
948+ ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , op_address );
949+ s -> op .failed = true;
950+ return op_address ;
951+ }
952+
953+ /* Retrieve the raw backend byte address in the info partitions. */
954+ unsigned bank_offset = bank * storage -> info_size ;
955+ unsigned info_part_offset = storage -> info_parts [info_partition ].offset ;
956+ unsigned address = address_in_bank + bank_offset + info_part_offset ;
957+ trace_ot_flash_info_part (s -> op .address , s -> op .count , s -> op .remaining , bank ,
958+ info_partition , address );
959+ return address ;
960+ }
961+
962+ static unsigned ot_flash_next_data_address (OtFlashState * s )
963+ {
964+ OtFlashStorage * storage = & s -> flash ;
965+ unsigned bank_size = storage -> data_size ;
966+
967+ /* offset the address by the number of proessed ops to get next addr */
968+ unsigned op_offset = (s -> op .count - s -> op .remaining ) * sizeof (uint32_t );
969+ unsigned address = s -> op .address + op_offset ;
970+ unsigned bank = address / bank_size ;
971+ if (bank >= storage -> bank_count ) {
972+ qemu_log_mask (LOG_GUEST_ERROR , "%s: invalid bank: %d\n" , __func__ ,
973+ bank );
974+ ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , address );
975+ s -> op .failed = true;
976+ return address ;
977+ }
978+ trace_ot_flash_data_part (s -> op .address , s -> op .count , s -> op .remaining , bank ,
979+ address );
980+ return address ;
981+ }
982+
911983static void ot_flash_op_read (OtFlashState * s )
912984{
913985 if (ot_fifo32_is_full (& s -> rd_fifo )) {
914986 xtrace_ot_flash_error ("read while RD FIFO full" );
915987 return ;
916988 }
917- unsigned max_size ;
918- unsigned offset ;
919- unsigned address ;
989+
920990 OtFlashStorage * storage = & s -> flash ;
921- uint32_t * src ;
922-
923- if (s -> op .info_part ) {
924- if (s -> op .info_sel >= storage -> info_part_count ) {
925- qemu_log_mask (LOG_GUEST_ERROR , "%s: invalid info partition: %u\n" ,
926- __func__ , s -> op .info_sel );
927- ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , s -> op .address );
928- ot_flash_op_complete (s );
929- return ;
930- }
931- max_size = storage -> info_size ;
932- /* relative storage offset in the info storage */
933- offset = storage -> info_parts [s -> op .info_sel ].offset ;
934- unsigned bank_size = storage -> data_size ;
935- /* extract the bank from the address */
936- unsigned bank = s -> op .address / bank_size ;
937- if (bank >= storage -> bank_count ) {
938- qemu_log_mask (LOG_GUEST_ERROR , "%s: invalid bank: %d\n" , __func__ ,
939- bank );
940- ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , s -> op .address );
941- ot_flash_op_complete (s );
942- return ;
943- }
944- /* get the adress relative to the bank */
945- address = s -> op .address % bank_size ;
946- if (address + s -> op .count * sizeof (uint32_t ) >=
947- storage -> info_parts [s -> op .info_sel ].size ) {
948- qemu_log_mask (LOG_GUEST_ERROR ,
949- "%s: invalid address in partition: %u %u\n" , __func__ ,
950- address , s -> op .info_sel );
951- ot_flash_set_error (s , R_ERR_CODE_MP_ERR_MASK , s -> op .address );
952- ot_flash_op_complete (s );
953- return ;
991+ uint32_t * src = s -> op .info_part ? storage -> info : storage -> data ;
992+
993+ while (s -> op .remaining ) {
994+ uint32_t word = 0xFFFFFFFFu ;
995+ if (!s -> op .failed ) {
996+ unsigned address = s -> op .info_part ? ot_flash_next_info_address (s ) :
997+ ot_flash_next_data_address (s );
998+ address /= sizeof (uint32_t ); /* convert to word address */
999+
1000+ /* For multi-word read access permission errors, return all 1s. */
1001+ if (!s -> op .failed ) {
1002+ word = src [address ];
1003+ }
9541004 }
955- /* add the bank offset of the first byte of info part */
956- address += bank * storage -> info_size ;
957- /* add the offset of the partition in the current bank */
958- address += offset ;
959- src = storage -> info ;
960- trace_ot_flash_info_part (s -> op .address , bank , s -> op .info_sel , address );
961- } else {
962- max_size = storage -> data_size ;
963- address = s -> op .address ;
964- src = storage -> data ;
965- }
966-
967- /* sanity check */
968- if (address >= max_size * storage -> bank_count ) {
969- xtrace_ot_flash_error ("read address out of bound" );
970- g_assert_not_reached ();
971- }
972-
973- /* convert to word address */
974- address /= sizeof (uint32_t );
9751005
976- while (s -> op .count ) {
977- uint32_t word = src [address ++ ];
978- s -> op .count -- ;
9791006 if (!ot_flash_fifo_in_reset (s )) {
9801007 ot_fifo32_push (& s -> rd_fifo , word );
9811008 s -> regs [R_STATUS ] &= ~R_STATUS_RD_EMPTY_MASK ;
9821009 ot_flash_update_rd_watermark (s );
1010+ s -> op .remaining -- ;
9831011 }
9841012 if (ot_fifo32_is_full (& s -> rd_fifo )) {
9851013 s -> regs [R_STATUS ] |= R_STATUS_RD_FULL_MASK ;
@@ -989,7 +1017,11 @@ static void ot_flash_op_read(OtFlashState *s)
9891017 }
9901018 }
9911019
992- if (!s -> op .count ) {
1020+ /*
1021+ * If we finished the entire read operation (i.e. no early exit as FIFO
1022+ * is full), mark the operation as completed.
1023+ */
1024+ if (!s -> op .remaining ) {
9931025 ot_flash_op_complete (s );
9941026 }
9951027}
@@ -998,7 +1030,7 @@ static void ot_flash_op_execute(OtFlashState *s)
9981030{
9991031 switch (s -> op .kind ) {
10001032 case OP_READ :
1001- trace_ot_flash_op_start (OP_NAME (s -> op .kind ));
1033+ trace_ot_flash_op_execute (OP_NAME (s -> op .kind ));
10021034 ot_flash_op_read (s );
10031035 break ;
10041036 default :
@@ -1342,6 +1374,9 @@ static void ot_flash_regs_write(void *opaque, hwaddr addr, uint64_t val64,
13421374 ot_flash_op_complete (s );
13431375 return ;
13441376 }
1377+ s -> op .failed = false;
1378+ s -> op .remaining = s -> op .count ;
1379+ trace_ot_flash_op_start (OP_NAME (s -> op .kind ));
13451380 }
13461381 ot_flash_op_execute (s );
13471382 break ;
0 commit comments