17c0e8b0cSWill Deacon #include "kvm/devices.h" 27c0e8b0cSWill Deacon #include "kvm/fdt.h" 37c0e8b0cSWill Deacon #include "kvm/kvm.h" 47c0e8b0cSWill Deacon #include "kvm/kvm-cpu.h" 57c0e8b0cSWill Deacon #include "kvm/virtio-mmio.h" 67c0e8b0cSWill Deacon 77c0e8b0cSWill Deacon #include "arm-common/gic.h" 87c0e8b0cSWill Deacon 97c0e8b0cSWill Deacon #include <stdbool.h> 107c0e8b0cSWill Deacon 117c0e8b0cSWill Deacon #include <asm/setup.h> 127c0e8b0cSWill Deacon #include <linux/byteorder.h> 137c0e8b0cSWill Deacon #include <linux/kernel.h> 147c0e8b0cSWill Deacon #include <linux/sizes.h> 157c0e8b0cSWill Deacon 167c0e8b0cSWill Deacon #define DEBUG 0 177c0e8b0cSWill Deacon #define DEBUG_FDT_DUMP_FILE "/tmp/kvmtool.dtb" 187c0e8b0cSWill Deacon 197c0e8b0cSWill Deacon static char kern_cmdline[COMMAND_LINE_SIZE]; 207c0e8b0cSWill Deacon 217c0e8b0cSWill Deacon bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) 227c0e8b0cSWill Deacon { 237c0e8b0cSWill Deacon return false; 247c0e8b0cSWill Deacon } 257c0e8b0cSWill Deacon 267c0e8b0cSWill Deacon int kvm__arch_setup_firmware(struct kvm *kvm) 277c0e8b0cSWill Deacon { 287c0e8b0cSWill Deacon return 0; 297c0e8b0cSWill Deacon } 307c0e8b0cSWill Deacon 317c0e8b0cSWill Deacon #if DEBUG 327c0e8b0cSWill Deacon static void dump_fdt(void *fdt) 337c0e8b0cSWill Deacon { 347c0e8b0cSWill Deacon int count, fd; 357c0e8b0cSWill Deacon 367c0e8b0cSWill Deacon fd = open(DEBUG_FDT_DUMP_FILE, O_CREAT | O_TRUNC | O_RDWR, 0666); 377c0e8b0cSWill Deacon if (fd < 0) 387c0e8b0cSWill Deacon die("Failed to write dtb to %s", DEBUG_FDT_DUMP_FILE); 397c0e8b0cSWill Deacon 407c0e8b0cSWill Deacon count = write(fd, fdt, FDT_MAX_SIZE); 417c0e8b0cSWill Deacon if (count < 0) 427c0e8b0cSWill Deacon die_perror("Failed to dump dtb"); 437c0e8b0cSWill Deacon 447c0e8b0cSWill Deacon pr_info("Wrote %d bytes to dtb %s\n", count, DEBUG_FDT_DUMP_FILE); 457c0e8b0cSWill Deacon close(fd); 467c0e8b0cSWill Deacon } 477c0e8b0cSWill Deacon #else 487c0e8b0cSWill Deacon static void dump_fdt(void *fdt) { } 497c0e8b0cSWill Deacon #endif 507c0e8b0cSWill Deacon 517c0e8b0cSWill Deacon #define DEVICE_NAME_MAX_LEN 32 527c0e8b0cSWill Deacon static void generate_virtio_mmio_node(void *fdt, struct virtio_mmio *vmmio) 537c0e8b0cSWill Deacon { 547c0e8b0cSWill Deacon char dev_name[DEVICE_NAME_MAX_LEN]; 557c0e8b0cSWill Deacon u64 addr = vmmio->addr; 567c0e8b0cSWill Deacon u64 reg_prop[] = { 577c0e8b0cSWill Deacon cpu_to_fdt64(addr), 587c0e8b0cSWill Deacon cpu_to_fdt64(VIRTIO_MMIO_IO_SIZE) 597c0e8b0cSWill Deacon }; 607c0e8b0cSWill Deacon u32 irq_prop[] = { 617c0e8b0cSWill Deacon cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), 627c0e8b0cSWill Deacon cpu_to_fdt32(vmmio->irq - GIC_SPI_IRQ_BASE), 637c0e8b0cSWill Deacon cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), 647c0e8b0cSWill Deacon }; 657c0e8b0cSWill Deacon 667c0e8b0cSWill Deacon snprintf(dev_name, DEVICE_NAME_MAX_LEN, "virtio@%llx", addr); 677c0e8b0cSWill Deacon 687c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, dev_name)); 697c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "virtio,mmio")); 707c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 717c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop))); 727c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 737c0e8b0cSWill Deacon } 747c0e8b0cSWill Deacon 757c0e8b0cSWill Deacon static int setup_fdt(struct kvm *kvm) 767c0e8b0cSWill Deacon { 777c0e8b0cSWill Deacon struct device_header *dev_hdr; 787c0e8b0cSWill Deacon u8 staging_fdt[FDT_MAX_SIZE]; 797c0e8b0cSWill Deacon u32 gic_phandle = fdt__alloc_phandle(); 807c0e8b0cSWill Deacon u64 mem_reg_prop[] = { 817c0e8b0cSWill Deacon cpu_to_fdt64(kvm->arch.memory_guest_start), 827c0e8b0cSWill Deacon cpu_to_fdt64(kvm->ram_size), 837c0e8b0cSWill Deacon }; 847c0e8b0cSWill Deacon void *fdt = staging_fdt; 857c0e8b0cSWill Deacon void *fdt_dest = guest_flat_to_host(kvm, 867c0e8b0cSWill Deacon kvm->arch.dtb_guest_start); 877c0e8b0cSWill Deacon void (*generate_cpu_nodes)(void *, struct kvm *, u32) 887c0e8b0cSWill Deacon = kvm->cpus[0]->generate_fdt_nodes; 897c0e8b0cSWill Deacon 907c0e8b0cSWill Deacon /* Create new tree without a reserve map */ 917c0e8b0cSWill Deacon _FDT(fdt_create(fdt, FDT_MAX_SIZE)); 927c0e8b0cSWill Deacon if (kvm->nrcpus > 1) 937c0e8b0cSWill Deacon _FDT(fdt_add_reservemap_entry(fdt, 947c0e8b0cSWill Deacon kvm->arch.smp_pen_guest_start, 957c0e8b0cSWill Deacon ARM_SMP_PEN_SIZE)); 967c0e8b0cSWill Deacon _FDT(fdt_finish_reservemap(fdt)); 977c0e8b0cSWill Deacon 987c0e8b0cSWill Deacon /* Header */ 997c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "")); 1007c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "interrupt-parent", gic_phandle)); 1017c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "linux,dummy-virt")); 1027c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#address-cells", 0x2)); 1037c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#size-cells", 0x2)); 1047c0e8b0cSWill Deacon 1057c0e8b0cSWill Deacon /* /chosen */ 1067c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "chosen")); 1077c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "bootargs", kern_cmdline)); 1087c0e8b0cSWill Deacon 1097c0e8b0cSWill Deacon /* Initrd */ 1107c0e8b0cSWill Deacon if (kvm->arch.initrd_size != 0) { 1117c0e8b0cSWill Deacon u32 ird_st_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start); 1127c0e8b0cSWill Deacon u32 ird_end_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start + 1137c0e8b0cSWill Deacon kvm->arch.initrd_size); 1147c0e8b0cSWill Deacon 1157c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "linux,initrd-start", 1167c0e8b0cSWill Deacon &ird_st_prop, sizeof(ird_st_prop))); 1177c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "linux,initrd-end", 1187c0e8b0cSWill Deacon &ird_end_prop, sizeof(ird_end_prop))); 1197c0e8b0cSWill Deacon } 1207c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 1217c0e8b0cSWill Deacon 1227c0e8b0cSWill Deacon /* Memory */ 1237c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "memory")); 1247c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "device_type", "memory")); 1257c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop))); 1267c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 1277c0e8b0cSWill Deacon 1287c0e8b0cSWill Deacon /* CPU and peripherals (interrupt controller, timers, etc) */ 1297c0e8b0cSWill Deacon if (generate_cpu_nodes) 1307c0e8b0cSWill Deacon generate_cpu_nodes(fdt, kvm, gic_phandle); 1317c0e8b0cSWill Deacon 1327c0e8b0cSWill Deacon /* Virtio MMIO devices */ 1337c0e8b0cSWill Deacon dev_hdr = device__first_dev(DEVICE_BUS_MMIO); 1347c0e8b0cSWill Deacon while (dev_hdr) { 1357c0e8b0cSWill Deacon generate_virtio_mmio_node(fdt, dev_hdr->data); 1367c0e8b0cSWill Deacon dev_hdr = device__next_dev(dev_hdr); 1377c0e8b0cSWill Deacon } 1387c0e8b0cSWill Deacon 1397c0e8b0cSWill Deacon /* Finalise. */ 1407c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 1417c0e8b0cSWill Deacon _FDT(fdt_finish(fdt)); 1427c0e8b0cSWill Deacon 1437c0e8b0cSWill Deacon _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE)); 1447c0e8b0cSWill Deacon _FDT(fdt_pack(fdt_dest)); 1457c0e8b0cSWill Deacon 1467c0e8b0cSWill Deacon dump_fdt(fdt_dest); 1477c0e8b0cSWill Deacon return 0; 1487c0e8b0cSWill Deacon } 1497c0e8b0cSWill Deacon late_init(setup_fdt); 1507c0e8b0cSWill Deacon 1517c0e8b0cSWill Deacon static int read_image(int fd, void **pos, void *limit) 1527c0e8b0cSWill Deacon { 1537c0e8b0cSWill Deacon int count; 1547c0e8b0cSWill Deacon 1557c0e8b0cSWill Deacon while (((count = xread(fd, *pos, SZ_64K)) > 0) && *pos <= limit) 1567c0e8b0cSWill Deacon *pos += count; 1577c0e8b0cSWill Deacon 1587c0e8b0cSWill Deacon if (pos < 0) 1597c0e8b0cSWill Deacon die_perror("xread"); 1607c0e8b0cSWill Deacon 1617c0e8b0cSWill Deacon return *pos < limit ? 0 : -ENOMEM; 1627c0e8b0cSWill Deacon } 1637c0e8b0cSWill Deacon 1647c0e8b0cSWill Deacon #define FDT_ALIGN SZ_2M 1657c0e8b0cSWill Deacon #define INITRD_ALIGN 4 1667c0e8b0cSWill Deacon #define SMP_PEN_ALIGN PAGE_SIZE 1677c0e8b0cSWill Deacon int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, 1687c0e8b0cSWill Deacon const char *kernel_cmdline) 1697c0e8b0cSWill Deacon { 1707c0e8b0cSWill Deacon void *pos, *kernel_end, *limit; 1717c0e8b0cSWill Deacon unsigned long guest_addr; 1727c0e8b0cSWill Deacon 1737c0e8b0cSWill Deacon if (lseek(fd_kernel, 0, SEEK_SET) < 0) 1747c0e8b0cSWill Deacon die_perror("lseek"); 1757c0e8b0cSWill Deacon 1767c0e8b0cSWill Deacon /* 1777c0e8b0cSWill Deacon * Linux requires the initrd, pen and dtb to be mapped inside 1787c0e8b0cSWill Deacon * lowmem, so we can't just place them at the top of memory. 1797c0e8b0cSWill Deacon */ 1807c0e8b0cSWill Deacon limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 1817c0e8b0cSWill Deacon 1827c0e8b0cSWill Deacon pos = kvm->ram_start + ARM_KERN_OFFSET; 1837c0e8b0cSWill Deacon kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 1847c0e8b0cSWill Deacon if (read_image(fd_kernel, &pos, limit) == -ENOMEM) 1857c0e8b0cSWill Deacon die("kernel image too big to contain in guest memory."); 1867c0e8b0cSWill Deacon 1877c0e8b0cSWill Deacon kernel_end = pos; 1887c0e8b0cSWill Deacon pr_info("Loaded kernel to 0x%llx (%llu bytes)", 1897c0e8b0cSWill Deacon kvm->arch.kern_guest_start, 1907c0e8b0cSWill Deacon host_to_guest_flat(kvm, pos) - kvm->arch.kern_guest_start); 1917c0e8b0cSWill Deacon 1927c0e8b0cSWill Deacon /* 1937c0e8b0cSWill Deacon * Now load backwards from the end of memory so the kernel 1947c0e8b0cSWill Deacon * decompressor has plenty of space to work with. First up is 1957c0e8b0cSWill Deacon * the SMP pen if we have more than one virtual CPU... 1967c0e8b0cSWill Deacon */ 1977c0e8b0cSWill Deacon pos = limit; 1987c0e8b0cSWill Deacon if (kvm->cfg.nrcpus > 1) { 1997c0e8b0cSWill Deacon pos -= (ARM_SMP_PEN_SIZE + SMP_PEN_ALIGN); 2007c0e8b0cSWill Deacon guest_addr = ALIGN(host_to_guest_flat(kvm, pos), SMP_PEN_ALIGN); 2017c0e8b0cSWill Deacon pos = guest_flat_to_host(kvm, guest_addr); 2027c0e8b0cSWill Deacon if (pos < kernel_end) 2037c0e8b0cSWill Deacon die("SMP pen overlaps with kernel image."); 2047c0e8b0cSWill Deacon 2057c0e8b0cSWill Deacon kvm->arch.smp_pen_guest_start = guest_addr; 2067c0e8b0cSWill Deacon pr_info("Placing SMP pen at 0x%llx - 0x%llx", 2077c0e8b0cSWill Deacon kvm->arch.smp_pen_guest_start, 2087c0e8b0cSWill Deacon host_to_guest_flat(kvm, limit)); 2097c0e8b0cSWill Deacon limit = pos; 2107c0e8b0cSWill Deacon } 2117c0e8b0cSWill Deacon 2127c0e8b0cSWill Deacon /* ...now the device tree blob... */ 2137c0e8b0cSWill Deacon pos -= (FDT_MAX_SIZE + FDT_ALIGN); 2147c0e8b0cSWill Deacon guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 2157c0e8b0cSWill Deacon pos = guest_flat_to_host(kvm, guest_addr); 2167c0e8b0cSWill Deacon if (pos < kernel_end) 2177c0e8b0cSWill Deacon die("fdt overlaps with kernel image."); 2187c0e8b0cSWill Deacon 2197c0e8b0cSWill Deacon kvm->arch.dtb_guest_start = guest_addr; 2207c0e8b0cSWill Deacon pr_info("Placing fdt at 0x%llx - 0x%llx", 2217c0e8b0cSWill Deacon kvm->arch.dtb_guest_start, 2227c0e8b0cSWill Deacon host_to_guest_flat(kvm, limit)); 2237c0e8b0cSWill Deacon limit = pos; 2247c0e8b0cSWill Deacon 2257c0e8b0cSWill Deacon /* ... and finally the initrd, if we have one. */ 2267c0e8b0cSWill Deacon if (fd_initrd != -1) { 2277c0e8b0cSWill Deacon struct stat sb; 2287c0e8b0cSWill Deacon unsigned long initrd_start; 2297c0e8b0cSWill Deacon 2307c0e8b0cSWill Deacon if (lseek(fd_initrd, 0, SEEK_SET) < 0) 2317c0e8b0cSWill Deacon die_perror("lseek"); 2327c0e8b0cSWill Deacon 2337c0e8b0cSWill Deacon if (fstat(fd_initrd, &sb)) 2347c0e8b0cSWill Deacon die_perror("fstat"); 2357c0e8b0cSWill Deacon 2367c0e8b0cSWill Deacon pos -= (sb.st_size + INITRD_ALIGN); 2377c0e8b0cSWill Deacon guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 2387c0e8b0cSWill Deacon pos = guest_flat_to_host(kvm, guest_addr); 2397c0e8b0cSWill Deacon if (pos < kernel_end) 2407c0e8b0cSWill Deacon die("initrd overlaps with kernel image."); 2417c0e8b0cSWill Deacon 2427c0e8b0cSWill Deacon initrd_start = guest_addr; 2437c0e8b0cSWill Deacon if (read_image(fd_initrd, &pos, limit) == -ENOMEM) 2447c0e8b0cSWill Deacon die("initrd too big to contain in guest memory."); 2457c0e8b0cSWill Deacon 2467c0e8b0cSWill Deacon kvm->arch.initrd_guest_start = initrd_start; 2477c0e8b0cSWill Deacon kvm->arch.initrd_size = host_to_guest_flat(kvm, pos) - initrd_start; 2487c0e8b0cSWill Deacon pr_info("Loaded initrd to 0x%llx (%llu bytes)", 2497c0e8b0cSWill Deacon kvm->arch.initrd_guest_start, 2507c0e8b0cSWill Deacon kvm->arch.initrd_size); 2517c0e8b0cSWill Deacon } else { 2527c0e8b0cSWill Deacon kvm->arch.initrd_size = 0; 2537c0e8b0cSWill Deacon } 2547c0e8b0cSWill Deacon 2557c0e8b0cSWill Deacon strncpy(kern_cmdline, kernel_cmdline, COMMAND_LINE_SIZE); 2567c0e8b0cSWill Deacon kern_cmdline[COMMAND_LINE_SIZE - 1] = '\0'; 2577c0e8b0cSWill Deacon 2587c0e8b0cSWill Deacon return true; 2597c0e8b0cSWill Deacon } 2607c0e8b0cSWill Deacon 261*ff7ba6faSWill Deacon bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, 262*ff7ba6faSWill Deacon const char *kernel_cmdline) 2637c0e8b0cSWill Deacon { 2647c0e8b0cSWill Deacon /* To b or not to b? That is the zImage. */ 2657c0e8b0cSWill Deacon return false; 2667c0e8b0cSWill Deacon } 267