On 5/26/25 12:46 PM, Oleksii Kurochko wrote:


On 5/22/25 9:50 AM, Jan Beulich wrote:
On 21.05.2025 18:03, Oleksii Kurochko wrote:
--- a/xen/arch/riscv/smpboot.c
+++ b/xen/arch/riscv/smpboot.c
@@ -1,5 +1,8 @@
  #include <xen/cpumask.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
  #include <xen/init.h>
+#include <xen/types.h>
  #include <xen/sections.h>
Nit: The latter insertion wants to move one line down. Yet then - isn't
xen/stdint.h sufficient here?
__be32 used in dt_get_hartid() is defined in xen/types.h.

@@ -14,3 +17,69 @@ void __init smp_prepare_boot_cpu(void)
      cpumask_set_cpu(0, &cpu_possible_map);
      cpumask_set_cpu(0, &cpu_online_map);
  }
+
+/**
+ * dt_get_hartid - Get the hartid from a CPU device node
+ *
+ * @cpun: CPU number(logical index) for which device node is required
+ *
+ * Return: The hartid for the CPU node or ~0UL if not found.
+ */
+static unsigned long dt_get_hartid(const struct dt_device_node *cpun)
+{
+    const __be32 *cell;
+    unsigned int ac;
+    uint32_t len;
+
+    ac = dt_n_addr_cells(cpun);
+    cell = dt_get_property(cpun, "reg", &len);
+    if ( !cell || !ac || ((sizeof(*cell) * ac) > len) )
Does DT make any guarantees for this multiplication to not overflow?
I haven't tried of DTC checks such things during compilation but considering 
that
ac value is uin32_t value (according to DT spec) then overflow could really 
happen.
I will add the following to check an overflow:
     if ( ac > ((sizeof(size_t) * BIT_PER_BYTE) / sizeof(*cell)) )
     {
         printk("%s: overflow detected\n", __func__);
         return ~0UL;
     }

Oops, I meant here size_t_max instead of (sizeof(size_t) * BIT_PER_BYTE), lost 
power of 2 minus 1.
Probably, SIZE_T_MAX or something similar exists. I have to check.

~ Oleksii


+        return ~0UL;
+
+    return dt_read_number(cell, ac);
+}
+
+/*
+ * Returns the hartid of the given device tree node, or -ENODEV if the node
+ * isn't an enabled and valid RISC-V hart node.
+ */
+int dt_processor_hartid(const struct dt_device_node *node,
+                        unsigned long *hartid)
+{
+    const char *isa;
+    int ret;
+
+    if ( !dt_device_is_compatible(node, "riscv") )
+    {
+        printk("Found incompatible CPU\n");
+        return -ENODEV;
+    }
+
+    *hartid = dt_get_hartid(node);
+    if ( *hartid == ~0UL )
+    {
+        printk("Found CPU without CPU ID\n");
+        return -ENODATA;
+    }
+
+    if ( !dt_device_is_available(node))
+    {
+        printk("CPU with hartid=%lu is not available\n", *hartid);
Considering that hart ID assignment is outside of our control, would we
perhaps better (uniformly) log such using %#lx?
It makes sense, DTC when generates dts from dtb also uses hex number, so it 
could
help to find a failure node faster.

+        return -ENODEV;
+    }
+
+    if ( (ret = dt_property_read_string(node, "riscv,isa", &isa)) )
+    {
+        printk("CPU with hartid=%lu has no \"riscv,isa\" property\n", *hartid);
+        return ret;
+    }
+
+    if ( isa[0] != 'r' || isa[1] != 'v' )
+    {
+        printk("CPU with hartid=%lu has an invalid ISA of \"%s\"\n", *hartid,
+               isa);
+        return -EINVAL;
As before -EINVAL is appropriate when input arguments have wrong values.
Here, however, you found an unexpected value in something the platform
has presented to you. While not entirely appropriate either, maybe
-ENODEV again (if nothing better can be found)?
I don't see better candidate.

Interesting if some reserved region exists for user
defined errors.

~ Oleksii

Reply via email to