xref: /kvmtool/arm/kvm.c (revision 77b108c6a6f1c66fb7f60a80d17596bb80bda8ad)
1 #include "kvm/kvm.h"
2 #include "kvm/term.h"
3 #include "kvm/util.h"
4 #include "kvm/8250-serial.h"
5 #include "kvm/virtio-console.h"
6 #include "kvm/fdt.h"
7 
8 #include "arm-common/gic.h"
9 
10 #include <linux/kernel.h>
11 #include <linux/kvm.h>
12 #include <linux/sizes.h>
13 
14 struct kvm_ext kvm_req_ext[] = {
15 	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
16 	{ DEFINE_KVM_EXT(KVM_CAP_ONE_REG) },
17 	{ DEFINE_KVM_EXT(KVM_CAP_ARM_PSCI) },
18 	{ 0, 0 },
19 };
20 
kvm__arch_cpu_supports_vm(void)21 bool kvm__arch_cpu_supports_vm(void)
22 {
23 	/* The KVM capability check is enough. */
24 	return true;
25 }
26 
kvm__init_ram(struct kvm * kvm)27 void kvm__init_ram(struct kvm *kvm)
28 {
29 	u64 phys_start, phys_size;
30 	void *host_mem;
31 	int err;
32 
33 	/*
34 	 * Allocate guest memory. We must align our buffer to 64K to
35 	 * correlate with the maximum guest page size for virtio-mmio.
36 	 * If using THP, then our minimal alignment becomes 2M.
37 	 * 2M trumps 64K, so let's go with that.
38 	 */
39 	kvm->ram_size = kvm->cfg.ram_size;
40 	kvm->arch.ram_alloc_size = kvm->ram_size;
41 	if (!kvm->cfg.hugetlbfs_path)
42 		kvm->arch.ram_alloc_size += SZ_2M;
43 	kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm,
44 						kvm->cfg.hugetlbfs_path,
45 						kvm->arch.ram_alloc_size);
46 
47 	if (kvm->arch.ram_alloc_start == MAP_FAILED)
48 		die("Failed to map %lld bytes for guest memory (%d)",
49 		    kvm->arch.ram_alloc_size, errno);
50 
51 	kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
52 					SZ_2M);
53 
54 	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
55 		MADV_MERGEABLE);
56 
57 	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
58 		MADV_HUGEPAGE);
59 
60 	phys_start	= kvm->cfg.ram_addr;
61 	phys_size	= kvm->ram_size;
62 	host_mem	= kvm->ram_start;
63 
64 	err = kvm__register_ram(kvm, phys_start, phys_size, host_mem);
65 	if (err)
66 		die("Failed to register %lld bytes of memory at physical "
67 		    "address 0x%llx [err %d]", phys_size, phys_start, err);
68 
69 	kvm->arch.memory_guest_start = phys_start;
70 
71 	pr_debug("RAM created at 0x%llx - 0x%llx",
72 		 phys_start, phys_start + phys_size - 1);
73 }
74 
kvm__arch_delete_ram(struct kvm * kvm)75 void kvm__arch_delete_ram(struct kvm *kvm)
76 {
77 	munmap(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size);
78 }
79 
kvm__arch_read_term(struct kvm * kvm)80 void kvm__arch_read_term(struct kvm *kvm)
81 {
82 	serial8250__update_consoles(kvm);
83 	virtio_console__inject_interrupt(kvm);
84 }
85 
kvm__arch_set_cmdline(char * cmdline,bool video)86 void kvm__arch_set_cmdline(char *cmdline, bool video)
87 {
88 }
89 
kvm__arch_init(struct kvm * kvm)90 void kvm__arch_init(struct kvm *kvm)
91 {
92 	/* Create the virtual GIC. */
93 	if (gic__create(kvm, kvm->cfg.arch.irqchip))
94 		die("Failed to create virtual GIC");
95 
96 	kvm__arch_enable_mte(kvm);
97 }
98 
99 #define FDT_ALIGN	SZ_2M
100 #define INITRD_ALIGN	4
kvm__arch_load_kernel_image(struct kvm * kvm,int fd_kernel,int fd_initrd,const char * kernel_cmdline)101 bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
102 				 const char *kernel_cmdline)
103 {
104 	void *pos, *kernel_end, *limit;
105 	unsigned long guest_addr;
106 	ssize_t file_size;
107 
108 	/*
109 	 * Linux requires the initrd and dtb to be mapped inside lowmem,
110 	 * so we can't just place them at the top of memory.
111 	 */
112 	limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1;
113 
114 	pos = kvm->ram_start + kvm__arch_get_kern_offset(kvm, fd_kernel);
115 	kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos);
116 	file_size = read_file(fd_kernel, pos, limit - pos);
117 	if (file_size < 0) {
118 		if (errno == ENOMEM)
119 			die("kernel image too big to contain in guest memory.");
120 
121 		die_perror("kernel read");
122 	}
123 	kernel_end = pos + file_size;
124 	pr_debug("Loaded kernel to 0x%llx (%zd bytes)",
125 		 kvm->arch.kern_guest_start, file_size);
126 
127 	/*
128 	 * Now load backwards from the end of memory so the kernel
129 	 * decompressor has plenty of space to work with. First up is
130 	 * the device tree blob...
131 	 */
132 	pos = limit;
133 	pos -= (FDT_MAX_SIZE + FDT_ALIGN);
134 	guest_addr = ALIGN(host_to_guest_flat(kvm, pos), FDT_ALIGN);
135 	pos = guest_flat_to_host(kvm, guest_addr);
136 	if (pos < kernel_end)
137 		die("fdt overlaps with kernel image.");
138 
139 	kvm->arch.dtb_guest_start = guest_addr;
140 	pr_debug("Placing fdt at 0x%llx - 0x%llx",
141 		 kvm->arch.dtb_guest_start,
142 		 host_to_guest_flat(kvm, limit));
143 	limit = pos;
144 
145 	/* ... and finally the initrd, if we have one. */
146 	if (fd_initrd != -1) {
147 		struct stat sb;
148 		unsigned long initrd_start;
149 
150 		if (fstat(fd_initrd, &sb))
151 			die_perror("fstat");
152 
153 		pos -= (sb.st_size + INITRD_ALIGN);
154 		guest_addr = ALIGN(host_to_guest_flat(kvm, pos), INITRD_ALIGN);
155 		pos = guest_flat_to_host(kvm, guest_addr);
156 		if (pos < kernel_end)
157 			die("initrd overlaps with kernel image.");
158 
159 		initrd_start = guest_addr;
160 		file_size = read_file(fd_initrd, pos, limit - pos);
161 		if (file_size == -1) {
162 			if (errno == ENOMEM)
163 				die("initrd too big to contain in guest memory.");
164 
165 			die_perror("initrd read");
166 		}
167 
168 		kvm->arch.initrd_guest_start = initrd_start;
169 		kvm->arch.initrd_size = file_size;
170 		pr_debug("Loaded initrd to 0x%llx (%llu bytes)",
171 			 kvm->arch.initrd_guest_start,
172 			 kvm->arch.initrd_size);
173 	} else {
174 		kvm->arch.initrd_size = 0;
175 	}
176 
177 	return true;
178 }
179 
validate_fw_addr(struct kvm * kvm,u64 fw_addr)180 static bool validate_fw_addr(struct kvm *kvm, u64 fw_addr)
181 {
182 	u64 ram_phys;
183 
184 	ram_phys = host_to_guest_flat(kvm, kvm->ram_start);
185 
186 	if (fw_addr < ram_phys || fw_addr >= ram_phys + kvm->ram_size) {
187 		pr_err("Provide --firmware-address an address in RAM: "
188 		       "0x%016llx - 0x%016llx",
189 		       ram_phys, ram_phys + kvm->ram_size);
190 
191 		return false;
192 	}
193 
194 	return true;
195 }
196 
kvm__load_firmware(struct kvm * kvm,const char * firmware_filename)197 bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename)
198 {
199 	u64 fw_addr = kvm->cfg.arch.fw_addr;
200 	void *host_pos;
201 	void *limit;
202 	ssize_t fw_sz;
203 	int fd;
204 
205 	limit = kvm->ram_start + kvm->ram_size;
206 
207 	/* For default firmware address, lets load it at the begining of RAM */
208 	if (fw_addr == 0)
209 		fw_addr = kvm->arch.memory_guest_start;
210 
211 	if (!validate_fw_addr(kvm, fw_addr))
212 		die("Bad firmware destination: 0x%016llx", fw_addr);
213 
214 	fd = open(firmware_filename, O_RDONLY);
215 	if (fd < 0)
216 		return false;
217 
218 	host_pos = guest_flat_to_host(kvm, fw_addr);
219 	if (!host_pos || host_pos < kvm->ram_start)
220 		return false;
221 
222 	fw_sz = read_file(fd, host_pos, limit - host_pos);
223 	if (fw_sz < 0)
224 		die("failed to load firmware");
225 	close(fd);
226 
227 	/* Kernel isn't loaded by kvm, point start address to firmware */
228 	kvm->arch.kern_guest_start = fw_addr;
229 	pr_debug("Loaded firmware to 0x%llx (%zd bytes)",
230 		 kvm->arch.kern_guest_start, fw_sz);
231 
232 	/* Load dtb just after the firmware image*/
233 	host_pos += fw_sz;
234 	if (host_pos + FDT_MAX_SIZE > limit)
235 		die("not enough space to load fdt");
236 
237 	kvm->arch.dtb_guest_start = ALIGN(host_to_guest_flat(kvm, host_pos),
238 					  FDT_ALIGN);
239 	pr_debug("Placing fdt at 0x%llx - 0x%llx",
240 		 kvm->arch.dtb_guest_start,
241 		 kvm->arch.dtb_guest_start + FDT_MAX_SIZE);
242 
243 	return true;
244 }
245 
kvm__arch_setup_firmware(struct kvm * kvm)246 int kvm__arch_setup_firmware(struct kvm *kvm)
247 {
248 	return 0;
249 }
250