ARMmbed / ARMmbed/uvisor

uVisor prevents LwIP/Hal from properly using ENET hardware when enabled

Open
#315 30 comments 0 reactions 0 assignees View on GitHub
closed_in_jira issue mirrored
Dominant language
C
Stars
135
Forks
72
PR merge metrics
No merged PRs in 30d

Description

**EDIT:** I changed the issue's name to more appropriately track the purpose of this thread after relevant information has been uncovered surrounding the original problem.

---

I have been trying to determine the appropriate uVisor ACL such that I can use the Ethernet hardware on the FRDM K64F development board. After a few hours of debugging and tracing the problem I managed to determine two points of failure when using EthernetInterface.cpp and (a dependency thereof) the LWIP implementation; the root of the corresponding source tree can be found [here](https://github.com/ARMmbed/mbed-os/tree/master/features/net/FEATURE_IPV4/lwip-interface).

The first problem I found was that the LWIP implementation was trying to disable the MPU, which I thought might be problematic for uVisor.

`MPU->CESR &= ~MPU_CESR_VLD_MASK;`

https://github.com/ARMmbed/mbed-os/blob/master/features/net/FEATURE_IPV4/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c#L41

I have defined the MPU as an enabled memory range in my ACL, but that does not prevent the system from stopping on that instruction.

```
const UvisorBoxAclItem g_main_acl[] = {
{SIM, sizeof(*SIM), UVISOR_TACLDEF_PERIPH},
{OSC, sizeof(*OSC), UVISOR_TACLDEF_PERIPH},
{MCG, sizeof(*MCG), UVISOR_TACLDEF_PERIPH},
{PORTA, sizeof(*PORTA), UVISOR_TACLDEF_PERIPH},
{PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH},
{PORTC, sizeof(*PORTC), UVISOR_TACLDEF_PERIPH},
{PORTD, sizeof(*PORTD), UVISOR_TACLDEF_PERIPH},
{PORTE, sizeof(*PORTE), UVISOR_TACLDEF_PERIPH},
{RTC, sizeof(*RTC), UVISOR_TACLDEF_PERIPH},
{LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH},
{PIT, sizeof(*PIT), UVISOR_TACLDEF_PERIPH},
{SMC, sizeof(*SMC), UVISOR_TACLDEF_PERIPH},
{UART0, sizeof(*UART0), UVISOR_TACLDEF_PERIPH},
{I2C0, sizeof(*I2C0), UVISOR_TACLDEF_PERIPH},
{SPI0, sizeof(*SPI0), UVISOR_TACLDEF_PERIPH},
{MPU, sizeof(*MPU), UVISOR_TACLDEF_PERIPH},

/* EthernetInterface */
{ENET, sizeof(*ENET), UVISOR_TACLDEF_PERIPH},
{EWM, sizeof(*EWM), UVISOR_TACLDEF_PERIPH},
};
```

---

The second problem was related to a call to `EnableIRQ` in `fsl_enet.c`. At the highest level, a call to `EthernetInterface.connect()` will lead to execution of the following.

```
/* Enables Ethernet interrupt and NVIC. */
ENET_EnableInterrupts(base, config->interrupt);
if (config->interrupt & (kENET_RxByteInterrupt | kENET_RxFrameInterrupt))
{
EnableIRQ(s_enetRxIrqId[instance]);
}
if (config->interrupt & (kENET_TxByteInterrupt | kENET_TxFrameInterrupt))
{
EnableIRQ(s_enetTxIrqId[instance]);
}
if (config->interrupt & (kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_GraceStopInterrupt | kENET_MiiInterrupt |
kENET_EBusERInterrupt | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt |
kENET_UnderrunInterrupt | kENET_PayloadRxInterrupt | kENET_WakeupInterrupt))
{
EnableIRQ(s_enetErrIrqId[instance]);
}
```

https://github.com/ARMmbed/mbed-os/blob/master/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_MCU_K64F/drivers/fsl_enet.c#L453

As it turns out, `EnableIRQ()` is an inline function defined in `fsl_common.h` as a link to an [NVIC_EnableIRQ](https://www.keil.com/pack/doc/cmsis/Core/html/group___n_v_i_c__gr.html) call:

```
static inline void EnableIRQ(IRQn_Type interrupt)
{
#if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0)
if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX)
#endif
{
NVIC_EnableIRQ(interrupt);
}
}
```

https://github.com/ARMmbed/mbed-os/blob/master/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_MCU_K64F/drivers/fsl_common.h#L182

I could not trace the NVIC definition down any further as there were a very large number of them. However, I did check out the generated source code in a disassembler and it seems that `NVIC_EnableIRQ` is being translated to an [SVC](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s07.html) 3 call.

Are there a special configuration required for this? Does the default SVC_Handler function not handled this case for enabling interrupts? The behavior I am observing is that a call to this function never returns, so I can only guess (since I do not have a debugger) that the uVisor is trapping on this call.

---

As a side note, I tried using `UVISOR_PERMISSIVE` for my main ACL, but the problem still persists.

Are there any obvious problems with using `NVIC_EnableIRQ` or writing to the MPU? Are there additional configuration requirements to support either?

If I comment out the offending MPU and NVIC_EnableIRQ lines then everything executes without issue -- except the Ethernet hardware does not work, of course.

Contributor guide

Open the contributing guide

Research direction

Start with features/net/FEATURE_IPV4/lwip-interface/lwip-eth/arch/TARGET_Freescale/hardware_init_MK64F12.c and hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_MCU_K64F/drivers/fsl_enet.c. Trace the MPU write, EnableIRQ/NVIC_EnableIRQ in fsl_common.h, and the SVC_Handler behavior under the supplied ACL. Done means identifying the uVisor configuration or compatibility issue that prevents Ethernet initialization.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.