12e996783SAnup Patel #include "kvm/kvm.h" 22e996783SAnup Patel #include "kvm/util.h" 3867159a7SAnup Patel #include "kvm/8250-serial.h" 4867159a7SAnup 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 16*3f7e48f6SAlexandru Elisei u64 kvm__arch_default_ram_address(void) 17*3f7e48f6SAlexandru Elisei { 18*3f7e48f6SAlexandru Elisei return RISCV_RAM; 19*3f7e48f6SAlexandru Elisei } 20*3f7e48f6SAlexandru Elisei 21abe3f28aSAlexandru Elisei void kvm__arch_validate_cfg(struct kvm *kvm) 22abe3f28aSAlexandru Elisei { 23abe3f28aSAlexandru Elisei } 24abe3f28aSAlexandru Elisei 252e996783SAnup Patel bool kvm__arch_cpu_supports_vm(void) 262e996783SAnup Patel { 272e996783SAnup Patel /* The KVM capability check is enough. */ 282e996783SAnup Patel return true; 292e996783SAnup Patel } 302e996783SAnup Patel 312e996783SAnup Patel void kvm__init_ram(struct kvm *kvm) 322e996783SAnup Patel { 33867159a7SAnup Patel int err; 34867159a7SAnup Patel u64 phys_start, phys_size; 35867159a7SAnup Patel void *host_mem; 36867159a7SAnup Patel 37867159a7SAnup Patel phys_start = RISCV_RAM; 38867159a7SAnup Patel phys_size = kvm->ram_size; 39867159a7SAnup Patel host_mem = kvm->ram_start; 40867159a7SAnup Patel 41867159a7SAnup Patel err = kvm__register_ram(kvm, phys_start, phys_size, host_mem); 42867159a7SAnup Patel if (err) 43867159a7SAnup Patel die("Failed to register %lld bytes of memory at physical " 44867159a7SAnup Patel "address 0x%llx [err %d]", phys_size, phys_start, err); 45867159a7SAnup Patel 46867159a7SAnup Patel kvm->arch.memory_guest_start = phys_start; 472e996783SAnup Patel } 482e996783SAnup Patel 492e996783SAnup Patel void kvm__arch_delete_ram(struct kvm *kvm) 502e996783SAnup Patel { 51867159a7SAnup Patel munmap(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size); 522e996783SAnup Patel } 532e996783SAnup Patel 542e996783SAnup Patel void kvm__arch_read_term(struct kvm *kvm) 552e996783SAnup Patel { 56867159a7SAnup Patel serial8250__update_consoles(kvm); 57867159a7SAnup Patel virtio_console__inject_interrupt(kvm); 582e996783SAnup Patel } 592e996783SAnup Patel 602e996783SAnup Patel void kvm__arch_set_cmdline(char *cmdline, bool video) 612e996783SAnup Patel { 622e996783SAnup Patel } 632e996783SAnup Patel 645e9c654eSJulien Grall void kvm__arch_init(struct kvm *kvm) 652e996783SAnup Patel { 66867159a7SAnup Patel /* 67867159a7SAnup Patel * Allocate guest memory. We must align our buffer to 64K to 68867159a7SAnup Patel * correlate with the maximum guest page size for virtio-mmio. 69867159a7SAnup Patel * If using THP, then our minimal alignment becomes 2M. 70867159a7SAnup Patel * 2M trumps 64K, so let's go with that. 71867159a7SAnup Patel */ 725e9c654eSJulien Grall kvm->ram_size = min(kvm->cfg.ram_size, (u64)RISCV_MAX_MEMORY(kvm)); 73867159a7SAnup Patel kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M; 745e9c654eSJulien Grall kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, 755e9c654eSJulien Grall kvm->cfg.hugetlbfs_path, 76867159a7SAnup Patel kvm->arch.ram_alloc_size); 77867159a7SAnup Patel 78867159a7SAnup Patel if (kvm->arch.ram_alloc_start == MAP_FAILED) 79867159a7SAnup Patel die("Failed to map %lld bytes for guest memory (%d)", 80867159a7SAnup Patel kvm->arch.ram_alloc_size, errno); 81867159a7SAnup Patel 82867159a7SAnup Patel kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start, 83867159a7SAnup Patel SZ_2M); 84867159a7SAnup Patel 85867159a7SAnup Patel madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 86867159a7SAnup Patel MADV_MERGEABLE); 87867159a7SAnup Patel 88867159a7SAnup Patel madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size, 89867159a7SAnup Patel MADV_HUGEPAGE); 902e996783SAnup Patel } 912e996783SAnup Patel 92867159a7SAnup Patel #define FDT_ALIGN SZ_4M 93867159a7SAnup Patel #define INITRD_ALIGN 8 942e996783SAnup Patel bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd, 952e996783SAnup Patel const char *kernel_cmdline) 962e996783SAnup Patel { 97867159a7SAnup Patel void *pos, *kernel_end, *limit; 98867159a7SAnup Patel unsigned long guest_addr, kernel_offset; 99867159a7SAnup Patel ssize_t file_size; 100867159a7SAnup Patel 101867159a7SAnup Patel /* 102867159a7SAnup Patel * Linux requires the initrd and dtb to be mapped inside lowmem, 103867159a7SAnup Patel * so we can't just place them at the top of memory. 104867159a7SAnup Patel */ 105867159a7SAnup Patel limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1; 106867159a7SAnup Patel 107867159a7SAnup Patel #if __riscv_xlen == 64 108867159a7SAnup Patel /* Linux expects to be booted at 2M boundary for RV64 */ 109867159a7SAnup Patel kernel_offset = 0x200000; 110867159a7SAnup Patel #else 111867159a7SAnup Patel /* Linux expects to be booted at 4M boundary for RV32 */ 112867159a7SAnup Patel kernel_offset = 0x400000; 113867159a7SAnup Patel #endif 114867159a7SAnup Patel 115867159a7SAnup Patel pos = kvm->ram_start + kernel_offset; 116867159a7SAnup Patel kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos); 117867159a7SAnup Patel file_size = read_file(fd_kernel, pos, limit - pos); 118867159a7SAnup Patel if (file_size < 0) { 119867159a7SAnup Patel if (errno == ENOMEM) 120867159a7SAnup Patel die("kernel image too big to fit in guest memory."); 121867159a7SAnup Patel 122867159a7SAnup Patel die_perror("kernel read"); 123867159a7SAnup Patel } 124867159a7SAnup Patel kernel_end = pos + file_size; 125867159a7SAnup Patel pr_debug("Loaded kernel to 0x%llx (%zd bytes)", 126867159a7SAnup Patel kvm->arch.kern_guest_start, file_size); 127867159a7SAnup Patel 128867159a7SAnup Patel /* Place FDT just after kernel at FDT_ALIGN address */ 129867159a7SAnup Patel pos = kernel_end + FDT_ALIGN; 130867159a7SAnup Patel guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN); 131867159a7SAnup Patel pos = guest_flat_to_host(kvm, guest_addr); 132867159a7SAnup Patel if (pos < kernel_end) 133867159a7SAnup Patel die("fdt overlaps with kernel image."); 134867159a7SAnup Patel 135867159a7SAnup Patel kvm->arch.dtb_guest_start = guest_addr; 136867159a7SAnup Patel pr_debug("Placing fdt at 0x%llx - 0x%llx", 137867159a7SAnup Patel kvm->arch.dtb_guest_start, 138867159a7SAnup Patel host_to_guest_flat(kvm, limit)); 139867159a7SAnup Patel 140867159a7SAnup Patel /* ... and finally the initrd, if we have one. */ 141867159a7SAnup Patel if (fd_initrd != -1) { 142867159a7SAnup Patel struct stat sb; 143867159a7SAnup Patel unsigned long initrd_start; 144867159a7SAnup Patel 145867159a7SAnup Patel if (fstat(fd_initrd, &sb)) 146867159a7SAnup Patel die_perror("fstat"); 147867159a7SAnup Patel 148867159a7SAnup Patel pos = limit - (sb.st_size + INITRD_ALIGN); 149867159a7SAnup Patel guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN); 150867159a7SAnup Patel pos = guest_flat_to_host(kvm, guest_addr); 151867159a7SAnup Patel if (pos < kernel_end) 152867159a7SAnup Patel die("initrd overlaps with kernel image."); 153867159a7SAnup Patel 154867159a7SAnup Patel initrd_start = guest_addr; 155867159a7SAnup Patel file_size = read_file(fd_initrd, pos, limit - pos); 156867159a7SAnup Patel if (file_size == -1) { 157867159a7SAnup Patel if (errno == ENOMEM) 158867159a7SAnup Patel die("initrd too big to fit in guest memory."); 159867159a7SAnup Patel 160867159a7SAnup Patel die_perror("initrd read"); 161867159a7SAnup Patel } 162867159a7SAnup Patel 163867159a7SAnup Patel kvm->arch.initrd_guest_start = initrd_start; 164867159a7SAnup Patel kvm->arch.initrd_size = file_size; 165867159a7SAnup Patel pr_debug("Loaded initrd to 0x%llx (%llu bytes)", 166867159a7SAnup Patel kvm->arch.initrd_guest_start, 167867159a7SAnup Patel kvm->arch.initrd_size); 168867159a7SAnup Patel } else { 169867159a7SAnup Patel kvm->arch.initrd_size = 0; 170867159a7SAnup Patel } 171867159a7SAnup Patel 1722e996783SAnup Patel return true; 1732e996783SAnup Patel } 1742e996783SAnup Patel 1752e996783SAnup Patel bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename) 1762e996783SAnup Patel { 1772e996783SAnup Patel /* TODO: Firmware loading to be supported later. */ 1782e996783SAnup Patel return false; 1792e996783SAnup Patel } 1802e996783SAnup Patel 1812e996783SAnup Patel int kvm__arch_setup_firmware(struct kvm *kvm) 1822e996783SAnup Patel { 1832e996783SAnup Patel return 0; 1842e996783SAnup Patel } 185