Skip to content

Commit 6b17b41

Browse files
committed
sunxi-fel: factor SMC workaround handling
Separate the runtime SMC-workaround probe from the code that executes the workaround so later SoCs can choose a different implementation without mixing that change into the existing direct-SMC path. Describe the workaround method in SoC data and make every existing secure-FEL user select the direct-SMC method explicitly. This preserves the current behaviour because direct SMC remains the only implementation in this patch. Also make the old-format thunk header rule pattern-based while it still only builds the existing SPL thunk header. Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
1 parent 5d552bc commit 6b17b41

4 files changed

Lines changed: 35 additions & 16 deletions

File tree

fel.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -564,31 +564,38 @@ void aw_set_sctlr(feldev_handle *dev, soc_info_t *soc_info,
564564
aw_write_arm_cp_reg(dev, soc_info, 15, 0, 1, 0, 0, sctlr);
565565
}
566566

567+
static bool aw_fel_needs_smc_workaround(feldev_handle *dev)
568+
{
569+
soc_info_t *soc_info = dev->soc_info;
570+
uint32_t val;
571+
572+
/* Return if the SoC does not need this workaround */
573+
if (!soc_info->needs_smc_workaround_if_zero_word_at_addr)
574+
return false;
575+
576+
/* This has less overhead than fel_readl_n() and may be good enough */
577+
aw_fel_read(dev, soc_info->needs_smc_workaround_if_zero_word_at_addr,
578+
&val, sizeof(val));
579+
580+
return val == 0;
581+
}
582+
567583
/*
568584
* Issue a "smc #0" instruction. This brings a SoC booted in "secure boot"
569585
* state from the default non-secure FEL into secure FEL.
570586
* This crashes on devices using "non-secure boot", as the BROM does not
571587
* provide a handler address in MVBAR. So we have a runtime check.
572588
*/
573-
void aw_apply_smc_workaround(feldev_handle *dev)
589+
static void aw_apply_smc_workaround(feldev_handle *dev)
574590
{
575591
soc_info_t *soc_info = dev->soc_info;
576-
uint32_t val;
577592
uint32_t arm_code[] = {
578593
htole32(0xe1600070), /* smc #0 */
579594
htole32(0xe12fff1e), /* bx lr */
580595
};
581596

582-
/* Return if the SoC does not need this workaround */
583-
if (!soc_info->needs_smc_workaround_if_zero_word_at_addr)
584-
return;
585-
586-
/* This has less overhead than fel_readl_n() and may be good enough */
587-
aw_fel_read(dev, soc_info->needs_smc_workaround_if_zero_word_at_addr,
588-
&val, sizeof(val));
589-
590597
/* Return if the workaround is not needed or has been already applied */
591-
if (val != 0)
598+
if (!aw_fel_needs_smc_workaround(dev))
592599
return;
593600

594601
pr_info("Applying SMC workaround... ");

soc_info.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ soc_info_t soc_info_table[] = {
397397
.rvbar_reg = 0x017000A0,
398398
/* Check L.NOP in the OpenRISC reset vector */
399399
.needs_smc_workaround_if_zero_word_at_addr = 0x40004,
400+
.smc_workaround = SMC_WORKAROUND_DIRECT_SMC,
400401
.watchdog = &wd_h3_compat,
401402
},{
402403
.soc_id = 0x1639, /* Allwinner A80 */
@@ -445,6 +446,7 @@ soc_info_t soc_info_table[] = {
445446
.sid_sections = h3_sid_maps,
446447
/* Check L.NOP in the OpenRISC reset vector */
447448
.needs_smc_workaround_if_zero_word_at_addr = 0x40004,
449+
.smc_workaround = SMC_WORKAROUND_DIRECT_SMC,
448450
.watchdog = &wd_h3_compat,
449451
},{
450452
.soc_id = 0x1681, /* Allwinner V3s */
@@ -483,6 +485,7 @@ soc_info_t soc_info_table[] = {
483485
.rvbar_reg = 0x017000A0,
484486
/* Check L.NOP in the OpenRISC reset vector */
485487
.needs_smc_workaround_if_zero_word_at_addr = 0x40004,
488+
.smc_workaround = SMC_WORKAROUND_DIRECT_SMC,
486489
.watchdog = &wd_h3_compat,
487490
},{
488491
.soc_id = 0x1701, /* Allwinner R40 */
@@ -522,6 +525,7 @@ soc_info_t soc_info_table[] = {
522525
.rvbar_reg = 0x09010040,
523526
/* Check L.NOP in the OpenRISC reset vector */
524527
.needs_smc_workaround_if_zero_word_at_addr = 0x100004,
528+
.smc_workaround = SMC_WORKAROUND_DIRECT_SMC,
525529
.watchdog = &wd_h6_compat,
526530
},{
527531
.soc_id = 0x1816, /* Allwinner V536 */
@@ -641,6 +645,7 @@ soc_info_t soc_info_table[] = {
641645
.sid_sections = generic_2k_sid_maps,
642646
.rvbar_reg = 0x08100040,
643647
.needs_smc_workaround_if_zero_word_at_addr = 0x100004,
648+
.smc_workaround = SMC_WORKAROUND_DIRECT_SMC,
644649
.watchdog = &wd_h6_compat,
645650
},{
646651
.swap_buffers = NULL /* End of the table */

soc_info.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,18 @@ typedef struct {
107107
* - No access to the secure side of the GIC, so it can't be configured to
108108
* be accessible from non-secure world.
109109
* - No RMR trigger on ARMv8 cores to bring the core into AArch64.
110-
* However it has been found out that a simple "smc" call will immediately
111-
* return from monitor mode, but with the NS bit cleared, so access to all
112-
* secure peripherals is suddenly possible.
110+
* On older SoCs, a simple "smc" call returns with the NS bit cleared,
111+
* so access to all secure peripherals is suddenly possible.
113112
* The 'needs_smc_workaround_if_zero_word_at_addr' field can be used to
114113
* have a check for this condition (reading from restricted addresses
115114
* typically returns zero) and then activate the SMC workaround if needed.
115+
* The 'smc_workaround' field selects how to apply the workaround once the
116+
* runtime checks say that it is needed.
116117
*/
118+
typedef enum {
119+
SMC_WORKAROUND_DIRECT_SMC,
120+
} smc_workaround_t;
121+
117122
typedef struct {
118123
uint32_t soc_id; /* ID of the SoC */
119124
const char *name; /* human-readable SoC name string */
@@ -135,6 +140,8 @@ typedef struct {
135140
bool icache_fix;
136141
/* Use SMC workaround (enter secure mode) if can't read from this address */
137142
uint32_t needs_smc_workaround_if_zero_word_at_addr;
143+
/* How to apply the SMC workaround */
144+
smc_workaround_t smc_workaround;
138145
uint32_t sram_size; /* Usable contiguous SRAM at spl_addr */
139146
sram_swap_buffers *swap_buffers;
140147
} soc_info_t;

thunks/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ OBJDUMP := $(CROSS_COMPILE)objdump
2424

2525
AWK_O_TO_H := LC_ALL=C awk -f objdump_to_h.awk
2626

27-
# The SPL thunk requires a different output format. The "style" variable for
27+
# These thunks require the old output format. The "style" variable for
2828
# awk controls this, and causes the htole32() conversion to be omitted.
29-
fel-to-spl-thunk.h: fel-to-spl-thunk.S FORCE
29+
$(SPL_THUNK): %.h: %.S FORCE
3030
$(AS) -o $(subst .S,.o,$<) -march=armv5te $<
3131
$(OBJDUMP) -d $(subst .S,.o,$<) | $(AWK_O_TO_H) -v style=old > $@
3232

0 commit comments

Comments
 (0)