[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xen/riscv: bound each IMSIC MMIO regset by the per-group hart slots



imsic_init() requires every MMIO register set to be exactly
IMSIC_HART_SIZE(guest_index_bits) * nr_parent_irqs bytes, i.e. to cover
the interrupt files of all harts listed in interrupts-extended. This only
holds when the DT describes a single register set.

When harts are split into groups (riscv,group-index-bits > 0), each group
has its own register set, which only covers the harts of that group. For
example, the SpacemiT V100 IMSIC node describes two 2 MiB register sets,
each holding 64 hart slots of 32 KiB, with 128 parent interrupts in total.
Xen expects 4 MiB per register set and fails with:

  IMSIC MMIO size is incorrect 2097152, expected MMIO size: 4194304

A register set can also be smaller than its slot space, when the number
of harts in a group is not a power of two.

Check instead that a register set does not exceed the address space of
one group of BIT(hart_index_bits) hart slots.

While at it, print the MMIO sizes in hex, so they can be compared directly
with the reg property of the DT node.

Fixes: c9bd8b322ecb ("xen/riscv: imsic_init() implementation")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>
---
 xen/arch/riscv/imsic.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c
index 44b8640ea3..255ac44b52 100644
--- a/xen/arch/riscv/imsic.c
+++ b/xen/arch/riscv/imsic.c
@@ -416,8 +416,8 @@ int __init imsic_init(const struct dt_device_node *node)
     for ( unsigned int i = 0; i < nr_mmios; i++ )
     {
         unsigned int guest_bits = imsic_cfg.guest_index_bits;
-        unsigned long expected_mmio_size =
-            IMSIC_HART_SIZE(guest_bits) * nr_parent_irqs;
+        unsigned long max_mmio_regset_size =
+            IMSIC_HART_SIZE(guest_bits) * BIT(imsic_cfg.hart_index_bits, U);
 
         rc = dt_device_get_address(node, i, &mmios[i].base_addr,
                                    &mmios[i].size);
@@ -442,11 +442,11 @@ int __init imsic_init(const struct dt_device_node *node)
             goto imsic_init_err;
         }
 
-        if ( mmios[i].size != expected_mmio_size )
+        if ( mmios[i].size > max_mmio_regset_size )
         {
             rc = -EINVAL;
-            printk(XENLOG_ERR "%s: IMSIC MMIO size is incorrect %ld, expected 
MMIO size: %ld\n",
-                   node->name, mmios[i].size, expected_mmio_size);
+            printk(XENLOG_ERR "%s: IMSIC MMIO regset %u size %#lx larger than 
max %#lx\n",
+                   node->name, i, mmios[i].size, max_mmio_regset_size);
             goto imsic_init_err;
         }
     }

---
base-commit: 97bf370375113caf92fccf04e2877fc6b5ff887f
change-id: 20261113-fix-imsic-mmio-dt-c3317ac2efec

Best regards,
--  
Baptiste Le Duc <baptiste.le-duc@xxxxxxxxxx>




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.