platform: generic: Add support for specify coldboot harts in DT
authorCheng Yang <yangcheng.work@foxmail.com>
Thu, 8 Feb 2024 03:14:32 +0000 (11:14 +0800)
committerAnup Patel <anup@brainfault.org>
Tue, 20 Feb 2024 10:19:36 +0000 (15:49 +0530)
Added support for the generic platform to specify the set of coldboot
hart in DT. If not specified in DT, all harts are allowed to coldboot
as before.

The functions related to sbi_hartmask are not available before coldboot,
so I used bitmap, and added a new bitmap_test() function to test whether
a certain bit of the bitmap is set.

Signed-off-by: Cheng Yang <yangcheng.work@foxmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
include/sbi/sbi_bitmap.h
lib/utils/fdt/fdt_fixup.c
platform/generic/platform.c

index 4f0ebb63a6993a24cc5eb812844f614d90fc71c5..354476c9dd811346a650a611ccc34c1bff1c02c5 100644 (file)
@@ -62,6 +62,11 @@ static inline void bitmap_zero(unsigned long *dst, int nbits)
        }
 }
 
+static inline int bitmap_test(unsigned long *bmap, int bit)
+{
+       return __test_bit(bit, bmap);
+}
+
 static inline void bitmap_zero_except(unsigned long *dst,
                                      int exception, int nbits)
 {
index 5fc76738077ec124b382529d7c43272e26f819a9..194e55b3a82f616a0c12ad6e2221d55b0ff31933 100644 (file)
@@ -385,6 +385,21 @@ int fdt_reserved_memory_fixup(void *fdt)
        return 0;
 }
 
+void fdt_config_fixup(void *fdt)
+{
+       int chosen_offset, config_offset;
+
+       chosen_offset = fdt_path_offset(fdt, "/chosen");
+       if (chosen_offset < 0)
+               return;
+
+       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
+       if (chosen_offset < 0)
+               return;
+
+       fdt_nop_node(fdt, config_offset);
+}
+
 void fdt_fixups(void *fdt)
 {
        fdt_aplic_fixup(fdt);
@@ -398,4 +413,6 @@ void fdt_fixups(void *fdt)
 #ifndef CONFIG_FDT_FIXUPS_PRESERVE_PMU_NODE
        fdt_pmu_fixup(fdt);
 #endif
+
+       fdt_config_fixup(fdt);
 }
index bfd7d318fe66a10d0db4ccdfbe0aed3753a0d9af..00c6c2e27358735712436c9a501c81891e86f1fe 100644 (file)
@@ -73,6 +73,61 @@ extern struct sbi_platform platform;
 static bool platform_has_mlevel_imsic = false;
 static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
 
+static DECLARE_BITMAP(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+
+/*
+ * The fw_platform_coldboot_harts_init() function is called by fw_platform_init() 
+ * function to initialize the cold boot harts allowed by the generic platform
+ * according to the DT property "cold-boot-harts" in "/chosen/opensbi-config" 
+ * DT node. If there is no "cold-boot-harts" in DT, all harts will be allowed.
+ */
+static void fw_platform_coldboot_harts_init(void *fdt)
+{
+       int chosen_offset, config_offset, cpu_offset, len, err;
+       u32 val32;
+       const u32 *val;
+
+       bitmap_zero(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+
+       chosen_offset = fdt_path_offset(fdt, "/chosen");
+       if (chosen_offset < 0)
+               goto default_config;
+
+       config_offset = fdt_node_offset_by_compatible(fdt, chosen_offset, "opensbi,config");
+       if (config_offset < 0)
+               goto default_config;
+
+       val = fdt_getprop(fdt, config_offset, "cold-boot-harts", &len);
+       len = len / sizeof(u32);
+       if (val && len) {
+               for (int i = 0; i < len; i++) {
+                       cpu_offset = fdt_node_offset_by_phandle(fdt,
+                                                       fdt32_to_cpu(val[i]));
+                       if (cpu_offset < 0)
+                               goto default_config;
+
+                       err = fdt_parse_hart_id(fdt, cpu_offset, &val32);
+                       if (err)
+                               goto default_config;
+
+                       if (!fdt_node_is_enabled(fdt, cpu_offset))
+                               continue;
+
+                       for (int i = 0; i < platform.hart_count; i++) {
+                               if (val32 == generic_hart_index2id[i])
+                                       bitmap_set(generic_coldboot_harts, i, 1);
+                       }
+
+               }
+       }
+
+       return;
+
+default_config:
+       bitmap_fill(generic_coldboot_harts, SBI_HARTMASK_MAX_BITS);
+       return;
+}
+
 /*
  * The fw_platform_init() function is called very early on the boot HART
  * OpenSBI reference firmwares so that platform specific code get chance
@@ -133,6 +188,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
        platform.heap_size = fw_platform_calculate_heap_size(hart_count);
        platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
 
+       fw_platform_coldboot_harts_init(fdt);
+
        /* Return original FDT pointer */
        return arg1;
 
@@ -146,7 +203,13 @@ static bool generic_cold_boot_allowed(u32 hartid)
        if (generic_plat && generic_plat->cold_boot_allowed)
                return generic_plat->cold_boot_allowed(
                                                hartid, generic_plat_match);
-       return true;
+
+       for (int i = 0; i < platform.hart_count; i++) {
+               if (hartid == generic_hart_index2id[i])
+                       return bitmap_test(generic_coldboot_harts, i);
+       }
+
+       return false;
 }
 
 static int generic_nascent_init(void)