12e996783SAnup Patel #include "kvm/kvm.h" 22e996783SAnup Patel #include "kvm/util.h" 3*867159a7SAnup Patel #include "kvm/8250-serial.h" 4*867159a7SAnup Patel #include "kvm/virtio-console.h" 52e996783SAnup Patel #include "kvm/fdt.h" 62e996783SAnup Patel 72e996783SAnup Patel #include <linux/kernel.h> 82e996783SAnup Patel #include <linux/kvm.h> 92e996783SAnup Patel #include <linux/sizes.h> 102e996783SAnup Patel 112e996783SAnup Patel struct kvm_ext kvm_req_ext[] = { 122e996783SAnup Patel { DEFINE_KVM_EXT(KVM_CAP_ONE_REG) }, 132e996783SAnup Patel { 0, 0 }, 142e996783SAnup Patel }; 152e996783SAnup Patel 162e996783SAnup Patel bool kvm__arch_cpu_supports_vm(void) 172e996783SAnup Patel { 182e996783SAnup Patel /* The KVM capability check is enough. */ 192e996783SAnup Patel return true; 202e996783SAnup Patel } 212e996783SAnup Patel 222e996783SAnup Patel void kvm__init_ram(struct kvm *kvm) 232e996783SAnup Patel { 24*867159a7SAnup Patel int err; 25*867159a7SAnup Patel u64 phys_start, phys_size; 26*867159a7SAnup Patel void *host_mem; 27*867159a7SAnup Patel 28*867159a7SAnup Patel phys_start = RISCV_RAM; 29*867159a7SAnup Patel phys_size = kvm->ram_size; 30*867159a7SAnup Patel host_mem = kvm->ram_start; 31*867159a7SAnup Patel 32*867159a7SAnup Patel err = kvm__register_ram(kvm, phys_start, phys_size, host_mem); 33*867159a7SAnup Patel if (err) 34*867159a7SAnup Patel die("Failed to register %lld bytes of memory at physical " 35*867159a7SAnup Patel "address 0x%llx [err %d]", phys_size, phys_start, err); 36*867159a7SAnup Patel 37*867159a7SAnup Patel kvm->arch.memory_guest_start = phys_start; 382e996783SAnup Patel } 392e996783SAnup Patel 402e996783SAnup Patel void kvm__arch_delete_ram(struct kvm *kvm) 412e996783SAnup Patel { 42*867159a7SAnup Patel munmap(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size); 432e996783SAnup Patel } 442e996783SAnup Patel 452e996783SAnup Patel void kvm__arch_read_term(struct kvm *kvm) 462e996783SAnup Patel { 47*867159a7SAnup Patel serial8250__update_consoles(kvm); 48*867159a7SAnup Patel virtio_console__inject_interrupt(kvm); 492e996783SAnup Patel } 502e996783SAnup Patel 512e996783SAnup Patel void kvm__arch_set_cmdline(char *cmdline, bool video) 522e996783SAnup Patel { 532e996783SAnup Patel } 542e996783SAnup Patel 552e996783SAnup Patel void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size) 562e996783SAnup Patel { 57*867159a7SAnup Patel /* 58*867159a7SAnup Patel * Allocate guest memory. We must align our buffer to 64K to 59*867159a7SAnup Patel * correlate with the maximum guest page size for virtio-mmio. 60*867159a7SAnup Patel * If using THP, then our minimal alignment becomes 2M. 61*867159a7SAnup Patel * 2M trumps 64K, so let's go with that. 62*867159a7SAnup Patel */ 63*867159a7SAnup Patel kvm->ram_size = min(ram_size, (u64)RISCV_MAX_MEMORY(kvm)); 64*867159a7SAnup Patel kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M; 65*867159a7SAnup Patel kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, 66*867159a7SAnup Patel kvm->arch.ram_alloc_size); 67*867159a7SAnup Patel 68*867159a7SAnup Patel if (kvm->arch.ram_alloc_start == MAP_FAILED) 69*867159a7SAnup Patel die("Failed to map %lld bytes for guest memory (%d)", 70*867159a7SAnup Patel kvm->arch.ram_alloc_size, errno); 71*867159a7SAnup Patel 72*867159a7SAnup Patel kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start, 73*867159a7SAnup Patel SZ_2M); 74*867159a7SAnup Patel 75*867159a7SAnup Patel madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 76*867159a7SAnup Patel MADV_MERGEABLE); 77*867159a7SAnup Patel 78*867159a7SAnup Patel madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 79*867159a7SAnup Patel MADV_HUGEPAGE); 802e996783SAnup Patel } 812e996783SAnup Patel 82*867159a7SAnup Patel #define FDT_ALIGN SZ_4M 83*867159a7SAnup Patel #define INITRD_ALIGN 8 842e996783SAnup Patel bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd, 852e996783SAnup Patel const char *kernel_cmdline) 862e996783SAnup Patel { 87*867159a7SAnup Patel void *pos, *kernel_end, *limit; 88*867159a7SAnup Patel unsigned long guest_addr, kernel_offset; 89*867159a7SAnup Patel ssize_t file_size; 90*867159a7SAnup Patel 91*867159a7SAnup Patel /* 92*867159a7SAnup Patel * Linux requires the initrd and dtb to be mapped inside lowmem, 93*867159a7SAnup Patel * so we can't just place them at the top of memory. 94*867159a7SAnup Patel */ 95*867159a7SAnup Patel limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 96*867159a7SAnup Patel 97*867159a7SAnup Patel #if __riscv_xlen == 64 98*867159a7SAnup Patel /* Linux expects to be booted at 2M boundary for RV64 */ 99*867159a7SAnup Patel kernel_offset = 0x200000; 100*867159a7SAnup Patel #else 101*867159a7SAnup Patel /* Linux expects to be booted at 4M boundary for RV32 */ 102*867159a7SAnup Patel kernel_offset = 0x400000; 103*867159a7SAnup Patel #endif 104*867159a7SAnup Patel 105*867159a7SAnup Patel pos = kvm->ram_start + kernel_offset; 106*867159a7SAnup Patel kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 107*867159a7SAnup Patel file_size = read_file(fd_kernel, pos, limit - pos); 108*867159a7SAnup Patel if (file_size < 0) { 109*867159a7SAnup Patel if (errno == ENOMEM) 110*867159a7SAnup Patel die("kernel image too big to fit in guest memory."); 111*867159a7SAnup Patel 112*867159a7SAnup Patel die_perror("kernel read"); 113*867159a7SAnup Patel } 114*867159a7SAnup Patel kernel_end = pos + file_size; 115*867159a7SAnup Patel pr_debug("Loaded kernel to 0x%llx (%zd bytes)", 116*867159a7SAnup Patel kvm->arch.kern_guest_start, file_size); 117*867159a7SAnup Patel 118*867159a7SAnup Patel /* Place FDT just after kernel at FDT_ALIGN address */ 119*867159a7SAnup Patel pos = kernel_end + FDT_ALIGN; 120*867159a7SAnup Patel guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 121*867159a7SAnup Patel pos = guest_flat_to_host(kvm, guest_addr); 122*867159a7SAnup Patel if (pos < kernel_end) 123*867159a7SAnup Patel die("fdt overlaps with kernel image."); 124*867159a7SAnup Patel 125*867159a7SAnup Patel kvm->arch.dtb_guest_start = guest_addr; 126*867159a7SAnup Patel pr_debug("Placing fdt at 0x%llx - 0x%llx", 127*867159a7SAnup Patel kvm->arch.dtb_guest_start, 128*867159a7SAnup Patel host_to_guest_flat(kvm, limit)); 129*867159a7SAnup Patel 130*867159a7SAnup Patel /* ... and finally the initrd, if we have one. */ 131*867159a7SAnup Patel if (fd_initrd != -1) { 132*867159a7SAnup Patel struct stat sb; 133*867159a7SAnup Patel unsigned long initrd_start; 134*867159a7SAnup Patel 135*867159a7SAnup Patel if (fstat(fd_initrd, &sb)) 136*867159a7SAnup Patel die_perror("fstat"); 137*867159a7SAnup Patel 138*867159a7SAnup Patel pos = limit - (sb.st_size + INITRD_ALIGN); 139*867159a7SAnup Patel guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 140*867159a7SAnup Patel pos = guest_flat_to_host(kvm, guest_addr); 141*867159a7SAnup Patel if (pos < kernel_end) 142*867159a7SAnup Patel die("initrd overlaps with kernel image."); 143*867159a7SAnup Patel 144*867159a7SAnup Patel initrd_start = guest_addr; 145*867159a7SAnup Patel file_size = read_file(fd_initrd, pos, limit - pos); 146*867159a7SAnup Patel if (file_size == -1) { 147*867159a7SAnup Patel if (errno == ENOMEM) 148*867159a7SAnup Patel die("initrd too big to fit in guest memory."); 149*867159a7SAnup Patel 150*867159a7SAnup Patel die_perror("initrd read"); 151*867159a7SAnup Patel } 152*867159a7SAnup Patel 153*867159a7SAnup Patel kvm->arch.initrd_guest_start = initrd_start; 154*867159a7SAnup Patel kvm->arch.initrd_size = file_size; 155*867159a7SAnup Patel pr_debug("Loaded initrd to 0x%llx (%llu bytes)", 156*867159a7SAnup Patel kvm->arch.initrd_guest_start, 157*867159a7SAnup Patel kvm->arch.initrd_size); 158*867159a7SAnup Patel } else { 159*867159a7SAnup Patel kvm->arch.initrd_size = 0; 160*867159a7SAnup Patel } 161*867159a7SAnup Patel 1622e996783SAnup Patel return true; 1632e996783SAnup Patel } 1642e996783SAnup Patel 1652e996783SAnup Patel bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) 1662e996783SAnup Patel { 1672e996783SAnup Patel /* TODO: Firmware loading to be supported later. */ 1682e996783SAnup Patel return false; 1692e996783SAnup Patel } 1702e996783SAnup Patel 1712e996783SAnup Patel int kvm__arch_setup_firmware(struct kvm *kvm) 1722e996783SAnup Patel { 1732e996783SAnup Patel return 0; 1742e996783SAnup Patel } 175