xref: /kvmtool/riscv/kvm.c (revision 867159a7963bddb5d2a53aeb256af7f3dbbb8ca4)
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