[2/5] aspeed/smc: Do not map disabled segment on the AST2600
diff mbox series

Message ID 20191114094544.30114-3-clg@kaod.org
State New
Headers show
Series
  • aspeed: AST2600 SMC fixes and tacoma-bmc machine
Related show

Commit Message

Cédric Le Goater Nov. 14, 2019, 9:45 a.m. UTC
The segments can be disabled on the AST2600 (zero register value).
CS0 is open by default but not the other CS. This is closing the
access to the flash device in user mode and forbids scanning.

In the model, check the segment size and disable the associated region
when the value is zero.

Fixes: bcaa8ddd081c ("aspeed/smc: Add AST2600 support")
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

Comments

Joel Stanley Nov. 18, 2019, 7:13 a.m. UTC | #1
On Thu, 14 Nov 2019 at 09:46, Cédric Le Goater <clg@kaod.org> wrote:
>
> The segments can be disabled on the AST2600 (zero register value).
> CS0 is open by default but not the other CS. This is closing the
> access to the flash device in user mode and forbids scanning.
>
> In the model, check the segment size and disable the associated region
> when the value is zero.
>
> Fixes: bcaa8ddd081c ("aspeed/smc: Add AST2600 support")
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 955ec21852ac..86cadbe4cc00 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -444,8 +444,13 @@ static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
>      uint32_t start_offset = (reg << 16) & AST2600_SEG_ADDR_MASK;
>      uint32_t end_offset = reg & AST2600_SEG_ADDR_MASK;
>
> -    seg->addr = s->ctrl->flash_window_base + start_offset;
> -    seg->size = end_offset + MiB - start_offset;
> +    if (reg) {
> +        seg->addr = s->ctrl->flash_window_base + start_offset;
> +        seg->size = end_offset + MiB - start_offset;
> +    } else {
> +        seg->addr = s->ctrl->flash_window_base;
> +        seg->size = 0;
> +    }
>  }
>
>  static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
> @@ -486,7 +491,7 @@ static void aspeed_smc_flash_set_segment_region(AspeedSMCState *s, int cs,
>      memory_region_transaction_begin();
>      memory_region_set_size(&fl->mmio, seg.size);
>      memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
> -    memory_region_set_enabled(&fl->mmio, true);
> +    memory_region_set_enabled(&fl->mmio, !!seg.size);
>      memory_region_transaction_commit();
>
>      s->regs[R_SEG_ADDR0 + cs] = regval;
> @@ -526,8 +531,9 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
>      }
>
>      /* Keep the segment in the overall flash window */
> -    if (seg.addr + seg.size <= s->ctrl->flash_window_base ||
> -        seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size) {
> +    if (seg.size &&
> +        (seg.addr + seg.size <= s->ctrl->flash_window_base ||
> +         seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is invalid : "
>                        "[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
>                        s->ctrl->name, cs, seg.addr, seg.addr + seg.size);
> --
> 2.21.0
>

Patch
diff mbox series

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 955ec21852ac..86cadbe4cc00 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -444,8 +444,13 @@  static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
     uint32_t start_offset = (reg << 16) & AST2600_SEG_ADDR_MASK;
     uint32_t end_offset = reg & AST2600_SEG_ADDR_MASK;
 
-    seg->addr = s->ctrl->flash_window_base + start_offset;
-    seg->size = end_offset + MiB - start_offset;
+    if (reg) {
+        seg->addr = s->ctrl->flash_window_base + start_offset;
+        seg->size = end_offset + MiB - start_offset;
+    } else {
+        seg->addr = s->ctrl->flash_window_base;
+        seg->size = 0;
+    }
 }
 
 static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
@@ -486,7 +491,7 @@  static void aspeed_smc_flash_set_segment_region(AspeedSMCState *s, int cs,
     memory_region_transaction_begin();
     memory_region_set_size(&fl->mmio, seg.size);
     memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
-    memory_region_set_enabled(&fl->mmio, true);
+    memory_region_set_enabled(&fl->mmio, !!seg.size);
     memory_region_transaction_commit();
 
     s->regs[R_SEG_ADDR0 + cs] = regval;
@@ -526,8 +531,9 @@  static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
     }
 
     /* Keep the segment in the overall flash window */
-    if (seg.addr + seg.size <= s->ctrl->flash_window_base ||
-        seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size) {
+    if (seg.size &&
+        (seg.addr + seg.size <= s->ctrl->flash_window_base ||
+         seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size)) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is invalid : "
                       "[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
                       s->ctrl->name, cs, seg.addr, seg.addr + seg.size);