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" 816242d27SWill Deacon #include "arm-common/pci.h" 97c0e8b0cSWill Deacon 107c0e8b0cSWill Deacon #include <stdbool.h> 117c0e8b0cSWill Deacon 127c0e8b0cSWill Deacon #include <asm/setup.h> 137c0e8b0cSWill Deacon #include <linux/byteorder.h> 147c0e8b0cSWill Deacon #include <linux/kernel.h> 157c0e8b0cSWill Deacon #include <linux/sizes.h> 16*c2dad402SAnup Patel #include <linux/psci.h> 177c0e8b0cSWill Deacon 187c0e8b0cSWill Deacon static char kern_cmdline[COMMAND_LINE_SIZE]; 197c0e8b0cSWill Deacon 207c0e8b0cSWill Deacon bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) 217c0e8b0cSWill Deacon { 227c0e8b0cSWill Deacon return false; 237c0e8b0cSWill Deacon } 247c0e8b0cSWill Deacon 257c0e8b0cSWill Deacon int kvm__arch_setup_firmware(struct kvm *kvm) 267c0e8b0cSWill Deacon { 277c0e8b0cSWill Deacon return 0; 287c0e8b0cSWill Deacon } 297c0e8b0cSWill Deacon 30ba27ff46SWill Deacon static void dump_fdt(const char *dtb_file, void *fdt) 317c0e8b0cSWill Deacon { 327c0e8b0cSWill Deacon int count, fd; 337c0e8b0cSWill Deacon 34ba27ff46SWill Deacon fd = open(dtb_file, O_CREAT | O_TRUNC | O_RDWR, 0666); 357c0e8b0cSWill Deacon if (fd < 0) 36ba27ff46SWill Deacon die("Failed to write dtb to %s", dtb_file); 377c0e8b0cSWill Deacon 387c0e8b0cSWill Deacon count = write(fd, fdt, FDT_MAX_SIZE); 397c0e8b0cSWill Deacon if (count < 0) 407c0e8b0cSWill Deacon die_perror("Failed to dump dtb"); 417c0e8b0cSWill Deacon 42ba27ff46SWill Deacon pr_info("Wrote %d bytes to dtb %s\n", count, dtb_file); 437c0e8b0cSWill Deacon close(fd); 447c0e8b0cSWill Deacon } 457c0e8b0cSWill Deacon 46beff7ae0SMarc Zyngier #define CPU_NAME_MAX_LEN 8 47beff7ae0SMarc Zyngier static void generate_cpu_nodes(void *fdt, struct kvm *kvm) 48beff7ae0SMarc Zyngier { 49beff7ae0SMarc Zyngier int cpu; 50beff7ae0SMarc Zyngier 51beff7ae0SMarc Zyngier _FDT(fdt_begin_node(fdt, "cpus")); 52beff7ae0SMarc Zyngier _FDT(fdt_property_cell(fdt, "#address-cells", 0x1)); 53beff7ae0SMarc Zyngier _FDT(fdt_property_cell(fdt, "#size-cells", 0x0)); 54beff7ae0SMarc Zyngier 55beff7ae0SMarc Zyngier for (cpu = 0; cpu < kvm->nrcpus; ++cpu) { 56beff7ae0SMarc Zyngier char cpu_name[CPU_NAME_MAX_LEN]; 57d06bc640SMarc Zyngier struct kvm_cpu *vcpu = kvm->cpus[cpu]; 58d06bc640SMarc Zyngier unsigned long mpidr = kvm_cpu__get_vcpu_mpidr(vcpu); 59beff7ae0SMarc Zyngier 60d06bc640SMarc Zyngier mpidr &= ARM_MPIDR_HWID_BITMASK; 61d06bc640SMarc Zyngier snprintf(cpu_name, CPU_NAME_MAX_LEN, "cpu@%lx", mpidr); 62beff7ae0SMarc Zyngier 63beff7ae0SMarc Zyngier _FDT(fdt_begin_node(fdt, cpu_name)); 64beff7ae0SMarc Zyngier _FDT(fdt_property_string(fdt, "device_type", "cpu")); 65d06bc640SMarc Zyngier _FDT(fdt_property_string(fdt, "compatible", vcpu->cpu_compatible)); 66beff7ae0SMarc Zyngier 67beff7ae0SMarc Zyngier if (kvm->nrcpus > 1) 68beff7ae0SMarc Zyngier _FDT(fdt_property_string(fdt, "enable-method", "psci")); 69beff7ae0SMarc Zyngier 70d06bc640SMarc Zyngier _FDT(fdt_property_cell(fdt, "reg", mpidr)); 71beff7ae0SMarc Zyngier _FDT(fdt_end_node(fdt)); 72beff7ae0SMarc Zyngier } 73beff7ae0SMarc Zyngier 74beff7ae0SMarc Zyngier _FDT(fdt_end_node(fdt)); 75beff7ae0SMarc Zyngier } 76beff7ae0SMarc Zyngier 772454c7dcSWill Deacon static void generate_irq_prop(void *fdt, u8 irq) 787c0e8b0cSWill Deacon { 797c0e8b0cSWill Deacon u32 irq_prop[] = { 807c0e8b0cSWill Deacon cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), 812454c7dcSWill Deacon cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE), 827c0e8b0cSWill Deacon cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), 837c0e8b0cSWill Deacon }; 847c0e8b0cSWill Deacon 857c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop))); 867c0e8b0cSWill Deacon } 877c0e8b0cSWill Deacon 88*c2dad402SAnup Patel struct psci_fns { 89*c2dad402SAnup Patel u32 cpu_suspend; 90*c2dad402SAnup Patel u32 cpu_off; 91*c2dad402SAnup Patel u32 cpu_on; 92*c2dad402SAnup Patel u32 migrate; 93*c2dad402SAnup Patel }; 94*c2dad402SAnup Patel 95*c2dad402SAnup Patel static struct psci_fns psci_0_1_fns = { 96*c2dad402SAnup Patel .cpu_suspend = KVM_PSCI_FN_CPU_SUSPEND, 97*c2dad402SAnup Patel .cpu_off = KVM_PSCI_FN_CPU_OFF, 98*c2dad402SAnup Patel .cpu_on = KVM_PSCI_FN_CPU_ON, 99*c2dad402SAnup Patel .migrate = KVM_PSCI_FN_MIGRATE, 100*c2dad402SAnup Patel }; 101*c2dad402SAnup Patel 102*c2dad402SAnup Patel static struct psci_fns psci_0_2_aarch32_fns = { 103*c2dad402SAnup Patel .cpu_suspend = PSCI_0_2_FN_CPU_SUSPEND, 104*c2dad402SAnup Patel .cpu_off = PSCI_0_2_FN_CPU_OFF, 105*c2dad402SAnup Patel .cpu_on = PSCI_0_2_FN_CPU_ON, 106*c2dad402SAnup Patel .migrate = PSCI_0_2_FN_MIGRATE, 107*c2dad402SAnup Patel }; 108*c2dad402SAnup Patel 109*c2dad402SAnup Patel static struct psci_fns psci_0_2_aarch64_fns = { 110*c2dad402SAnup Patel .cpu_suspend = PSCI_0_2_FN64_CPU_SUSPEND, 111*c2dad402SAnup Patel .cpu_off = PSCI_0_2_FN_CPU_OFF, 112*c2dad402SAnup Patel .cpu_on = PSCI_0_2_FN64_CPU_ON, 113*c2dad402SAnup Patel .migrate = PSCI_0_2_FN64_MIGRATE, 114*c2dad402SAnup Patel }; 115*c2dad402SAnup Patel 1167c0e8b0cSWill Deacon static int setup_fdt(struct kvm *kvm) 1177c0e8b0cSWill Deacon { 1187c0e8b0cSWill Deacon struct device_header *dev_hdr; 1197c0e8b0cSWill Deacon u8 staging_fdt[FDT_MAX_SIZE]; 1207c0e8b0cSWill Deacon u32 gic_phandle = fdt__alloc_phandle(); 1217c0e8b0cSWill Deacon u64 mem_reg_prop[] = { 1227c0e8b0cSWill Deacon cpu_to_fdt64(kvm->arch.memory_guest_start), 1237c0e8b0cSWill Deacon cpu_to_fdt64(kvm->ram_size), 1247c0e8b0cSWill Deacon }; 125*c2dad402SAnup Patel struct psci_fns *fns; 1267c0e8b0cSWill Deacon void *fdt = staging_fdt; 1277c0e8b0cSWill Deacon void *fdt_dest = guest_flat_to_host(kvm, 1287c0e8b0cSWill Deacon kvm->arch.dtb_guest_start); 1292454c7dcSWill Deacon void (*generate_mmio_fdt_nodes)(void *, struct device_header *, 1302454c7dcSWill Deacon void (*)(void *, u8)); 1312454c7dcSWill Deacon void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32) 1327c0e8b0cSWill Deacon = kvm->cpus[0]->generate_fdt_nodes; 1337c0e8b0cSWill Deacon 1347c0e8b0cSWill Deacon /* Create new tree without a reserve map */ 1357c0e8b0cSWill Deacon _FDT(fdt_create(fdt, FDT_MAX_SIZE)); 1367c0e8b0cSWill Deacon _FDT(fdt_finish_reservemap(fdt)); 1377c0e8b0cSWill Deacon 1387c0e8b0cSWill Deacon /* Header */ 1397c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "")); 1407c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "interrupt-parent", gic_phandle)); 1417c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "linux,dummy-virt")); 1427c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#address-cells", 0x2)); 1437c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#size-cells", 0x2)); 1447c0e8b0cSWill Deacon 1457c0e8b0cSWill Deacon /* /chosen */ 1467c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "chosen")); 1471fcf0d77SWill Deacon _FDT(fdt_property_cell(fdt, "linux,pci-probe-only", 1)); 1487c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "bootargs", kern_cmdline)); 1497c0e8b0cSWill Deacon 1507c0e8b0cSWill Deacon /* Initrd */ 1517c0e8b0cSWill Deacon if (kvm->arch.initrd_size != 0) { 1527c0e8b0cSWill Deacon u32 ird_st_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start); 1537c0e8b0cSWill Deacon u32 ird_end_prop = cpu_to_fdt64(kvm->arch.initrd_guest_start + 1547c0e8b0cSWill Deacon kvm->arch.initrd_size); 1557c0e8b0cSWill Deacon 1567c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "linux,initrd-start", 1577c0e8b0cSWill Deacon &ird_st_prop, sizeof(ird_st_prop))); 1587c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "linux,initrd-end", 1597c0e8b0cSWill Deacon &ird_end_prop, sizeof(ird_end_prop))); 1607c0e8b0cSWill Deacon } 1617c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 1627c0e8b0cSWill Deacon 1637c0e8b0cSWill Deacon /* Memory */ 1647c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "memory")); 1657c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "device_type", "memory")); 1667c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", mem_reg_prop, sizeof(mem_reg_prop))); 1677c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 1687c0e8b0cSWill Deacon 1697c0e8b0cSWill Deacon /* CPU and peripherals (interrupt controller, timers, etc) */ 170beff7ae0SMarc Zyngier generate_cpu_nodes(fdt, kvm); 1712454c7dcSWill Deacon if (generate_cpu_peripheral_fdt_nodes) 1722454c7dcSWill Deacon generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle); 1737c0e8b0cSWill Deacon 1747c0e8b0cSWill Deacon /* Virtio MMIO devices */ 1757c0e8b0cSWill Deacon dev_hdr = device__first_dev(DEVICE_BUS_MMIO); 1767c0e8b0cSWill Deacon while (dev_hdr) { 1772454c7dcSWill Deacon generate_mmio_fdt_nodes = dev_hdr->data; 1782454c7dcSWill Deacon generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop); 1797c0e8b0cSWill Deacon dev_hdr = device__next_dev(dev_hdr); 1807c0e8b0cSWill Deacon } 1817c0e8b0cSWill Deacon 182ed7b31c9SWill Deacon /* IOPORT devices (!) */ 183ed7b31c9SWill Deacon dev_hdr = device__first_dev(DEVICE_BUS_IOPORT); 184ed7b31c9SWill Deacon while (dev_hdr) { 185ed7b31c9SWill Deacon generate_mmio_fdt_nodes = dev_hdr->data; 186ed7b31c9SWill Deacon generate_mmio_fdt_nodes(fdt, dev_hdr, generate_irq_prop); 187ed7b31c9SWill Deacon dev_hdr = device__next_dev(dev_hdr); 188ed7b31c9SWill Deacon } 189ed7b31c9SWill Deacon 19016242d27SWill Deacon /* PCI host controller */ 19116242d27SWill Deacon pci__generate_fdt_nodes(fdt, gic_phandle); 19216242d27SWill Deacon 19361076240SWill Deacon /* PSCI firmware */ 19461076240SWill Deacon _FDT(fdt_begin_node(fdt, "psci")); 195*c2dad402SAnup Patel if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) { 196*c2dad402SAnup Patel const char compatible[] = "arm,psci-0.2\0arm,psci"; 197*c2dad402SAnup Patel _FDT(fdt_property(fdt, "compatible", 198*c2dad402SAnup Patel compatible, sizeof(compatible))); 199*c2dad402SAnup Patel if (kvm->cfg.arch.aarch32_guest) 200*c2dad402SAnup Patel fns = &psci_0_2_aarch32_fns; 201*c2dad402SAnup Patel else 202*c2dad402SAnup Patel fns = &psci_0_2_aarch64_fns; 203*c2dad402SAnup Patel } else { 20461076240SWill Deacon _FDT(fdt_property_string(fdt, "compatible", "arm,psci")); 205*c2dad402SAnup Patel fns = &psci_0_1_fns; 206*c2dad402SAnup Patel } 20761076240SWill Deacon _FDT(fdt_property_string(fdt, "method", "hvc")); 208*c2dad402SAnup Patel _FDT(fdt_property_cell(fdt, "cpu_suspend", fns->cpu_suspend)); 209*c2dad402SAnup Patel _FDT(fdt_property_cell(fdt, "cpu_off", fns->cpu_off)); 210*c2dad402SAnup Patel _FDT(fdt_property_cell(fdt, "cpu_on", fns->cpu_on)); 211*c2dad402SAnup Patel _FDT(fdt_property_cell(fdt, "migrate", fns->migrate)); 21261076240SWill Deacon _FDT(fdt_end_node(fdt)); 21361076240SWill Deacon 2147c0e8b0cSWill Deacon /* Finalise. */ 2157c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 2167c0e8b0cSWill Deacon _FDT(fdt_finish(fdt)); 2177c0e8b0cSWill Deacon 2187c0e8b0cSWill Deacon _FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE)); 2197c0e8b0cSWill Deacon _FDT(fdt_pack(fdt_dest)); 2207c0e8b0cSWill Deacon 221ba27ff46SWill Deacon if (kvm->cfg.arch.dump_dtb_filename) 222ba27ff46SWill Deacon dump_fdt(kvm->cfg.arch.dump_dtb_filename, fdt_dest); 2237c0e8b0cSWill Deacon return 0; 2247c0e8b0cSWill Deacon } 2257c0e8b0cSWill Deacon late_init(setup_fdt); 2267c0e8b0cSWill Deacon 2277c0e8b0cSWill Deacon static int read_image(int fd, void **pos, void *limit) 2287c0e8b0cSWill Deacon { 2297c0e8b0cSWill Deacon int count; 2307c0e8b0cSWill Deacon 2317c0e8b0cSWill Deacon while (((count = xread(fd, *pos, SZ_64K)) > 0) && *pos <= limit) 2327c0e8b0cSWill Deacon *pos += count; 2337c0e8b0cSWill Deacon 2347c0e8b0cSWill Deacon if (pos < 0) 2357c0e8b0cSWill Deacon die_perror("xread"); 2367c0e8b0cSWill Deacon 2377c0e8b0cSWill Deacon return *pos < limit ? 0 : -ENOMEM; 2387c0e8b0cSWill Deacon } 2397c0e8b0cSWill Deacon 2407c0e8b0cSWill Deacon #define FDT_ALIGN SZ_2M 2417c0e8b0cSWill Deacon #define INITRD_ALIGN 4 2427c0e8b0cSWill Deacon int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, 2437c0e8b0cSWill Deacon const char *kernel_cmdline) 2447c0e8b0cSWill Deacon { 2457c0e8b0cSWill Deacon void *pos, *kernel_end, *limit; 2467c0e8b0cSWill Deacon unsigned long guest_addr; 2477c0e8b0cSWill Deacon 2487c0e8b0cSWill Deacon if (lseek(fd_kernel, 0, SEEK_SET) < 0) 2497c0e8b0cSWill Deacon die_perror("lseek"); 2507c0e8b0cSWill Deacon 2517c0e8b0cSWill Deacon /* 25261076240SWill Deacon * Linux requires the initrd and dtb to be mapped inside lowmem, 25361076240SWill Deacon * so we can't just place them at the top of memory. 2547c0e8b0cSWill Deacon */ 2557c0e8b0cSWill Deacon limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 2567c0e8b0cSWill Deacon 2571e0c135aSWill Deacon pos = kvm->ram_start + ARM_KERN_OFFSET(kvm); 2587c0e8b0cSWill Deacon kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 2597c0e8b0cSWill Deacon if (read_image(fd_kernel, &pos, limit) == -ENOMEM) 2607c0e8b0cSWill Deacon die("kernel image too big to contain in guest memory."); 2617c0e8b0cSWill Deacon 2627c0e8b0cSWill Deacon kernel_end = pos; 2637c0e8b0cSWill Deacon pr_info("Loaded kernel to 0x%llx (%llu bytes)", 2647c0e8b0cSWill Deacon kvm->arch.kern_guest_start, 2657c0e8b0cSWill Deacon host_to_guest_flat(kvm, pos) - kvm->arch.kern_guest_start); 2667c0e8b0cSWill Deacon 2677c0e8b0cSWill Deacon /* 2687c0e8b0cSWill Deacon * Now load backwards from the end of memory so the kernel 2697c0e8b0cSWill Deacon * decompressor has plenty of space to work with. First up is 27061076240SWill Deacon * the device tree blob... 2717c0e8b0cSWill Deacon */ 2727c0e8b0cSWill Deacon pos = limit; 2737c0e8b0cSWill Deacon pos -= (FDT_MAX_SIZE + FDT_ALIGN); 2747c0e8b0cSWill Deacon guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 2757c0e8b0cSWill Deacon pos = guest_flat_to_host(kvm, guest_addr); 2767c0e8b0cSWill Deacon if (pos < kernel_end) 2777c0e8b0cSWill Deacon die("fdt overlaps with kernel image."); 2787c0e8b0cSWill Deacon 2797c0e8b0cSWill Deacon kvm->arch.dtb_guest_start = guest_addr; 2807c0e8b0cSWill Deacon pr_info("Placing fdt at 0x%llx - 0x%llx", 2817c0e8b0cSWill Deacon kvm->arch.dtb_guest_start, 2827c0e8b0cSWill Deacon host_to_guest_flat(kvm, limit)); 2837c0e8b0cSWill Deacon limit = pos; 2847c0e8b0cSWill Deacon 2857c0e8b0cSWill Deacon /* ... and finally the initrd, if we have one. */ 2867c0e8b0cSWill Deacon if (fd_initrd != -1) { 2877c0e8b0cSWill Deacon struct stat sb; 2887c0e8b0cSWill Deacon unsigned long initrd_start; 2897c0e8b0cSWill Deacon 2907c0e8b0cSWill Deacon if (lseek(fd_initrd, 0, SEEK_SET) < 0) 2917c0e8b0cSWill Deacon die_perror("lseek"); 2927c0e8b0cSWill Deacon 2937c0e8b0cSWill Deacon if (fstat(fd_initrd, &sb)) 2947c0e8b0cSWill Deacon die_perror("fstat"); 2957c0e8b0cSWill Deacon 2967c0e8b0cSWill Deacon pos -= (sb.st_size + INITRD_ALIGN); 2977c0e8b0cSWill Deacon guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 2987c0e8b0cSWill Deacon pos = guest_flat_to_host(kvm, guest_addr); 2997c0e8b0cSWill Deacon if (pos < kernel_end) 3007c0e8b0cSWill Deacon die("initrd overlaps with kernel image."); 3017c0e8b0cSWill Deacon 3027c0e8b0cSWill Deacon initrd_start = guest_addr; 3037c0e8b0cSWill Deacon if (read_image(fd_initrd, &pos, limit) == -ENOMEM) 3047c0e8b0cSWill Deacon die("initrd too big to contain in guest memory."); 3057c0e8b0cSWill Deacon 3067c0e8b0cSWill Deacon kvm->arch.initrd_guest_start = initrd_start; 3077c0e8b0cSWill Deacon kvm->arch.initrd_size = host_to_guest_flat(kvm, pos) - initrd_start; 3087c0e8b0cSWill Deacon pr_info("Loaded initrd to 0x%llx (%llu bytes)", 3097c0e8b0cSWill Deacon kvm->arch.initrd_guest_start, 3107c0e8b0cSWill Deacon kvm->arch.initrd_size); 3117c0e8b0cSWill Deacon } else { 3127c0e8b0cSWill Deacon kvm->arch.initrd_size = 0; 3137c0e8b0cSWill Deacon } 3147c0e8b0cSWill Deacon 3157c0e8b0cSWill Deacon strncpy(kern_cmdline, kernel_cmdline, COMMAND_LINE_SIZE); 3167c0e8b0cSWill Deacon kern_cmdline[COMMAND_LINE_SIZE - 1] = '\0'; 3177c0e8b0cSWill Deacon 3187c0e8b0cSWill Deacon return true; 3197c0e8b0cSWill Deacon } 320