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 int err; 307c0e8b0cSWill Deacon u64 phys_start, phys_size; 317c0e8b0cSWill Deacon void *host_mem; 327c0e8b0cSWill Deacon 337c0e8b0cSWill Deacon phys_start = ARM_MEMORY_AREA; 347c0e8b0cSWill Deacon phys_size = kvm->ram_size; 357c0e8b0cSWill Deacon host_mem = kvm->ram_start; 367c0e8b0cSWill Deacon 37*8f46c736SJean-Philippe Brucker err = kvm__register_ram(kvm, phys_start, phys_size, host_mem); 387c0e8b0cSWill Deacon if (err) 397c0e8b0cSWill Deacon die("Failed to register %lld bytes of memory at physical " 407c0e8b0cSWill Deacon "address 0x%llx [err %d]", phys_size, phys_start, err); 417c0e8b0cSWill Deacon 427c0e8b0cSWill Deacon kvm->arch.memory_guest_start = phys_start; 437c0e8b0cSWill Deacon } 447c0e8b0cSWill Deacon 457c0e8b0cSWill Deacon void kvm__arch_delete_ram(struct kvm *kvm) 467c0e8b0cSWill Deacon { 479eb3dbcbSWill Deacon munmap(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size); 487c0e8b0cSWill Deacon } 497c0e8b0cSWill Deacon 5012c406a8SJonathan Austin void kvm__arch_read_term(struct kvm *kvm) 517c0e8b0cSWill Deacon { 5297e65b5fSWill Deacon serial8250__update_consoles(kvm); 537c0e8b0cSWill Deacon virtio_console__inject_interrupt(kvm); 547c0e8b0cSWill Deacon } 557c0e8b0cSWill Deacon 567c0e8b0cSWill Deacon void kvm__arch_set_cmdline(char *cmdline, bool video) 577c0e8b0cSWill Deacon { 587c0e8b0cSWill Deacon } 597c0e8b0cSWill Deacon 607c0e8b0cSWill Deacon void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size) 617c0e8b0cSWill Deacon { 629eb3dbcbSWill Deacon /* 63b4d9ac64SMarc Zyngier * Allocate guest memory. We must align our buffer to 64K to 649eb3dbcbSWill Deacon * correlate with the maximum guest page size for virtio-mmio. 65b4d9ac64SMarc Zyngier * If using THP, then our minimal alignment becomes 2M. 66b4d9ac64SMarc Zyngier * 2M trumps 64K, so let's go with that. 679eb3dbcbSWill Deacon */ 681e0c135aSWill Deacon kvm->ram_size = min(ram_size, (u64)ARM_MAX_MEMORY(kvm)); 69b4d9ac64SMarc Zyngier kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M; 709eb3dbcbSWill Deacon kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, 719eb3dbcbSWill Deacon kvm->arch.ram_alloc_size); 729eb3dbcbSWill Deacon 739eb3dbcbSWill Deacon if (kvm->arch.ram_alloc_start == MAP_FAILED) 747c0e8b0cSWill Deacon die("Failed to map %lld bytes for guest memory (%d)", 759eb3dbcbSWill Deacon kvm->arch.ram_alloc_size, errno); 769eb3dbcbSWill Deacon 779eb3dbcbSWill Deacon kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start, 78b4d9ac64SMarc Zyngier SZ_2M); 799eb3dbcbSWill Deacon 809eb3dbcbSWill Deacon madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 810093df80SStefan Agner MADV_MERGEABLE); 820093df80SStefan Agner 830093df80SStefan Agner madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 840093df80SStefan Agner MADV_HUGEPAGE); 857c0e8b0cSWill Deacon 8669b9a17aSMarc Zyngier /* Create the virtual GIC. */ 8743d2781cSAndre Przywara if (gic__create(kvm, kvm->cfg.arch.irqchip)) 8869b9a17aSMarc Zyngier die("Failed to create virtual GIC"); 897c0e8b0cSWill Deacon } 903c8aec9eSAndre Przywara 913c8aec9eSAndre Przywara #define FDT_ALIGN SZ_2M 923c8aec9eSAndre Przywara #define INITRD_ALIGN 4 933c8aec9eSAndre Przywara bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd, 943c8aec9eSAndre Przywara const char *kernel_cmdline) 953c8aec9eSAndre Przywara { 963c8aec9eSAndre Przywara void *pos, *kernel_end, *limit; 973c8aec9eSAndre Przywara unsigned long guest_addr; 983c8aec9eSAndre Przywara ssize_t file_size; 993c8aec9eSAndre Przywara 1003c8aec9eSAndre Przywara /* 1013c8aec9eSAndre Przywara * Linux requires the initrd and dtb to be mapped inside lowmem, 1023c8aec9eSAndre Przywara * so we can't just place them at the top of memory. 1033c8aec9eSAndre Przywara */ 1043c8aec9eSAndre Przywara limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 1053c8aec9eSAndre Przywara 1063c8aec9eSAndre Przywara pos = kvm->ram_start + ARM_KERN_OFFSET(kvm); 1073c8aec9eSAndre Przywara kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 1083c8aec9eSAndre Przywara file_size = read_file(fd_kernel, pos, limit - pos); 1093c8aec9eSAndre Przywara if (file_size < 0) { 1103c8aec9eSAndre Przywara if (errno == ENOMEM) 1113c8aec9eSAndre Przywara die("kernel image too big to contain in guest memory."); 1123c8aec9eSAndre Przywara 1133c8aec9eSAndre Przywara die_perror("kernel read"); 1143c8aec9eSAndre Przywara } 1153c8aec9eSAndre Przywara kernel_end = pos + file_size; 1163c8aec9eSAndre Przywara pr_info("Loaded kernel to 0x%llx (%zd bytes)", 1173c8aec9eSAndre Przywara kvm->arch.kern_guest_start, file_size); 1183c8aec9eSAndre Przywara 1193c8aec9eSAndre Przywara /* 1203c8aec9eSAndre Przywara * Now load backwards from the end of memory so the kernel 1213c8aec9eSAndre Przywara * decompressor has plenty of space to work with. First up is 1223c8aec9eSAndre Przywara * the device tree blob... 1233c8aec9eSAndre Przywara */ 1243c8aec9eSAndre Przywara pos = limit; 1253c8aec9eSAndre Przywara pos -= (FDT_MAX_SIZE + FDT_ALIGN); 1263c8aec9eSAndre Przywara guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 1273c8aec9eSAndre Przywara pos = guest_flat_to_host(kvm, guest_addr); 1283c8aec9eSAndre Przywara if (pos < kernel_end) 1293c8aec9eSAndre Przywara die("fdt overlaps with kernel image."); 1303c8aec9eSAndre Przywara 1313c8aec9eSAndre Przywara kvm->arch.dtb_guest_start = guest_addr; 1323c8aec9eSAndre Przywara pr_info("Placing fdt at 0x%llx - 0x%llx", 1333c8aec9eSAndre Przywara kvm->arch.dtb_guest_start, 1343c8aec9eSAndre Przywara host_to_guest_flat(kvm, limit)); 1353c8aec9eSAndre Przywara limit = pos; 1363c8aec9eSAndre Przywara 1373c8aec9eSAndre Przywara /* ... and finally the initrd, if we have one. */ 1383c8aec9eSAndre Przywara if (fd_initrd != -1) { 1393c8aec9eSAndre Przywara struct stat sb; 1403c8aec9eSAndre Przywara unsigned long initrd_start; 1413c8aec9eSAndre Przywara 1423c8aec9eSAndre Przywara if (fstat(fd_initrd, &sb)) 1433c8aec9eSAndre Przywara die_perror("fstat"); 1443c8aec9eSAndre Przywara 1453c8aec9eSAndre Przywara pos -= (sb.st_size + INITRD_ALIGN); 1463c8aec9eSAndre Przywara guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 1473c8aec9eSAndre Przywara pos = guest_flat_to_host(kvm, guest_addr); 1483c8aec9eSAndre Przywara if (pos < kernel_end) 1493c8aec9eSAndre Przywara die("initrd overlaps with kernel image."); 1503c8aec9eSAndre Przywara 1513c8aec9eSAndre Przywara initrd_start = guest_addr; 1523c8aec9eSAndre Przywara file_size = read_file(fd_initrd, pos, limit - pos); 1533c8aec9eSAndre Przywara if (file_size == -1) { 1543c8aec9eSAndre Przywara if (errno == ENOMEM) 1553c8aec9eSAndre Przywara die("initrd too big to contain in guest memory."); 1563c8aec9eSAndre Przywara 1573c8aec9eSAndre Przywara die_perror("initrd read"); 1583c8aec9eSAndre Przywara } 1593c8aec9eSAndre Przywara 1603c8aec9eSAndre Przywara kvm->arch.initrd_guest_start = initrd_start; 1613c8aec9eSAndre Przywara kvm->arch.initrd_size = file_size; 1623c8aec9eSAndre Przywara pr_info("Loaded initrd to 0x%llx (%llu bytes)", 1633c8aec9eSAndre Przywara kvm->arch.initrd_guest_start, 1643c8aec9eSAndre Przywara kvm->arch.initrd_size); 1653c8aec9eSAndre Przywara } else { 1663c8aec9eSAndre Przywara kvm->arch.initrd_size = 0; 1673c8aec9eSAndre Przywara } 1683c8aec9eSAndre Przywara 1693c8aec9eSAndre Przywara return true; 1703c8aec9eSAndre Przywara } 171