libsel4vmmplatsupport: Generate arm cpus fdt node

Added a helper to the arm guest vcpu util interface that can
generates the cpu fdt node based on the vcpu's configured to a
specific VM. This can be appended to the fdt blob during
generation. This avoids presenting cpus to the Linux guest that
would otherwise be unavailable.
diff --git a/libsel4vmmplatsupport/arch_include/arm/sel4vmmplatsupport/arch/guest_vcpu_util.h b/libsel4vmmplatsupport/arch_include/arm/sel4vmmplatsupport/arch/guest_vcpu_util.h
new file mode 100644
index 0000000..68de714
--- /dev/null
+++ b/libsel4vmmplatsupport/arch_include/arm/sel4vmmplatsupport/arch/guest_vcpu_util.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#include <sel4vmmplatsupport/plat/guest_vcpu_util.h>
+
+int fdt_generate_plat_vcpu_node(vm_t *vm, void *fdt);
diff --git a/libsel4vmmplatsupport/include/sel4vmmplatsupport/guest_vcpu_util.h b/libsel4vmmplatsupport/include/sel4vmmplatsupport/guest_vcpu_util.h
index e55fcec..0074bcf 100644
--- a/libsel4vmmplatsupport/include/sel4vmmplatsupport/guest_vcpu_util.h
+++ b/libsel4vmmplatsupport/include/sel4vmmplatsupport/guest_vcpu_util.h
@@ -13,5 +13,6 @@
 #pragma once
 
 #include <sel4vm/guest_vm.h>
+#include <sel4vmmplatsupport/arch/guest_vcpu_util.h>
 
 vm_vcpu_t *create_vmm_plat_vcpu(vm_t *vm, int priority);
diff --git a/libsel4vmmplatsupport/plat_include/exynos5/sel4vmmplatsupport/plat/guest_vcpu_util.h b/libsel4vmmplatsupport/plat_include/exynos5/sel4vmmplatsupport/plat/guest_vcpu_util.h
new file mode 100644
index 0000000..b312eca
--- /dev/null
+++ b/libsel4vmmplatsupport/plat_include/exynos5/sel4vmmplatsupport/plat/guest_vcpu_util.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#define PLAT_CPU_COMPAT "arm,cortex-a15"
diff --git a/libsel4vmmplatsupport/plat_include/qemu-arm-virt/sel4vmmplatsupport/plat/guest_vcpu_util.h b/libsel4vmmplatsupport/plat_include/qemu-arm-virt/sel4vmmplatsupport/plat/guest_vcpu_util.h
new file mode 100644
index 0000000..c48d046
--- /dev/null
+++ b/libsel4vmmplatsupport/plat_include/qemu-arm-virt/sel4vmmplatsupport/plat/guest_vcpu_util.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#define PLAT_CPU_COMPAT "arm,cortex-a53"
diff --git a/libsel4vmmplatsupport/plat_include/tk1/sel4vmmplatsupport/plat/guest_vcpu_util.h b/libsel4vmmplatsupport/plat_include/tk1/sel4vmmplatsupport/plat/guest_vcpu_util.h
new file mode 100644
index 0000000..b312eca
--- /dev/null
+++ b/libsel4vmmplatsupport/plat_include/tk1/sel4vmmplatsupport/plat/guest_vcpu_util.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#define PLAT_CPU_COMPAT "arm,cortex-a15"
diff --git a/libsel4vmmplatsupport/plat_include/tx1/sel4vmmplatsupport/plat/guest_vcpu_util.h b/libsel4vmmplatsupport/plat_include/tx1/sel4vmmplatsupport/plat/guest_vcpu_util.h
new file mode 100644
index 0000000..bd7735b
--- /dev/null
+++ b/libsel4vmmplatsupport/plat_include/tx1/sel4vmmplatsupport/plat/guest_vcpu_util.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#define PLAT_CPU_COMPAT "arm,cortex-a57"
diff --git a/libsel4vmmplatsupport/plat_include/tx2/sel4vmmplatsupport/plat/guest_vcpu_util.h b/libsel4vmmplatsupport/plat_include/tx2/sel4vmmplatsupport/plat/guest_vcpu_util.h
new file mode 100644
index 0000000..a475091
--- /dev/null
+++ b/libsel4vmmplatsupport/plat_include/tx2/sel4vmmplatsupport/plat/guest_vcpu_util.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020, Data61
+ * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
+ * ABN 41 687 119 230.
+ *
+ * This software may be distributed and modified according to the terms of
+ * the BSD 2-Clause license. Note that NO WARRANTY is provided.
+ * See "LICENSE_BSD2.txt" for details.
+ *
+ * @TAG(DATA61_BSD)
+ */
+
+#define PLAT_CPU_COMPAT "arm,cortex-a57-64bit\0arm,armv8"
diff --git a/libsel4vmmplatsupport/src/arch/arm/guest_vcpu_util.c b/libsel4vmmplatsupport/src/arch/arm/guest_vcpu_util.c
index 301163d..ce99df9 100644
--- a/libsel4vmmplatsupport/src/arch/arm/guest_vcpu_util.c
+++ b/libsel4vmmplatsupport/src/arch/arm/guest_vcpu_util.c
@@ -18,6 +18,17 @@
 #include <sel4vmmplatsupport/arch/guest_vcpu_fault.h>
 #include <sel4vmmplatsupport/arch/irq_defs.h>
 
+#include <libfdt.h>
+#include <fdtgen.h>
+
+#define MAX_CPU_NAME_LENGTH 8
+
+#define FDT_OP(op)                                      \
+    do {                                                \
+        int err = (op);                                 \
+        ZF_LOGF_IF(err < 0, "FDT operation failed");    \
+    } while(0)                                          \
+
 static void vppi_event_ack(vm_vcpu_t *vcpu, int irq, void *cookie)
 {
     seL4_Error err = seL4_ARM_VCPU_AckVPPI(vcpu->vcpu.cptr, (seL4_Word)irq);
@@ -61,3 +72,49 @@
 
     return vm_vcpu;
 }
+
+static int generate_psci_node(void *fdt, int root_offset)
+{
+    int psci_node = fdt_add_subnode(fdt, root_offset, "psci");
+    if (psci_node < 0) {
+        return psci_node;
+    }
+    FDT_OP(fdt_appendprop_u32(fdt, psci_node, "cpu_off", 0x84000002));
+    FDT_OP(fdt_appendprop_u32(fdt, psci_node, "cpu_on", 0xc4000003));
+    FDT_OP(fdt_appendprop_u32(fdt, psci_node, "cpu_suspend", 0xc4000001));
+    FDT_OP(fdt_appendprop_string(fdt, psci_node, "method", "smc"));
+    FDT_OP(fdt_appendprop_string(fdt, psci_node, "compatible", "arm,psci-1.0"));
+    FDT_OP(fdt_appendprop_string(fdt, psci_node, "status", "okay"));
+    return 0;
+}
+
+int fdt_generate_plat_vcpu_node(vm_t *vm, void *fdt)
+{
+    int root_offset = fdt_path_offset(fdt, "/");
+    int cpu_node = fdt_add_subnode(fdt, root_offset, "cpus");
+    if (cpu_node < 0) {
+        return cpu_node;
+    }
+    FDT_OP(fdt_appendprop_u32(fdt, cpu_node, "#address-cells", 0x1));
+    FDT_OP(fdt_appendprop_u32(fdt, cpu_node, "#size-cells", 0x0));
+    for (int i = 0; i < vm->num_vcpus; i++) {
+        vm_vcpu_t *vcpu = vm->vcpus[i];
+        char cpu_name[MAX_CPU_NAME_LENGTH];
+        snprintf(cpu_name, MAX_CPU_NAME_LENGTH, "cpu@%x", vcpu->vcpu_id);
+        int sub_cpu_node = fdt_add_subnode(fdt, cpu_node, cpu_name);
+        if (sub_cpu_node < 0) {
+            return sub_cpu_node;
+        }
+        FDT_OP(fdt_appendprop_string(fdt, sub_cpu_node, "device_type", "cpu"));
+        FDT_OP(fdt_appendprop_string(fdt, sub_cpu_node, "compatible", PLAT_CPU_COMPAT));
+        FDT_OP(fdt_appendprop_u32(fdt, sub_cpu_node, "reg", vcpu->vcpu_id));
+        if (vm->num_vcpus > 1) {
+            FDT_OP(fdt_appendprop_string(fdt, sub_cpu_node, "enable-method", "psci"));
+        }
+    }
+    int ret = 0;
+    if (vm->num_vcpus > 1) {
+        ret = generate_psci_node(fdt, root_offset);
+    }
+    return 0;
+}