17c0e8b0cSWill Deacon #include "kvm/kvm.h" 27c0e8b0cSWill Deacon #include "kvm/term.h" 37c0e8b0cSWill Deacon #include "kvm/util.h" 497e65b5fSWill Deacon #include "kvm/8250-serial.h" 57c0e8b0cSWill Deacon #include "kvm/virtio-console.h" 63c8aec9eSAndre Przywara #include "kvm/fdt.h" 77c0e8b0cSWill Deacon 87c0e8b0cSWill Deacon #include "arm-common/gic.h" 97c0e8b0cSWill Deacon 107c0e8b0cSWill Deacon #include <linux/kernel.h> 117c0e8b0cSWill Deacon #include <linux/kvm.h> 129eb3dbcbSWill Deacon #include <linux/sizes.h> 137c0e8b0cSWill Deacon 147c0e8b0cSWill Deacon struct kvm_ext kvm_req_ext[] = { 157c0e8b0cSWill Deacon { DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) }, 167c0e8b0cSWill Deacon { DEFINE_KVM_EXT(KVM_CAP_ONE_REG) }, 1761076240SWill Deacon { DEFINE_KVM_EXT(KVM_CAP_ARM_PSCI) }, 187c0e8b0cSWill Deacon { 0, 0 }, 197c0e8b0cSWill Deacon }; 207c0e8b0cSWill Deacon 217c0e8b0cSWill Deacon bool kvm__arch_cpu_supports_vm(void) 227c0e8b0cSWill Deacon { 237c0e8b0cSWill Deacon /* The KVM capability check is enough. */ 247c0e8b0cSWill Deacon return true; 257c0e8b0cSWill Deacon } 267c0e8b0cSWill Deacon 277c0e8b0cSWill Deacon void kvm__init_ram(struct kvm *kvm) 287c0e8b0cSWill Deacon { 297c0e8b0cSWill Deacon u64 phys_start, phys_size; 307c0e8b0cSWill Deacon void *host_mem; 31a37dad0eSJulien Grall int err; 32a37dad0eSJulien Grall 33a37dad0eSJulien Grall /* 34a37dad0eSJulien Grall * Allocate guest memory. We must align our buffer to 64K to 35a37dad0eSJulien Grall * correlate with the maximum guest page size for virtio-mmio. 36a37dad0eSJulien Grall * If using THP, then our minimal alignment becomes 2M. 37a37dad0eSJulien Grall * 2M trumps 64K, so let's go with that. 38a37dad0eSJulien Grall */ 39a37dad0eSJulien Grall kvm->ram_size = kvm->cfg.ram_size; 40a37dad0eSJulien Grall kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M; 41a37dad0eSJulien Grall kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, 42a37dad0eSJulien Grall kvm->cfg.hugetlbfs_path, 43a37dad0eSJulien Grall kvm->arch.ram_alloc_size); 44a37dad0eSJulien Grall 45a37dad0eSJulien Grall if (kvm->arch.ram_alloc_start == MAP_FAILED) 46a37dad0eSJulien Grall die("Failed to map %lld bytes for guest memory (%d)", 47a37dad0eSJulien Grall kvm->arch.ram_alloc_size, errno); 48a37dad0eSJulien Grall 49a37dad0eSJulien Grall kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start, 50a37dad0eSJulien Grall SZ_2M); 51a37dad0eSJulien Grall 52a37dad0eSJulien Grall madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 53a37dad0eSJulien Grall MADV_MERGEABLE); 54a37dad0eSJulien Grall 55a37dad0eSJulien Grall madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 56a37dad0eSJulien Grall MADV_HUGEPAGE); 577c0e8b0cSWill Deacon 58*8b91a182SAlexandru Elisei phys_start = kvm->cfg.ram_addr; 597c0e8b0cSWill Deacon phys_size = kvm->ram_size; 607c0e8b0cSWill Deacon host_mem = kvm->ram_start; 617c0e8b0cSWill Deacon 628f46c736SJean-Philippe Brucker err = kvm__register_ram(kvm, phys_start, phys_size, host_mem); 637c0e8b0cSWill Deacon if (err) 647c0e8b0cSWill Deacon die("Failed to register %lld bytes of memory at physical " 657c0e8b0cSWill Deacon "address 0x%llx [err %d]", phys_size, phys_start, err); 667c0e8b0cSWill Deacon 677c0e8b0cSWill Deacon kvm->arch.memory_guest_start = phys_start; 68*8b91a182SAlexandru Elisei 69*8b91a182SAlexandru Elisei pr_debug("RAM created at 0x%llx - 0x%llx", 70*8b91a182SAlexandru Elisei phys_start, phys_start + phys_size - 1); 717c0e8b0cSWill Deacon } 727c0e8b0cSWill Deacon 737c0e8b0cSWill Deacon void kvm__arch_delete_ram(struct kvm *kvm) 747c0e8b0cSWill Deacon { 759eb3dbcbSWill Deacon munmap(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size); 767c0e8b0cSWill Deacon } 777c0e8b0cSWill Deacon 7812c406a8SJonathan Austin void kvm__arch_read_term(struct kvm *kvm) 797c0e8b0cSWill Deacon { 8097e65b5fSWill Deacon serial8250__update_consoles(kvm); 817c0e8b0cSWill Deacon virtio_console__inject_interrupt(kvm); 827c0e8b0cSWill Deacon } 837c0e8b0cSWill Deacon 847c0e8b0cSWill Deacon void kvm__arch_set_cmdline(char *cmdline, bool video) 857c0e8b0cSWill Deacon { 867c0e8b0cSWill Deacon } 877c0e8b0cSWill Deacon 885e9c654eSJulien Grall void kvm__arch_init(struct kvm *kvm) 897c0e8b0cSWill Deacon { 9069b9a17aSMarc Zyngier /* Create the virtual GIC. */ 9143d2781cSAndre Przywara if (gic__create(kvm, kvm->cfg.arch.irqchip)) 9269b9a17aSMarc Zyngier die("Failed to create virtual GIC"); 935657dd3eSAlexandru Elisei 945657dd3eSAlexandru Elisei kvm__arch_enable_mte(kvm); 957c0e8b0cSWill Deacon } 963c8aec9eSAndre Przywara 973c8aec9eSAndre Przywara #define FDT_ALIGN SZ_2M 983c8aec9eSAndre Przywara #define INITRD_ALIGN 4 993c8aec9eSAndre Przywara bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd, 1003c8aec9eSAndre Przywara const char *kernel_cmdline) 1013c8aec9eSAndre Przywara { 1023c8aec9eSAndre Przywara void *pos, *kernel_end, *limit; 1033c8aec9eSAndre Przywara unsigned long guest_addr; 1043c8aec9eSAndre Przywara ssize_t file_size; 1053c8aec9eSAndre Przywara 1063c8aec9eSAndre Przywara /* 1073c8aec9eSAndre Przywara * Linux requires the initrd and dtb to be mapped inside lowmem, 1083c8aec9eSAndre Przywara * so we can't just place them at the top of memory. 1093c8aec9eSAndre Przywara */ 1103c8aec9eSAndre Przywara limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 1113c8aec9eSAndre Przywara 112fd0a05bdSMarc Zyngier pos = kvm->ram_start + kvm__arch_get_kern_offset(kvm, fd_kernel); 1133c8aec9eSAndre Przywara kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 1143c8aec9eSAndre Przywara file_size = read_file(fd_kernel, pos, limit - pos); 1153c8aec9eSAndre Przywara if (file_size < 0) { 1163c8aec9eSAndre Przywara if (errno == ENOMEM) 1173c8aec9eSAndre Przywara die("kernel image too big to contain in guest memory."); 1183c8aec9eSAndre Przywara 1193c8aec9eSAndre Przywara die_perror("kernel read"); 1203c8aec9eSAndre Przywara } 1213c8aec9eSAndre Przywara kernel_end = pos + file_size; 122e1c7c62aSAndre Przywara pr_debug("Loaded kernel to 0x%llx (%zd bytes)", 1233c8aec9eSAndre Przywara kvm->arch.kern_guest_start, file_size); 1243c8aec9eSAndre Przywara 1253c8aec9eSAndre Przywara /* 1263c8aec9eSAndre Przywara * Now load backwards from the end of memory so the kernel 1273c8aec9eSAndre Przywara * decompressor has plenty of space to work with. First up is 1283c8aec9eSAndre Przywara * the device tree blob... 1293c8aec9eSAndre Przywara */ 1303c8aec9eSAndre Przywara pos = limit; 1313c8aec9eSAndre Przywara pos -= (FDT_MAX_SIZE + FDT_ALIGN); 1323c8aec9eSAndre Przywara guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 1333c8aec9eSAndre Przywara pos = guest_flat_to_host(kvm, guest_addr); 1343c8aec9eSAndre Przywara if (pos < kernel_end) 1353c8aec9eSAndre Przywara die("fdt overlaps with kernel image."); 1363c8aec9eSAndre Przywara 1373c8aec9eSAndre Przywara kvm->arch.dtb_guest_start = guest_addr; 138e1c7c62aSAndre Przywara pr_debug("Placing fdt at 0x%llx - 0x%llx", 1393c8aec9eSAndre Przywara kvm->arch.dtb_guest_start, 1403c8aec9eSAndre Przywara host_to_guest_flat(kvm, limit)); 1413c8aec9eSAndre Przywara limit = pos; 1423c8aec9eSAndre Przywara 1433c8aec9eSAndre Przywara /* ... and finally the initrd, if we have one. */ 1443c8aec9eSAndre Przywara if (fd_initrd != -1) { 1453c8aec9eSAndre Przywara struct stat sb; 1463c8aec9eSAndre Przywara unsigned long initrd_start; 1473c8aec9eSAndre Przywara 1483c8aec9eSAndre Przywara if (fstat(fd_initrd, &sb)) 1493c8aec9eSAndre Przywara die_perror("fstat"); 1503c8aec9eSAndre Przywara 1513c8aec9eSAndre Przywara pos -= (sb.st_size + INITRD_ALIGN); 1523c8aec9eSAndre Przywara guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 1533c8aec9eSAndre Przywara pos = guest_flat_to_host(kvm, guest_addr); 1543c8aec9eSAndre Przywara if (pos < kernel_end) 1553c8aec9eSAndre Przywara die("initrd overlaps with kernel image."); 1563c8aec9eSAndre Przywara 1573c8aec9eSAndre Przywara initrd_start = guest_addr; 1583c8aec9eSAndre Przywara file_size = read_file(fd_initrd, pos, limit - pos); 1593c8aec9eSAndre Przywara if (file_size == -1) { 1603c8aec9eSAndre Przywara if (errno == ENOMEM) 1613c8aec9eSAndre Przywara die("initrd too big to contain in guest memory."); 1623c8aec9eSAndre Przywara 1633c8aec9eSAndre Przywara die_perror("initrd read"); 1643c8aec9eSAndre Przywara } 1653c8aec9eSAndre Przywara 1663c8aec9eSAndre Przywara kvm->arch.initrd_guest_start = initrd_start; 1673c8aec9eSAndre Przywara kvm->arch.initrd_size = file_size; 168e1c7c62aSAndre Przywara pr_debug("Loaded initrd to 0x%llx (%llu bytes)", 1693c8aec9eSAndre Przywara kvm->arch.initrd_guest_start, 1703c8aec9eSAndre Przywara kvm->arch.initrd_size); 1713c8aec9eSAndre Przywara } else { 1723c8aec9eSAndre Przywara kvm->arch.initrd_size = 0; 1733c8aec9eSAndre Przywara } 1743c8aec9eSAndre Przywara 1753c8aec9eSAndre Przywara return true; 1763c8aec9eSAndre Przywara } 177f269c81dSJulien Thierry 1789afefd6cSJulien Thierry static bool validate_fw_addr(struct kvm *kvm, u64 fw_addr) 1799afefd6cSJulien Thierry { 1809afefd6cSJulien Thierry u64 ram_phys; 1819afefd6cSJulien Thierry 1829afefd6cSJulien Thierry ram_phys = host_to_guest_flat(kvm, kvm->ram_start); 1839afefd6cSJulien Thierry 1849afefd6cSJulien Thierry if (fw_addr < ram_phys || fw_addr >= ram_phys + kvm->ram_size) { 1859afefd6cSJulien Thierry pr_err("Provide --firmware-address an address in RAM: " 1869afefd6cSJulien Thierry "0x%016llx - 0x%016llx", 1879afefd6cSJulien Thierry ram_phys, ram_phys + kvm->ram_size); 1889afefd6cSJulien Thierry 1899afefd6cSJulien Thierry return false; 1909afefd6cSJulien Thierry } 1919afefd6cSJulien Thierry 1929afefd6cSJulien Thierry return true; 1939afefd6cSJulien Thierry } 1949afefd6cSJulien Thierry 195f269c81dSJulien Thierry bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) 196f269c81dSJulien Thierry { 1979afefd6cSJulien Thierry u64 fw_addr = kvm->cfg.arch.fw_addr; 1989afefd6cSJulien Thierry void *host_pos; 1999afefd6cSJulien Thierry void *limit; 2009afefd6cSJulien Thierry ssize_t fw_sz; 2019afefd6cSJulien Thierry int fd; 2029afefd6cSJulien Thierry 2039afefd6cSJulien Thierry limit = kvm->ram_start + kvm->ram_size; 2049afefd6cSJulien Thierry 2059afefd6cSJulien Thierry /* For default firmware address, lets load it at the begining of RAM */ 2069afefd6cSJulien Thierry if (fw_addr == 0) 207*8b91a182SAlexandru Elisei fw_addr = kvm->arch.memory_guest_start; 2089afefd6cSJulien Thierry 2099afefd6cSJulien Thierry if (!validate_fw_addr(kvm, fw_addr)) 2109afefd6cSJulien Thierry die("Bad firmware destination: 0x%016llx", fw_addr); 2119afefd6cSJulien Thierry 2129afefd6cSJulien Thierry fd = open(firmware_filename, O_RDONLY); 2139afefd6cSJulien Thierry if (fd < 0) 214f269c81dSJulien Thierry return false; 2159afefd6cSJulien Thierry 2169afefd6cSJulien Thierry host_pos = guest_flat_to_host(kvm, fw_addr); 2179afefd6cSJulien Thierry if (!host_pos || host_pos < kvm->ram_start) 2189afefd6cSJulien Thierry return false; 2199afefd6cSJulien Thierry 2209afefd6cSJulien Thierry fw_sz = read_file(fd, host_pos, limit - host_pos); 2219afefd6cSJulien Thierry if (fw_sz < 0) 2229afefd6cSJulien Thierry die("failed to load firmware"); 2239afefd6cSJulien Thierry close(fd); 2249afefd6cSJulien Thierry 2259afefd6cSJulien Thierry /* Kernel isn't loaded by kvm, point start address to firmware */ 2269afefd6cSJulien Thierry kvm->arch.kern_guest_start = fw_addr; 227c334a68eSAlexandru Elisei pr_debug("Loaded firmware to 0x%llx (%zd bytes)", 228c334a68eSAlexandru Elisei kvm->arch.kern_guest_start, fw_sz); 2299afefd6cSJulien Thierry 2309afefd6cSJulien Thierry /* Load dtb just after the firmware image*/ 2319afefd6cSJulien Thierry host_pos += fw_sz; 2329afefd6cSJulien Thierry if (host_pos + FDT_MAX_SIZE > limit) 2339afefd6cSJulien Thierry die("not enough space to load fdt"); 2349afefd6cSJulien Thierry 2359afefd6cSJulien Thierry kvm->arch.dtb_guest_start = ALIGN(host_to_guest_flat(kvm, host_pos), 2369afefd6cSJulien Thierry FDT_ALIGN); 237c334a68eSAlexandru Elisei pr_debug("Placing fdt at 0x%llx - 0x%llx", 2389afefd6cSJulien Thierry kvm->arch.dtb_guest_start, 2399afefd6cSJulien Thierry kvm->arch.dtb_guest_start + FDT_MAX_SIZE); 2409afefd6cSJulien Thierry 2419afefd6cSJulien Thierry return true; 242f269c81dSJulien Thierry } 243f269c81dSJulien Thierry 244f269c81dSJulien Thierry int kvm__arch_setup_firmware(struct kvm *kvm) 245f269c81dSJulien Thierry { 246f269c81dSJulien Thierry return 0; 247f269c81dSJulien Thierry } 248