qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly
@ 2025-06-11 23:43 Tan Siewert
  2025-06-12  6:58 ` Cédric Le Goater
  0 siblings, 1 reply; 3+ messages in thread
From: Tan Siewert @ 2025-06-11 23:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Tan Siewert, Cédric Le Goater, Peter Maydell, Steven Lee,
	Troy Lee, Jamin Lin, Andrew Jeffery, Joel Stanley, qemu-arm

The AST2600 SCU has two protection key registers (0x00 and 0x10) that
both need to be unlocked. Each must be unlocked individually, but
locking one will lock both.

This commit updates the SCU write logic to reject writes unless both
protection key registers are unlocked, matching the behaviour of
real hardware.

Signed-off-by: Tan Siewert <tan@siewert.io>
---
 hw/misc/aspeed_scu.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 4930e00fed..8e9eac4629 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -91,6 +91,7 @@
 #define BMC_DEV_ID           TO_REG(0x1A4)
 
 #define AST2600_PROT_KEY          TO_REG(0x00)
+#define AST2600_PROT_KEY2         TO_REG(0x10)
 #define AST2600_SILICON_REV       TO_REG(0x04)
 #define AST2600_SILICON_REV2      TO_REG(0x14)
 #define AST2600_SYS_RST_CTRL      TO_REG(0x40)
@@ -722,6 +723,7 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
     int reg = TO_REG(offset);
     /* Truncate here so bitwise operations below behave as expected */
     uint32_t data = data64;
+    bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2];
 
     if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -730,7 +732,7 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
         return;
     }
 
-    if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
+    if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
     }
 
@@ -738,7 +740,18 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
 
     switch (reg) {
     case AST2600_PROT_KEY:
-        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
+    case AST2600_PROT_KEY2:
+        /*
+         * Writing a value other than the protection key will lock
+         * both protection registers, but unlocking must be done
+         * to each protection register individually.
+         */
+        if (data != ASPEED_SCU_PROT_KEY) {
+            s->regs[AST2600_PROT_KEY] = 0;
+            s->regs[AST2600_PROT_KEY2] = 0;
+        } else {
+            s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
+        }
         return;
     case AST2600_HW_STRAP1:
     case AST2600_HW_STRAP2:
-- 
2.49.0



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly
  2025-06-11 23:43 [PATCH] hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly Tan Siewert
@ 2025-06-12  6:58 ` Cédric Le Goater
  2025-06-12 14:01   ` Tan Siewert
  0 siblings, 1 reply; 3+ messages in thread
From: Cédric Le Goater @ 2025-06-12  6:58 UTC (permalink / raw)
  To: Tan Siewert, qemu-devel
  Cc: Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Andrew Jeffery,
	Joel Stanley, qemu-arm

On 6/12/25 01:43, Tan Siewert wrote:
> The AST2600 SCU has two protection key registers (0x00 and 0x10) that
> both need to be unlocked. Each must be unlocked individually, but
> locking one will lock both.
> 
> This commit updates the SCU write logic to reject writes unless both
> protection key registers are unlocked, matching the behaviour of
> real hardware.
> 
> Signed-off-by: Tan Siewert <tan@siewert.io>

LGTM,

Jamin, Steven, Troy ?


Thanks,

C.


> ---
>   hw/misc/aspeed_scu.c | 17 +++++++++++++++--
>   1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 4930e00fed..8e9eac4629 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -91,6 +91,7 @@
>   #define BMC_DEV_ID           TO_REG(0x1A4)
>   
>   #define AST2600_PROT_KEY          TO_REG(0x00)
> +#define AST2600_PROT_KEY2         TO_REG(0x10)
>   #define AST2600_SILICON_REV       TO_REG(0x04)
>   #define AST2600_SILICON_REV2      TO_REG(0x14)
>   #define AST2600_SYS_RST_CTRL      TO_REG(0x40)
> @@ -722,6 +723,7 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
>       int reg = TO_REG(offset);
>       /* Truncate here so bitwise operations below behave as expected */
>       uint32_t data = data64;
> +    bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2];
>   
>       if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
>           qemu_log_mask(LOG_GUEST_ERROR,
> @@ -730,7 +732,7 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
>           return;
>       }
>   
> -    if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
> +    if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) {
>           qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
>       }
>   
> @@ -738,7 +740,18 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
>   
>       switch (reg) {
>       case AST2600_PROT_KEY:
> -        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> +    case AST2600_PROT_KEY2:
> +        /*
> +         * Writing a value other than the protection key will lock
> +         * both protection registers, but unlocking must be done
> +         * to each protection register individually.
> +         */
> +        if (data != ASPEED_SCU_PROT_KEY) {
> +            s->regs[AST2600_PROT_KEY] = 0;
> +            s->regs[AST2600_PROT_KEY2] = 0;
> +        } else {
> +            s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> +        }
>           return;
>       case AST2600_HW_STRAP1:
>       case AST2600_HW_STRAP2:



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly
  2025-06-12  6:58 ` Cédric Le Goater
@ 2025-06-12 14:01   ` Tan Siewert
  0 siblings, 0 replies; 3+ messages in thread
From: Tan Siewert @ 2025-06-12 14:01 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-devel
  Cc: Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Andrew Jeffery,
	Joel Stanley, qemu-arm

On 12.06.25 08:58, Cédric Le Goater wrote:
> LGTM,
> 
> Jamin, Steven, Troy ?
> 

On 12.06.25 01:43, Tan Siewert wrote:
>> -    if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
>> +    if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && ! 
>> unlocked) {
>>           qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", 
>> __func__);
>>       }

I just noticed that this never return when the SCU is locked, meaning 
you can still write to the SCU registers even though it is locked. I'll 
send a v2 in a few minutes that addresses this issue too.

The AST2500 SCU handles this correctly here.

Sorry for that!

Cheers,
Tan

>> @@ -738,7 +740,18 @@ static void aspeed_ast2600_scu_write(void 
>> *opaque, hwaddr offset,
>>       switch (reg) {
>>       case AST2600_PROT_KEY:
>> -        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
>> +    case AST2600_PROT_KEY2:
>> +        /*
>> +         * Writing a value other than the protection key will lock
>> +         * both protection registers, but unlocking must be done
>> +         * to each protection register individually.
>> +         */
>> +        if (data != ASPEED_SCU_PROT_KEY) {
>> +            s->regs[AST2600_PROT_KEY] = 0;
>> +            s->regs[AST2600_PROT_KEY2] = 0;
>> +        } else {
>> +            s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
>> +        }
>>           return;
>>       case AST2600_HW_STRAP1:
>>       case AST2600_HW_STRAP2:
> 



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-06-12 14:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-11 23:43 [PATCH] hw/misc/aspeed_scu: Handle AST2600 protection key registers correctly Tan Siewert
2025-06-12  6:58 ` Cédric Le Goater
2025-06-12 14:01   ` Tan Siewert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).