17c9aac00SAnup Patel #include "kvm/devices.h"
27c9aac00SAnup Patel #include "kvm/fdt.h"
37c9aac00SAnup Patel #include "kvm/kvm.h"
47c9aac00SAnup Patel #include "kvm/kvm-cpu.h"
57c9aac00SAnup Patel
67c9aac00SAnup Patel #include <stdbool.h>
77c9aac00SAnup Patel
87c9aac00SAnup Patel #include <linux/byteorder.h>
97c9aac00SAnup Patel #include <linux/kernel.h>
107c9aac00SAnup Patel #include <linux/sizes.h>
117c9aac00SAnup Patel
128aff29e1SAtish Patra struct isa_ext_info {
138aff29e1SAtish Patra const char *name;
148aff29e1SAtish Patra unsigned long ext_id;
158aff29e1SAtish Patra };
168aff29e1SAtish Patra
178aff29e1SAtish Patra struct isa_ext_info isa_info_arr[] = {
18b346fabeSAnup Patel /* sorted alphabetically */
198d02d5a8SAnup Patel {"smstateen", KVM_RISCV_ISA_EXT_SMSTATEEN},
208659200fSAnup Patel {"ssaia", KVM_RISCV_ISA_EXT_SSAIA},
21*fa958fb6SAtish Patra {"sscofpmf", KVM_RISCV_ISA_EXT_SSCOFPMF},
223c07aeafSAtish Patra {"sstc", KVM_RISCV_ISA_EXT_SSTC},
23ac16e943SAnup Patel {"svinval", KVM_RISCV_ISA_EXT_SVINVAL},
2456e2d678SAnup Patel {"svnapot", KVM_RISCV_ISA_EXT_SVNAPOT},
25b346fabeSAnup Patel {"svpbmt", KVM_RISCV_ISA_EXT_SVPBMT},
2632f81036SAnup Patel {"zacas", KVM_RISCV_ISA_EXT_ZACAS},
276331850dSAnup Patel {"zba", KVM_RISCV_ISA_EXT_ZBA},
288c1584e7SAnup Patel {"zbb", KVM_RISCV_ISA_EXT_ZBB},
298b4cc705SAnup Patel {"zbc", KVM_RISCV_ISA_EXT_ZBC},
30d9052a96SAnup Patel {"zbkb", KVM_RISCV_ISA_EXT_ZBKB},
31d9052a96SAnup Patel {"zbkc", KVM_RISCV_ISA_EXT_ZBKC},
32d9052a96SAnup Patel {"zbkx", KVM_RISCV_ISA_EXT_ZBKX},
336331850dSAnup Patel {"zbs", KVM_RISCV_ISA_EXT_ZBS},
349cf213d6SAnup Patel {"zfa", KVM_RISCV_ISA_EXT_ZFA},
35bd7f13c1SAnup Patel {"zfh", KVM_RISCV_ISA_EXT_ZFH},
36bd7f13c1SAnup Patel {"zfhmin", KVM_RISCV_ISA_EXT_ZFHMIN},
37798398f4SAndrew Jones {"zicbom", KVM_RISCV_ISA_EXT_ZICBOM},
388f1e47caSAndrew Jones {"zicboz", KVM_RISCV_ISA_EXT_ZICBOZ},
3966768569SAnup Patel {"zicntr", KVM_RISCV_ISA_EXT_ZICNTR},
408cd71ca5SAnup Patel {"zicond", KVM_RISCV_ISA_EXT_ZICOND},
4134366849SAnup Patel {"zicsr", KVM_RISCV_ISA_EXT_ZICSR},
4234366849SAnup Patel {"zifencei", KVM_RISCV_ISA_EXT_ZIFENCEI},
43fce28652SAnup Patel {"zihintntl", KVM_RISCV_ISA_EXT_ZIHINTNTL},
44b346fabeSAnup Patel {"zihintpause", KVM_RISCV_ISA_EXT_ZIHINTPAUSE},
4566768569SAnup Patel {"zihpm", KVM_RISCV_ISA_EXT_ZIHPM},
46d9052a96SAnup Patel {"zknd", KVM_RISCV_ISA_EXT_ZKND},
47d9052a96SAnup Patel {"zkne", KVM_RISCV_ISA_EXT_ZKNE},
48d9052a96SAnup Patel {"zknh", KVM_RISCV_ISA_EXT_ZKNH},
49d9052a96SAnup Patel {"zkr", KVM_RISCV_ISA_EXT_ZKR},
50d9052a96SAnup Patel {"zksed", KVM_RISCV_ISA_EXT_ZKSED},
51d9052a96SAnup Patel {"zksh", KVM_RISCV_ISA_EXT_ZKSH},
52d9052a96SAnup Patel {"zkt", KVM_RISCV_ISA_EXT_ZKT},
53a20adc64SAnup Patel {"ztso", KVM_RISCV_ISA_EXT_ZTSO},
5465b58f72SAnup Patel {"zvbb", KVM_RISCV_ISA_EXT_ZVBB},
5565b58f72SAnup Patel {"zvbc", KVM_RISCV_ISA_EXT_ZVBC},
565a64c1eaSAnup Patel {"zvfh", KVM_RISCV_ISA_EXT_ZVFH},
575a64c1eaSAnup Patel {"zvfhmin", KVM_RISCV_ISA_EXT_ZVFHMIN},
5865b58f72SAnup Patel {"zvkb", KVM_RISCV_ISA_EXT_ZVKB},
5965b58f72SAnup Patel {"zvkg", KVM_RISCV_ISA_EXT_ZVKG},
6065b58f72SAnup Patel {"zvkned", KVM_RISCV_ISA_EXT_ZVKNED},
6165b58f72SAnup Patel {"zvknha", KVM_RISCV_ISA_EXT_ZVKNHA},
6265b58f72SAnup Patel {"zvknhb", KVM_RISCV_ISA_EXT_ZVKNHB},
6365b58f72SAnup Patel {"zvksed", KVM_RISCV_ISA_EXT_ZVKSED},
6465b58f72SAnup Patel {"zvksh", KVM_RISCV_ISA_EXT_ZVKSH},
6565b58f72SAnup Patel {"zvkt", KVM_RISCV_ISA_EXT_ZVKT},
668aff29e1SAtish Patra };
678aff29e1SAtish Patra
dump_fdt(const char * dtb_file,void * fdt)687c9aac00SAnup Patel static void dump_fdt(const char *dtb_file, void *fdt)
697c9aac00SAnup Patel {
707c9aac00SAnup Patel int count, fd;
717c9aac00SAnup Patel
727c9aac00SAnup Patel fd = open(dtb_file, O_CREAT | O_TRUNC | O_RDWR, 0666);
737c9aac00SAnup Patel if (fd < 0)
747c9aac00SAnup Patel die("Failed to write dtb to %s", dtb_file);
757c9aac00SAnup Patel
767c9aac00SAnup Patel count = write(fd, fdt, FDT_MAX_SIZE);
777c9aac00SAnup Patel if (count < 0)
787c9aac00SAnup Patel die_perror("Failed to dump dtb");
797c9aac00SAnup Patel
807c9aac00SAnup Patel pr_debug("Wrote %d bytes to dtb %s", count, dtb_file);
817c9aac00SAnup Patel close(fd);
827c9aac00SAnup Patel }
837c9aac00SAnup Patel
847c9aac00SAnup Patel #define CPU_NAME_MAX_LEN 15
generate_cpu_nodes(void * fdt,struct kvm * kvm)857c9aac00SAnup Patel static void generate_cpu_nodes(void *fdt, struct kvm *kvm)
867c9aac00SAnup Patel {
877c9aac00SAnup Patel int cpu, pos, i, index, valid_isa_len;
887c9aac00SAnup Patel const char *valid_isa_order = "IEMAFDQCLBJTPVNSUHKORWXYZG";
898aff29e1SAtish Patra int arr_sz = ARRAY_SIZE(isa_info_arr);
90ef89838eSAnup Patel unsigned long cbom_blksz = 0, cboz_blksz = 0, satp_mode = 0;
917c9aac00SAnup Patel
927c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, "cpus"));
937c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
947c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#size-cells", 0x0));
957c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "timebase-frequency",
967c9aac00SAnup Patel kvm->cpus[0]->riscv_timebase));
977c9aac00SAnup Patel
987c9aac00SAnup Patel for (cpu = 0; cpu < kvm->nrcpus; ++cpu) {
997c9aac00SAnup Patel char cpu_name[CPU_NAME_MAX_LEN];
1007887b398SAnup Patel #define CPU_ISA_MAX_LEN (ARRAY_SIZE(isa_info_arr) * 16)
1017c9aac00SAnup Patel char cpu_isa[CPU_ISA_MAX_LEN];
1027c9aac00SAnup Patel struct kvm_cpu *vcpu = kvm->cpus[cpu];
1038aff29e1SAtish Patra struct kvm_one_reg reg;
1048aff29e1SAtish Patra unsigned long isa_ext_out = 0;
1057c9aac00SAnup Patel
1067c9aac00SAnup Patel snprintf(cpu_name, CPU_NAME_MAX_LEN, "cpu@%x", cpu);
1077c9aac00SAnup Patel
1087c9aac00SAnup Patel snprintf(cpu_isa, CPU_ISA_MAX_LEN, "rv%ld", vcpu->riscv_xlen);
1097c9aac00SAnup Patel pos = strlen(cpu_isa);
1107c9aac00SAnup Patel valid_isa_len = strlen(valid_isa_order);
1117c9aac00SAnup Patel for (i = 0; i < valid_isa_len; i++) {
1127c9aac00SAnup Patel index = valid_isa_order[i] - 'A';
1137c9aac00SAnup Patel if (vcpu->riscv_isa & (1 << (index)))
1147c9aac00SAnup Patel cpu_isa[pos++] = 'a' + index;
1157c9aac00SAnup Patel }
1168aff29e1SAtish Patra
1178aff29e1SAtish Patra for (i = 0; i < arr_sz; i++) {
1188aff29e1SAtish Patra reg.id = RISCV_ISA_EXT_REG(isa_info_arr[i].ext_id);
1198aff29e1SAtish Patra reg.addr = (unsigned long)&isa_ext_out;
1208aff29e1SAtish Patra if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0)
1218aff29e1SAtish Patra continue;
1228aff29e1SAtish Patra if (!isa_ext_out)
1238aff29e1SAtish Patra /* This extension is not available in hardware */
1248aff29e1SAtish Patra continue;
1258aff29e1SAtish Patra
126e17d182aSAnup Patel if (kvm->cfg.arch.ext_disabled[isa_info_arr[i].ext_id]) {
127e17d182aSAnup Patel isa_ext_out = 0;
128e17d182aSAnup Patel if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, ®) < 0)
129e17d182aSAnup Patel pr_warning("Failed to disable %s ISA exension\n",
130e17d182aSAnup Patel isa_info_arr[i].name);
131e17d182aSAnup Patel continue;
132e17d182aSAnup Patel }
133e17d182aSAnup Patel
134798398f4SAndrew Jones if (isa_info_arr[i].ext_id == KVM_RISCV_ISA_EXT_ZICBOM && !cbom_blksz) {
135798398f4SAndrew Jones reg.id = RISCV_CONFIG_REG(zicbom_block_size);
136798398f4SAndrew Jones reg.addr = (unsigned long)&cbom_blksz;
137798398f4SAndrew Jones if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0)
138798398f4SAndrew Jones die("KVM_GET_ONE_REG failed (config.zicbom_block_size)");
139798398f4SAndrew Jones }
140798398f4SAndrew Jones
1418f1e47caSAndrew Jones if (isa_info_arr[i].ext_id == KVM_RISCV_ISA_EXT_ZICBOZ && !cboz_blksz) {
1428f1e47caSAndrew Jones reg.id = RISCV_CONFIG_REG(zicboz_block_size);
1438f1e47caSAndrew Jones reg.addr = (unsigned long)&cboz_blksz;
1448f1e47caSAndrew Jones if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0)
1458f1e47caSAndrew Jones die("KVM_GET_ONE_REG failed (config.zicboz_block_size)");
1468f1e47caSAndrew Jones }
1478f1e47caSAndrew Jones
1488aff29e1SAtish Patra if ((strlen(isa_info_arr[i].name) + pos + 1) >= CPU_ISA_MAX_LEN) {
149fcb07675SAnup Patel pr_warning("Insufficient space to append ISA exension %s\n",
150fcb07675SAnup Patel isa_info_arr[i].name);
1518aff29e1SAtish Patra break;
1528aff29e1SAtish Patra }
1538aff29e1SAtish Patra pos += snprintf(cpu_isa + pos, CPU_ISA_MAX_LEN, "_%s",
1548aff29e1SAtish Patra isa_info_arr[i].name);
1558aff29e1SAtish Patra }
1567c9aac00SAnup Patel cpu_isa[pos] = '\0';
1577c9aac00SAnup Patel
158ef89838eSAnup Patel reg.id = RISCV_CONFIG_REG(satp_mode);
159ef89838eSAnup Patel reg.addr = (unsigned long)&satp_mode;
160ef89838eSAnup Patel if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, ®) < 0)
161ef89838eSAnup Patel satp_mode = (vcpu->riscv_xlen == 64) ? 8 : 1;
162ef89838eSAnup Patel
1637c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, cpu_name));
1647c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "device_type", "cpu"));
1657c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "compatible", "riscv"));
166ef89838eSAnup Patel if (vcpu->riscv_xlen == 64) {
167ef89838eSAnup Patel switch (satp_mode) {
168ef89838eSAnup Patel case 10:
169ef89838eSAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
170ef89838eSAnup Patel "riscv,sv57"));
171ef89838eSAnup Patel break;
172ef89838eSAnup Patel case 9:
1737c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
1747c9aac00SAnup Patel "riscv,sv48"));
175ef89838eSAnup Patel break;
176ef89838eSAnup Patel case 8:
177ef89838eSAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
178ef89838eSAnup Patel "riscv,sv39"));
179ef89838eSAnup Patel break;
180ef89838eSAnup Patel default:
181ef89838eSAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
182ef89838eSAnup Patel "riscv,none"));
183ef89838eSAnup Patel break;
184ef89838eSAnup Patel }
185ef89838eSAnup Patel } else {
186ef89838eSAnup Patel switch (satp_mode) {
187ef89838eSAnup Patel case 1:
1887c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
1897c9aac00SAnup Patel "riscv,sv32"));
190ef89838eSAnup Patel break;
191ef89838eSAnup Patel default:
192ef89838eSAnup Patel _FDT(fdt_property_string(fdt, "mmu-type",
193ef89838eSAnup Patel "riscv,none"));
194ef89838eSAnup Patel break;
195ef89838eSAnup Patel }
196ef89838eSAnup Patel }
1977c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "riscv,isa", cpu_isa));
198798398f4SAndrew Jones if (cbom_blksz)
199798398f4SAndrew Jones _FDT(fdt_property_cell(fdt, "riscv,cbom-block-size", cbom_blksz));
2008f1e47caSAndrew Jones if (cboz_blksz)
2018f1e47caSAndrew Jones _FDT(fdt_property_cell(fdt, "riscv,cboz-block-size", cboz_blksz));
2027c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "reg", cpu));
2037c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "status", "okay"));
2047c9aac00SAnup Patel
2057c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, "interrupt-controller"));
2067c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "compatible", "riscv,cpu-intc"));
2077c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#interrupt-cells", 1));
2087c9aac00SAnup Patel _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
2097c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "phandle",
2107c9aac00SAnup Patel PHANDLE_CPU_INTC_BASE + cpu));
2117c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
2127c9aac00SAnup Patel
2137c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
2147c9aac00SAnup Patel }
2157c9aac00SAnup Patel
2167c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
2177c9aac00SAnup Patel }
2187c9aac00SAnup Patel
setup_fdt(struct kvm * kvm)2197c9aac00SAnup Patel static int setup_fdt(struct kvm *kvm)
2207c9aac00SAnup Patel {
2217c9aac00SAnup Patel struct device_header *dev_hdr;
2227c9aac00SAnup Patel u8 staging_fdt[FDT_MAX_SIZE];
2237c9aac00SAnup Patel u64 mem_reg_prop[] = {
2247c9aac00SAnup Patel cpu_to_fdt64(kvm->arch.memory_guest_start),
2257c9aac00SAnup Patel cpu_to_fdt64(kvm->ram_size),
2267c9aac00SAnup Patel };
227ed805be5SAnup Patel char *str;
2287c9aac00SAnup Patel void *fdt = staging_fdt;
2297c9aac00SAnup Patel void *fdt_dest = guest_flat_to_host(kvm,
2307c9aac00SAnup Patel kvm->arch.dtb_guest_start);
2317c9aac00SAnup Patel void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
2327c9aac00SAnup Patel void (*)(void *, u8, enum irq_type));
2337c9aac00SAnup Patel
2347c9aac00SAnup Patel /* Create new tree without a reserve map */
2357c9aac00SAnup Patel _FDT(fdt_create(fdt, FDT_MAX_SIZE));
2367c9aac00SAnup Patel _FDT(fdt_finish_reservemap(fdt));
2377c9aac00SAnup Patel
2387c9aac00SAnup Patel /* Header */
2397c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, ""));
2407c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "compatible", "linux,dummy-virt"));
2417c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
2427c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
2437c9aac00SAnup Patel
2447c9aac00SAnup Patel /* /chosen */
2457c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, "chosen"));
2467c9aac00SAnup Patel
2477c9aac00SAnup Patel /* Pass on our amended command line to a Linux kernel only. */
2487c9aac00SAnup Patel if (kvm->cfg.firmware_filename) {
2497c9aac00SAnup Patel if (kvm->cfg.kernel_cmdline)
2507c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "bootargs",
2517c9aac00SAnup Patel kvm->cfg.kernel_cmdline));
2527c9aac00SAnup Patel } else
2537c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "bootargs",
2547c9aac00SAnup Patel kvm->cfg.real_cmdline));
2557c9aac00SAnup Patel
2567c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "stdout-path", "serial0"));
2577c9aac00SAnup Patel
2587c9aac00SAnup Patel /* Initrd */
2597c9aac00SAnup Patel if (kvm->arch.initrd_size != 0) {
2607c9aac00SAnup Patel u64 ird_st_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start);
2617c9aac00SAnup Patel u64 ird_end_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start +
2627c9aac00SAnup Patel kvm->arch.initrd_size);
2637c9aac00SAnup Patel
2647c9aac00SAnup Patel _FDT(fdt_property(fdt, "linux,initrd-start",
2657c9aac00SAnup Patel &ird_st_prop, sizeof(ird_st_prop)));
2667c9aac00SAnup Patel _FDT(fdt_property(fdt, "linux,initrd-end",
2677c9aac00SAnup Patel &ird_end_prop, sizeof(ird_end_prop)));
2687c9aac00SAnup Patel }
2697c9aac00SAnup Patel
2707c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
2717c9aac00SAnup Patel
2727c9aac00SAnup Patel /* Memory */
2737c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, "memory"));
2747c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "device_type", "memory"));
2757c9aac00SAnup Patel _FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop)));
2767c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
2777c9aac00SAnup Patel
2787c9aac00SAnup Patel /* CPUs */
2797c9aac00SAnup Patel generate_cpu_nodes(fdt, kvm);
2807c9aac00SAnup Patel
2810dff3501SAnup Patel /* IRQCHIP */
2820dff3501SAnup Patel if (!riscv_irqchip_generate_fdt_node)
2830dff3501SAnup Patel die("No way to generate IRQCHIP FDT node\n");
2840dff3501SAnup Patel riscv_irqchip_generate_fdt_node(fdt, kvm);
2850dff3501SAnup Patel
2867c9aac00SAnup Patel /* Simple Bus */
2877c9aac00SAnup Patel _FDT(fdt_begin_node(fdt, "smb"));
2887c9aac00SAnup Patel _FDT(fdt_property_string(fdt, "compatible", "simple-bus"));
2897c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
2907c9aac00SAnup Patel _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
2910dff3501SAnup Patel _FDT(fdt_property_cell(fdt, "interrupt-parent",
2920dff3501SAnup Patel riscv_irqchip_phandle));
2937c9aac00SAnup Patel _FDT(fdt_property(fdt, "ranges", NULL, 0));
2947c9aac00SAnup Patel
2957c9aac00SAnup Patel /* Virtio MMIO devices */
2967c9aac00SAnup Patel dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
2977c9aac00SAnup Patel while (dev_hdr) {
2987c9aac00SAnup Patel generate_mmio_fdt_nodes = dev_hdr->data;
2990dff3501SAnup Patel generate_mmio_fdt_nodes(fdt, dev_hdr,
3000dff3501SAnup Patel riscv__generate_irq_prop);
3017c9aac00SAnup Patel dev_hdr = device__next_dev(dev_hdr);
3027c9aac00SAnup Patel }
3037c9aac00SAnup Patel
3047c9aac00SAnup Patel /* IOPORT devices */
3057c9aac00SAnup Patel dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
3067c9aac00SAnup Patel while (dev_hdr) {
3077c9aac00SAnup Patel generate_mmio_fdt_nodes = dev_hdr->data;
3080dff3501SAnup Patel generate_mmio_fdt_nodes(fdt, dev_hdr,
3090dff3501SAnup Patel riscv__generate_irq_prop);
3107c9aac00SAnup Patel dev_hdr = device__next_dev(dev_hdr);
3117c9aac00SAnup Patel }
3127c9aac00SAnup Patel
313cdd7d8ccSAnup Patel /* PCI host controller */
314cdd7d8ccSAnup Patel pci__generate_fdt_nodes(fdt);
315cdd7d8ccSAnup Patel
3167c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
3177c9aac00SAnup Patel
3187c9aac00SAnup Patel if (fdt_stdout_path) {
319ed805be5SAnup Patel str = malloc(strlen(fdt_stdout_path) + strlen("/smb") + 1);
320ed805be5SAnup Patel sprintf(str, "/smb%s", fdt_stdout_path);
3217c9aac00SAnup Patel free(fdt_stdout_path);
3227c9aac00SAnup Patel fdt_stdout_path = NULL;
323ed805be5SAnup Patel
324ed805be5SAnup Patel _FDT(fdt_begin_node(fdt, "aliases"));
325ed805be5SAnup Patel _FDT(fdt_property_string(fdt, "serial0", str));
326ed805be5SAnup Patel _FDT(fdt_end_node(fdt));
327ed805be5SAnup Patel free(str);
3287c9aac00SAnup Patel }
3297c9aac00SAnup Patel
3307c9aac00SAnup Patel /* Finalise. */
3317c9aac00SAnup Patel _FDT(fdt_end_node(fdt));
3327c9aac00SAnup Patel _FDT(fdt_finish(fdt));
3337c9aac00SAnup Patel
3347c9aac00SAnup Patel _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
3357c9aac00SAnup Patel _FDT(fdt_pack(fdt_dest));
3367c9aac00SAnup Patel
3377c9aac00SAnup Patel if (kvm->cfg.arch.dump_dtb_filename)
3387c9aac00SAnup Patel dump_fdt(kvm->cfg.arch.dump_dtb_filename, fdt_dest);
3397c9aac00SAnup Patel return 0;
3407c9aac00SAnup Patel }
3417c9aac00SAnup Patel late_init(setup_fdt);
342