-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: stm32_gpio: register firewall controllers for GPIO access rights #7102
base: master
Are you sure you want to change the base?
Conversation
523c9ca
to
d049439
Compare
Rebased to fix merge conflicts. CI / Code Style checkpatch reports are all false positive: |
7 first patches (device tree):
|
Comments on the 7 first commits addressed. CI / Code style reports false positive (trace message impl. exceeding 80char/line + use BIT() in DT binding header file). CI / make check (QEMUv8, Clang) failed on optee_rust_examples_ext-1.0 build:
|
@@ -753,7 +754,7 @@ static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank) | |||
panic(); | |||
|
|||
for (i = 0; i < bank->ngpios; i++) { | |||
if (!(BIT(i) & bank->rif_cfg->access_mask[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this removed? So that we allow reconfiguration of pins that we don't list in the DT RIF config at first place? It's not what we have at downstream
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bits set in gpios_mask
are also set in bank->rif_cfg->access_mask[0]
(see caller functions) hence testing gpios_mask
is enough IMHO. Maybe I should add an assertion at function entry?
assert(gpios_mask & bank->rif_cfg->access_mask[0] == gpios_mask);
@@ -793,7 +794,7 @@ static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank) | |||
} | |||
|
|||
for (i = 0; i < bank->ngpios; i++) { | |||
if (!(BIT(i) & bank->rif_cfg->access_mask[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
core/drivers/stm32_gpio.c
Outdated
return TEE_ERROR_BAD_PARAMETERS; | ||
|
||
if (bank->rif_cfg) { | ||
#ifdef CFG_STM32_RIF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: #if defined(xxx)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
* Non RIF GPIO banks use TZPROT() bit mask (bits 0 to 15) | ||
* and GPIO_STM32_NSEC bit flag in the DT bindings. | ||
*/ | ||
gpios_mask = firewall->args[0] & GENMASK_32(15, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the non-RIF case, we allow multiple pin reconfiguration. We forbid that for RIF-capable banks. I think the function should have the same use, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that STM32MP1 DT bindings allow a single firewall config/query to confgure several GPIO pins whereas STM32 RIF DT bindings (STM32MP2 GPIO) require 1 config/query per GPIO pin?
If so, I intentionally made it that way to better conform with STM32 DT binding st,protreg
that defines the default configuration of the GPIOs secure hardening. For STM32 RIF protected GPIOS, st,proret
requires 1 DT 32bit cell per GPIO whereas in STM32MP1 protected GPIO, the DT binding allows to configure several GPIOs with a single 32bit DT cell.
core/drivers/stm32_gpio.c
Outdated
@@ -394,6 +394,67 @@ static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) | |||
panic(); | |||
} | |||
|
|||
#ifdef CFG_STM32_RIF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#if defined(xxx)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
fdt_get_name(fdt, consumer_node, NULL), | ||
bank + 'A', pin); | ||
do_panic = true; | ||
} else if (!pin_is_accessible(bank_ref, pin)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pin_is_accessible()
should also be checked when pinctrl is applied IMO. Same story as the secure state, it can be reconfigured in the meanswhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'll fix.
for (n = 0; n < pin_count; n++) { | ||
struct stm32_gpio_bank *bank = stm32_gpio_get_bank(p[n].bank); | ||
|
||
if (p[n].cfg.nsec == !pin_is_secure(bank, p[n].pin)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think:
if (pin_is_secure(bank, p[n].pin) && p[n].cfg.nsec)
continue;
is clearer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 cases to consider:
if ((pin_is_secure(bank, p[n].pin) && !p[n].cfg.nsec) ||
(!pin_is_secure(bank, p[n].pin) && p[n].cfg.nsec))
I though it would be simpler on a single line.
core/drivers/stm32_gpio.c
Outdated
} | ||
|
||
if (error) | ||
return TEE_ERROR_GENERIC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TEE_ERROR_SECURITY?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. Thanks.
@@ -113,19 +113,13 @@ static void register_secure_uart(struct stm32_uart_pdata *pd __maybe_unused) | |||
{ | |||
#ifndef CFG_STM32MP25 | |||
stm32mp_register_secure_periph_iomem(pd->base.pa); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking at our static mapping, I don't think we need this as well, don't you agree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't, but let's address that is a specific series/P-R if you don't mind.
stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl); | ||
if (i2c_handle->pinctrl_sleep) | ||
stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl_sleep); | ||
|
||
stm32mp_register_non_secure_periph_iomem(i2c_handle->base.pa); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
For commit ditto for following pinctrl commit For commits: For commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review comments addressed or answered.
I'll rebase the series to resolve some rebase conflicts.
@@ -753,7 +754,7 @@ static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank) | |||
panic(); | |||
|
|||
for (i = 0; i < bank->ngpios; i++) { | |||
if (!(BIT(i) & bank->rif_cfg->access_mask[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bits set in gpios_mask
are also set in bank->rif_cfg->access_mask[0]
(see caller functions) hence testing gpios_mask
is enough IMHO. Maybe I should add an assertion at function entry?
assert(gpios_mask & bank->rif_cfg->access_mask[0] == gpios_mask);
@@ -793,7 +794,7 @@ static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank) | |||
} | |||
|
|||
for (i = 0; i < bank->ngpios; i++) { | |||
if (!(BIT(i) & bank->rif_cfg->access_mask[0])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
core/drivers/stm32_gpio.c
Outdated
return TEE_ERROR_BAD_PARAMETERS; | ||
|
||
if (bank->rif_cfg) { | ||
#ifdef CFG_STM32_RIF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
* Non RIF GPIO banks use TZPROT() bit mask (bits 0 to 15) | ||
* and GPIO_STM32_NSEC bit flag in the DT bindings. | ||
*/ | ||
gpios_mask = firewall->args[0] & GENMASK_32(15, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that STM32MP1 DT bindings allow a single firewall config/query to confgure several GPIO pins whereas STM32 RIF DT bindings (STM32MP2 GPIO) require 1 config/query per GPIO pin?
If so, I intentionally made it that way to better conform with STM32 DT binding st,protreg
that defines the default configuration of the GPIOs secure hardening. For STM32 RIF protected GPIOS, st,proret
requires 1 DT 32bit cell per GPIO whereas in STM32MP1 protected GPIO, the DT binding allows to configure several GPIOs with a single 32bit DT cell.
core/drivers/stm32_gpio.c
Outdated
@@ -394,6 +394,67 @@ static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) | |||
panic(); | |||
} | |||
|
|||
#ifdef CFG_STM32_RIF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
fdt_get_name(fdt, consumer_node, NULL), | ||
bank + 'A', pin); | ||
do_panic = true; | ||
} else if (!pin_is_accessible(bank_ref, pin)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'll fix.
for (n = 0; n < pin_count; n++) { | ||
struct stm32_gpio_bank *bank = stm32_gpio_get_bank(p[n].bank); | ||
|
||
if (p[n].cfg.nsec == !pin_is_secure(bank, p[n].pin)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 cases to consider:
if ((pin_is_secure(bank, p[n].pin) && !p[n].cfg.nsec) ||
(!pin_is_secure(bank, p[n].pin) && p[n].cfg.nsec))
I though it would be simpler on a single line.
core/drivers/stm32_gpio.c
Outdated
} | ||
|
||
if (error) | ||
return TEE_ERROR_GENERIC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. Thanks.
@@ -113,19 +113,13 @@ static void register_secure_uart(struct stm32_uart_pdata *pd __maybe_unused) | |||
{ | |||
#ifndef CFG_STM32MP25 | |||
stm32mp_register_secure_periph_iomem(pd->base.pa); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't, but let's address that is a specific series/P-R if you don't mind.
Define STM32 GPIO DT bindings bit flags for GPIOs that are to be used in non-secure state. Signed-off-by: Etienne Carriere <[email protected]>
Define stm32 pinctrl DT bindings bit flags for pins that are expected to be used in non-secure state. Signed-off-by: Etienne Carriere <[email protected]>
Add property #access-controller-cells to GPIO banks that register to the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
On STM32MP15 based devices, UART2/3/4/5/6/7/8 cannot be secured. Explicitly state that in the pinctrl nodes. This change ease the use of a non-secure UART for OP-TEE output console on STM32MP15 based boards. Signed-off-by: Etienne Carriere <[email protected]>
Explicitly state that legacy pinctrl phandles i2c4_pins_a and i2c4_sleep_pins_a refer to non-secure I2C4 pin muxing on STM32MP15 based platforms. Define secure I2C4 bus pinctrl states for boards that use the I2C4 bus in secure state on STM32MP15 SoCs. Signed-off-by: Etienne Carriere <[email protected]>
Explicitly state that legacy pinctrl phandles usart4_pins_a refer to non-secure USART4 pin muxing, used in STM32MP13 based boards for OP-TEE console using a non-secure UART bus. Define secure USART4 bus pinctrl states for board that needs to use the USART4 bus in secure state. Signed-off-by: Etienne Carriere <[email protected]>
Explicitly state that legacy pinctrl phandles usart2_pins_a refer to non-secure USART2 pin muxing, used in STM32MP23 and STM32MP25 based boards for OP-TEE console using a non-secure UART bus. Define secure USART2 bus pinctrl states for board that needs to use the USART2 bus in secure state. Signed-off-by: Etienne Carriere <[email protected]>
Check that a GPIO requested by a consumer is not already consumed by another device. Signed-off-by: Etienne Carriere <[email protected]>
Change apply_rif_config() to be able to call it for a subset of pins in a GPIO bank. Signed-off-by: Etienne Carriere <[email protected]>
Register secure aware STM32 GPIO banks to the firewall framework to allow GPIO and pinctrl consumer devices to load alternate configurations for pins. Signed-off-by: Etienne Carriere <[email protected]>
STM32 GPIO driver verifies that any GPIO consumed by OP-TEE can be accessed and has the expected secure hardening configuration. If a driver attempts to consume a GPIO that cannot be accessed by OP-TEE, core panics. Use newly added GPIO_STM32_NSEC bindings macro in STM32 GPIO driver DT bindings header file as hint on whether GPIO is expected secure or shared with non-secure world. When a GPIO is used with an inappropriate configuration state, STM32 GPIO driver panics or prints an info level message, depending on CFG_INSECURE. Signed-off-by: Etienne Carriere <[email protected]>
STM32 GPIO driver verifies that any pinctrl consumed by OP-TEE can be accessed and has the expected secure hardening configuration. If a driver attempts to consume a pinctrl with pins that cannot be accessed by OP-TEE, core panics. Non-secure pins must have the STM32_PIN_NSEC bit set in the pin handler argument unless what the pin is expected to be secure. The driver returns an error when the expected secure state of a pin does not match its effective secure state, unless CFG_INSECURE is enabled in which case the driver only prints an info level trace message. Signed-off-by: Etienne Carriere <[email protected]>
Remove management of GPIO and pinctrl secure state since this is now handled from STM32 ETZPC driver based through the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
Remove use of stm32_pinctrl_set_secure_cfg() to set the secure state of the pins of a pinctrl state since this is now handled from STM32 ETZPC driver based on the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
Remove use of stm32_pinctrl_set_secure_cfg() to set the secure state of the pins of a pinctrl state since this is now handled from STM32 ETZPC driver based on the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
Remove use of shared_resources platform driver to manage the secure state of the pins of a pinctrl state since this is now managed using the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
…ctrl Remove use of shared_resources platform driver in STM32MP15 PMIC driver to manage the secure state of the pins of a pinctrl state since this is now managed using the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
…tate Remove stm32_gpio_set_secure_cfg() and stm32_pinctrl_set_secure_cfg() functions that are no more used since the GPIO and pins secure state is defined by the st,protreg registers already handled from get_pinctrl_from_fdt() and stm32_gpio_get_dt() callback functions. Signed-off-by: Etienne Carriere <[email protected]>
Remove the pin and GPIO secure state management from shared_resources platform driver since this is now managed using the firewall framework. Signed-off-by: Etienne Carriere <[email protected]>
Make GPIO_STM32_NSEC consistent regarding TZPROT() definition. Signed-off-by: Etienne Carriere <[email protected]>
…l states USART4 cannot be secure on STM32MP13 devices hence remove USART4 secure pinctrl state. Signed-off-by: Etienne Carriere <[email protected]>
s/#ifdef/#if defined()/ Signed-off-by: Etienne Carriere <[email protected]>
s/#ifdef/#if defined()/ Signed-off-by: Etienne Carriere <[email protected]>
Check each pins can be accessed when applying a pinctrl state. Return TEE_ERROR_SECURITY instead of TEE_ERROR_GENERIC when failing to apply a pinctrl state due to the pin configuration access rights. Signed-off-by: Etienne Carriere <[email protected]>
0feb9c2
to
c3886b1
Compare
Rebased |
Assert there is a GPIO configuration for the GPIOs for which apply_rif_config() is called. Signed-off-by: Etienne Carriere <[email protected]>
a063d7d
to
31d7a49
Compare
This P-R makes stm32mp platforms to OP-TEE secure DTB to manage STM32 GPIO access rights. It tried to nicely split changes but it now spreads on almost 20 commits.
"dt-bindings: gpio: stm32mp: flags for non-secure GPIOs"
"dt-bindings: pinctrl: stm32mp: flags for non-secure pins"
"dts: stm32: ..."
"drivers: stm32_gpio: check GPIO is not already consumed"
"drivers: stm32_gpio: factorize apply_rif_config()"
"drivers: stm32_gpio: register to firewall framework"
"drivers: stm32_gpio: check secure state of consumed GPIOs"
"drivers: stm32_gpio: check secure state of pinctrl states"
"drivers: stm32_xxx: remove use of xxx() ..."
"plat-stm32mp1: remove use of xxx() ..."