1af7b0868SMatt Evans #include "kvm/kvm.h"
2af7b0868SMatt Evans #include "kvm/boot-protocol.h"
3af7b0868SMatt Evans #include "kvm/cpufeature.h"
4af7b0868SMatt Evans #include "kvm/interrupt.h"
5af7b0868SMatt Evans #include "kvm/mptable.h"
6af7b0868SMatt Evans #include "kvm/util.h"
70b69bdefSMatt Evans #include "kvm/8250-serial.h"
80b69bdefSMatt Evans #include "kvm/virtio-console.h"
9af7b0868SMatt Evans
10af7b0868SMatt Evans #include <asm/bootparam.h>
11af7b0868SMatt Evans #include <linux/kvm.h>
1273f00e73SAndre Przywara #include <linux/kernel.h>
13af7b0868SMatt Evans
14af7b0868SMatt Evans #include <sys/types.h>
15af7b0868SMatt Evans #include <sys/ioctl.h>
16af7b0868SMatt Evans #include <sys/mman.h>
17af7b0868SMatt Evans #include <sys/stat.h>
18af7b0868SMatt Evans #include <stdbool.h>
19af7b0868SMatt Evans #include <stdlib.h>
20af7b0868SMatt Evans #include <string.h>
21af7b0868SMatt Evans #include <unistd.h>
22af7b0868SMatt Evans #include <stdio.h>
23af7b0868SMatt Evans #include <fcntl.h>
24af7b0868SMatt Evans
25af7b0868SMatt Evans struct kvm_ext kvm_req_ext[] = {
26af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
27af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
28af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_PIT2) },
29af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
30af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
31af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
32af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_HLT) },
33af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
34af7b0868SMatt Evans { DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
35af7b0868SMatt Evans { 0, 0 }
36af7b0868SMatt Evans };
37af7b0868SMatt Evans
kvm__arch_default_ram_address(void)383f7e48f6SAlexandru Elisei u64 kvm__arch_default_ram_address(void)
393f7e48f6SAlexandru Elisei {
403f7e48f6SAlexandru Elisei return 0;
413f7e48f6SAlexandru Elisei }
423f7e48f6SAlexandru Elisei
kvm__arch_validate_cfg(struct kvm * kvm)43abe3f28aSAlexandru Elisei void kvm__arch_validate_cfg(struct kvm *kvm)
44abe3f28aSAlexandru Elisei {
45abe3f28aSAlexandru Elisei }
46abe3f28aSAlexandru Elisei
kvm__arch_cpu_supports_vm(void)47af7b0868SMatt Evans bool kvm__arch_cpu_supports_vm(void)
48af7b0868SMatt Evans {
49af7b0868SMatt Evans struct cpuid_regs regs;
50af7b0868SMatt Evans u32 eax_base;
51af7b0868SMatt Evans int feature;
52af7b0868SMatt Evans
53af7b0868SMatt Evans regs = (struct cpuid_regs) {
54af7b0868SMatt Evans .eax = 0x00,
55af7b0868SMatt Evans };
56af7b0868SMatt Evans host_cpuid(®s);
57af7b0868SMatt Evans
58af7b0868SMatt Evans switch (regs.ebx) {
59af7b0868SMatt Evans case CPUID_VENDOR_INTEL_1:
60af7b0868SMatt Evans eax_base = 0x00;
61af7b0868SMatt Evans feature = KVM__X86_FEATURE_VMX;
62af7b0868SMatt Evans break;
63af7b0868SMatt Evans
64af7b0868SMatt Evans case CPUID_VENDOR_AMD_1:
65af7b0868SMatt Evans eax_base = 0x80000000;
66af7b0868SMatt Evans feature = KVM__X86_FEATURE_SVM;
67af7b0868SMatt Evans break;
68af7b0868SMatt Evans
69af7b0868SMatt Evans default:
70af7b0868SMatt Evans return false;
71af7b0868SMatt Evans }
72af7b0868SMatt Evans
73af7b0868SMatt Evans regs = (struct cpuid_regs) {
74af7b0868SMatt Evans .eax = eax_base,
75af7b0868SMatt Evans };
76af7b0868SMatt Evans host_cpuid(®s);
77af7b0868SMatt Evans
78af7b0868SMatt Evans if (regs.eax < eax_base + 0x01)
79af7b0868SMatt Evans return false;
80af7b0868SMatt Evans
81af7b0868SMatt Evans regs = (struct cpuid_regs) {
82af7b0868SMatt Evans .eax = eax_base + 0x01
83af7b0868SMatt Evans };
84af7b0868SMatt Evans host_cpuid(®s);
85af7b0868SMatt Evans
86af7b0868SMatt Evans return regs.ecx & (1 << feature);
87af7b0868SMatt Evans }
88af7b0868SMatt Evans
89af7b0868SMatt Evans /*
90af7b0868SMatt Evans * Allocating RAM size bigger than 4GB requires us to leave a gap
91af7b0868SMatt Evans * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
92af7b0868SMatt Evans * devices (see documentation of e820_setup_gap() for details).
93af7b0868SMatt Evans *
94af7b0868SMatt Evans * If we're required to initialize RAM bigger than 4GB, we will create
95af7b0868SMatt Evans * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
96af7b0868SMatt Evans */
97af7b0868SMatt Evans
kvm__init_ram(struct kvm * kvm)98af7b0868SMatt Evans void kvm__init_ram(struct kvm *kvm)
99af7b0868SMatt Evans {
100af7b0868SMatt Evans u64 phys_start, phys_size;
101af7b0868SMatt Evans void *host_mem;
102af7b0868SMatt Evans
103af7b0868SMatt Evans if (kvm->ram_size < KVM_32BIT_GAP_START) {
104af7b0868SMatt Evans /* Use a single block of RAM for 32bit RAM */
105af7b0868SMatt Evans
106af7b0868SMatt Evans phys_start = 0;
107af7b0868SMatt Evans phys_size = kvm->ram_size;
108af7b0868SMatt Evans host_mem = kvm->ram_start;
109af7b0868SMatt Evans
1108f46c736SJean-Philippe Brucker kvm__register_ram(kvm, phys_start, phys_size, host_mem);
111af7b0868SMatt Evans } else {
112af7b0868SMatt Evans /* First RAM range from zero to the PCI gap: */
113af7b0868SMatt Evans
114af7b0868SMatt Evans phys_start = 0;
115af7b0868SMatt Evans phys_size = KVM_32BIT_GAP_START;
116af7b0868SMatt Evans host_mem = kvm->ram_start;
117af7b0868SMatt Evans
1188f46c736SJean-Philippe Brucker kvm__register_ram(kvm, phys_start, phys_size, host_mem);
119af7b0868SMatt Evans
120af7b0868SMatt Evans /* Second RAM range from 4GB to the end of RAM: */
121af7b0868SMatt Evans
122f7abc4cdSHongyong Zang phys_start = KVM_32BIT_MAX_MEM_SIZE;
123f7abc4cdSHongyong Zang phys_size = kvm->ram_size - phys_start;
124af7b0868SMatt Evans host_mem = kvm->ram_start + phys_start;
125af7b0868SMatt Evans
1268f46c736SJean-Philippe Brucker kvm__register_ram(kvm, phys_start, phys_size, host_mem);
127af7b0868SMatt Evans }
128af7b0868SMatt Evans }
129af7b0868SMatt Evans
1308e704a7aSMatt Evans /* Arch-specific commandline setup */
kvm__arch_set_cmdline(char * cmdline,bool video)1318e704a7aSMatt Evans void kvm__arch_set_cmdline(char *cmdline, bool video)
1328e704a7aSMatt Evans {
1338e704a7aSMatt Evans strcpy(cmdline, "noapic noacpi pci=conf1 reboot=k panic=1 i8042.direct=1 "
1348e704a7aSMatt Evans "i8042.dumbkbd=1 i8042.nopnp=1");
1353a60be06SSasha Levin if (video)
1365857730cSWill Deacon strcat(cmdline, " video=vesafb");
1373a60be06SSasha Levin else
1385857730cSWill Deacon strcat(cmdline, " earlyprintk=serial i8042.noaux=1");
1398e704a7aSMatt Evans }
1408e704a7aSMatt Evans
141af7b0868SMatt Evans /* Architecture-specific KVM init */
kvm__arch_init(struct kvm * kvm)1425e9c654eSJulien Grall void kvm__arch_init(struct kvm *kvm)
143af7b0868SMatt Evans {
1445e9c654eSJulien Grall const char *hugetlbfs_path = kvm->cfg.hugetlbfs_path;
145af7b0868SMatt Evans struct kvm_pit_config pit_config = { .flags = 0, };
1465e9c654eSJulien Grall u64 ram_size = kvm->cfg.ram_size;
147af7b0868SMatt Evans int ret;
148af7b0868SMatt Evans
149af7b0868SMatt Evans ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
150af7b0868SMatt Evans if (ret < 0)
151af7b0868SMatt Evans die_perror("KVM_SET_TSS_ADDR ioctl");
152af7b0868SMatt Evans
153f7abc4cdSHongyong Zang if (ram_size < KVM_32BIT_GAP_START) {
154af7b0868SMatt Evans kvm->ram_size = ram_size;
1553ebd8e0bSMichael Ellerman kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size);
156af7b0868SMatt Evans } else {
1573ebd8e0bSMichael Ellerman kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size + KVM_32BIT_GAP_SIZE);
158f7abc4cdSHongyong Zang kvm->ram_size = ram_size + KVM_32BIT_GAP_SIZE;
1593a60be06SSasha Levin if (kvm->ram_start != MAP_FAILED)
160af7b0868SMatt Evans /*
161af7b0868SMatt Evans * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
162af7b0868SMatt Evans * if we accidently write to it, we will know.
163af7b0868SMatt Evans */
164af7b0868SMatt Evans mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
165af7b0868SMatt Evans }
166af7b0868SMatt Evans if (kvm->ram_start == MAP_FAILED)
167af7b0868SMatt Evans die("out of memory");
168af7b0868SMatt Evans
169af7b0868SMatt Evans madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
170af7b0868SMatt Evans
171af7b0868SMatt Evans ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
172af7b0868SMatt Evans if (ret < 0)
173af7b0868SMatt Evans die_perror("KVM_CREATE_IRQCHIP ioctl");
174*e73a6b29STengfei Yu
175*e73a6b29STengfei Yu ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
176*e73a6b29STengfei Yu if (ret < 0)
177*e73a6b29STengfei Yu die_perror("KVM_CREATE_PIT2 ioctl");
178af7b0868SMatt Evans }
179af7b0868SMatt Evans
kvm__arch_delete_ram(struct kvm * kvm)180e56e2de7SLai Jiangshan void kvm__arch_delete_ram(struct kvm *kvm)
181e56e2de7SLai Jiangshan {
182e56e2de7SLai Jiangshan munmap(kvm->ram_start, kvm->ram_size);
183e56e2de7SLai Jiangshan }
184e56e2de7SLai Jiangshan
kvm__irq_line(struct kvm * kvm,int irq,int level)185af7b0868SMatt Evans void kvm__irq_line(struct kvm *kvm, int irq, int level)
186af7b0868SMatt Evans {
187af7b0868SMatt Evans struct kvm_irq_level irq_level;
188af7b0868SMatt Evans
189af7b0868SMatt Evans irq_level = (struct kvm_irq_level) {
190af7b0868SMatt Evans {
191af7b0868SMatt Evans .irq = irq,
192af7b0868SMatt Evans },
193af7b0868SMatt Evans .level = level,
194af7b0868SMatt Evans };
195af7b0868SMatt Evans
196af7b0868SMatt Evans if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
197af7b0868SMatt Evans die_perror("KVM_IRQ_LINE failed");
198af7b0868SMatt Evans }
199af7b0868SMatt Evans
kvm__irq_trigger(struct kvm * kvm,int irq)200af7b0868SMatt Evans void kvm__irq_trigger(struct kvm *kvm, int irq)
201af7b0868SMatt Evans {
202af7b0868SMatt Evans kvm__irq_line(kvm, irq, 1);
203af7b0868SMatt Evans kvm__irq_line(kvm, irq, 0);
204af7b0868SMatt Evans }
205af7b0868SMatt Evans
206af7b0868SMatt Evans #define BOOT_LOADER_SELECTOR 0x1000
207af7b0868SMatt Evans #define BOOT_LOADER_IP 0x0000
208af7b0868SMatt Evans #define BOOT_LOADER_SP 0x8000
209af7b0868SMatt Evans #define BOOT_CMDLINE_OFFSET 0x20000
210af7b0868SMatt Evans
211af7b0868SMatt Evans #define BOOT_PROTOCOL_REQUIRED 0x206
212af7b0868SMatt Evans #define LOAD_HIGH 0x01
213af7b0868SMatt Evans
guest_real_to_host(struct kvm * kvm,u16 selector,u16 offset)214f412251fSWill Deacon static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
215f412251fSWill Deacon {
2161cbb2c50SAndre Przywara unsigned long flat = ((u32)selector << 4) + offset;
217f412251fSWill Deacon
218f412251fSWill Deacon return guest_flat_to_host(kvm, flat);
219f412251fSWill Deacon }
220f412251fSWill Deacon
load_flat_binary(struct kvm * kvm,int fd_kernel)221004f7684SAndre Przywara static bool load_flat_binary(struct kvm *kvm, int fd_kernel)
222af7b0868SMatt Evans {
223af7b0868SMatt Evans void *p;
224af7b0868SMatt Evans
225604dbd63SMatt Evans if (lseek(fd_kernel, 0, SEEK_SET) < 0)
226af7b0868SMatt Evans die_perror("lseek");
227af7b0868SMatt Evans
228af7b0868SMatt Evans p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
229af7b0868SMatt Evans
23073f00e73SAndre Przywara if (read_file(fd_kernel, p, kvm->cfg.ram_size) < 0)
23173f00e73SAndre Przywara die_perror("read");
232af7b0868SMatt Evans
23342ac24f9SSasha Levin kvm->arch.boot_selector = BOOT_LOADER_SELECTOR;
23442ac24f9SSasha Levin kvm->arch.boot_ip = BOOT_LOADER_IP;
23542ac24f9SSasha Levin kvm->arch.boot_sp = BOOT_LOADER_SP;
236af7b0868SMatt Evans
237af7b0868SMatt Evans return true;
238af7b0868SMatt Evans }
239af7b0868SMatt Evans
240af7b0868SMatt Evans static const char *BZIMAGE_MAGIC = "HdrS";
241af7b0868SMatt Evans
load_bzimage(struct kvm * kvm,int fd_kernel,int fd_initrd,const char * kernel_cmdline)242004f7684SAndre Przywara static bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd,
243ff7ba6faSWill Deacon const char *kernel_cmdline)
244af7b0868SMatt Evans {
245af7b0868SMatt Evans struct boot_params *kern_boot;
246af7b0868SMatt Evans struct boot_params boot;
247af7b0868SMatt Evans size_t cmdline_size;
24873f00e73SAndre Przywara ssize_t file_size;
249af7b0868SMatt Evans void *p;
250ff7ba6faSWill Deacon u16 vidmode;
251af7b0868SMatt Evans
252af7b0868SMatt Evans /*
253af7b0868SMatt Evans * See Documentation/x86/boot.txt for details no bzImage on-disk and
254af7b0868SMatt Evans * memory layout.
255af7b0868SMatt Evans */
256af7b0868SMatt Evans
25773f00e73SAndre Przywara if (read_in_full(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
258af7b0868SMatt Evans return false;
259af7b0868SMatt Evans
260af7b0868SMatt Evans if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
261af7b0868SMatt Evans return false;
262af7b0868SMatt Evans
263af7b0868SMatt Evans if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
264af7b0868SMatt Evans die("Too old kernel");
265af7b0868SMatt Evans
266af7b0868SMatt Evans if (lseek(fd_kernel, 0, SEEK_SET) < 0)
267af7b0868SMatt Evans die_perror("lseek");
268af7b0868SMatt Evans
269af7b0868SMatt Evans if (!boot.hdr.setup_sects)
270af7b0868SMatt Evans boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
27173f00e73SAndre Przywara file_size = (boot.hdr.setup_sects + 1) << 9;
272af7b0868SMatt Evans p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
27373f00e73SAndre Przywara if (read_in_full(fd_kernel, p, file_size) != file_size)
27473f00e73SAndre Przywara die_perror("kernel setup read");
275af7b0868SMatt Evans
27673f00e73SAndre Przywara /* read actual kernel image (vmlinux.bin) to BZ_KERNEL_START */
277af7b0868SMatt Evans p = guest_flat_to_host(kvm, BZ_KERNEL_START);
27873f00e73SAndre Przywara file_size = read_file(fd_kernel, p,
27973f00e73SAndre Przywara kvm->cfg.ram_size - BZ_KERNEL_START);
28073f00e73SAndre Przywara if (file_size < 0)
28173f00e73SAndre Przywara die_perror("kernel read");
282af7b0868SMatt Evans
283af7b0868SMatt Evans p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
284af7b0868SMatt Evans if (kernel_cmdline) {
285af7b0868SMatt Evans cmdline_size = strlen(kernel_cmdline) + 1;
286af7b0868SMatt Evans if (cmdline_size > boot.hdr.cmdline_size)
287af7b0868SMatt Evans cmdline_size = boot.hdr.cmdline_size;
288af7b0868SMatt Evans
289af7b0868SMatt Evans memset(p, 0, boot.hdr.cmdline_size);
290af7b0868SMatt Evans memcpy(p, kernel_cmdline, cmdline_size - 1);
291af7b0868SMatt Evans }
292af7b0868SMatt Evans
293ff7ba6faSWill Deacon /* vidmode should be either specified or set by default */
2947bcceb95SPekka Enberg if (kvm->cfg.vnc || kvm->cfg.sdl || kvm->cfg.gtk) {
2956ad7171aSAsias He if (!kvm->cfg.arch.vidmode)
296ff7ba6faSWill Deacon vidmode = 0x312;
2976ad7171aSAsias He else
2986ad7171aSAsias He vidmode = kvm->cfg.arch.vidmode;
299ff7ba6faSWill Deacon } else {
300ff7ba6faSWill Deacon vidmode = 0;
301ff7ba6faSWill Deacon }
302ff7ba6faSWill Deacon
303af7b0868SMatt Evans kern_boot = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
304af7b0868SMatt Evans
305af7b0868SMatt Evans kern_boot->hdr.cmd_line_ptr = BOOT_CMDLINE_OFFSET;
306af7b0868SMatt Evans kern_boot->hdr.type_of_loader = 0xff;
307af7b0868SMatt Evans kern_boot->hdr.heap_end_ptr = 0xfe00;
308af7b0868SMatt Evans kern_boot->hdr.loadflags |= CAN_USE_HEAP;
309af7b0868SMatt Evans kern_boot->hdr.vid_mode = vidmode;
310af7b0868SMatt Evans
311af7b0868SMatt Evans /*
312af7b0868SMatt Evans * Read initrd image into guest memory
313af7b0868SMatt Evans */
314af7b0868SMatt Evans if (fd_initrd >= 0) {
315af7b0868SMatt Evans struct stat initrd_stat;
316af7b0868SMatt Evans unsigned long addr;
317af7b0868SMatt Evans
318af7b0868SMatt Evans if (fstat(fd_initrd, &initrd_stat))
319af7b0868SMatt Evans die_perror("fstat");
320af7b0868SMatt Evans
321af7b0868SMatt Evans addr = boot.hdr.initrd_addr_max & ~0xfffff;
322af7b0868SMatt Evans for (;;) {
323af7b0868SMatt Evans if (addr < BZ_KERNEL_START)
324af7b0868SMatt Evans die("Not enough memory for initrd");
325af7b0868SMatt Evans else if (addr < (kvm->ram_size - initrd_stat.st_size))
326af7b0868SMatt Evans break;
327af7b0868SMatt Evans addr -= 0x100000;
328af7b0868SMatt Evans }
329af7b0868SMatt Evans
330af7b0868SMatt Evans p = guest_flat_to_host(kvm, addr);
33173f00e73SAndre Przywara if (read_in_full(fd_initrd, p, initrd_stat.st_size) < 0)
332af7b0868SMatt Evans die("Failed to read initrd");
333af7b0868SMatt Evans
334af7b0868SMatt Evans kern_boot->hdr.ramdisk_image = addr;
335af7b0868SMatt Evans kern_boot->hdr.ramdisk_size = initrd_stat.st_size;
336af7b0868SMatt Evans }
337af7b0868SMatt Evans
33842ac24f9SSasha Levin kvm->arch.boot_selector = BOOT_LOADER_SELECTOR;
339af7b0868SMatt Evans /*
340af7b0868SMatt Evans * The real-mode setup code starts at offset 0x200 of a bzImage. See
341af7b0868SMatt Evans * Documentation/x86/boot.txt for details.
342af7b0868SMatt Evans */
34342ac24f9SSasha Levin kvm->arch.boot_ip = BOOT_LOADER_IP + 0x200;
34442ac24f9SSasha Levin kvm->arch.boot_sp = BOOT_LOADER_SP;
345af7b0868SMatt Evans
346af7b0868SMatt Evans return true;
347af7b0868SMatt Evans }
348af7b0868SMatt Evans
kvm__arch_load_kernel_image(struct kvm * kvm,int fd_kernel,int fd_initrd,const char * kernel_cmdline)349004f7684SAndre Przywara bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
350004f7684SAndre Przywara const char *kernel_cmdline)
351004f7684SAndre Przywara {
352004f7684SAndre Przywara if (load_bzimage(kvm, fd_kernel, fd_initrd, kernel_cmdline))
353004f7684SAndre Przywara return true;
354004f7684SAndre Przywara pr_warning("Kernel image is not a bzImage.");
355004f7684SAndre Przywara pr_warning("Trying to load it as a flat binary (no cmdline support)");
356004f7684SAndre Przywara
357004f7684SAndre Przywara if (fd_initrd != -1)
358004f7684SAndre Przywara pr_warning("Loading initrd with flat binary not supported.");
359004f7684SAndre Przywara
360004f7684SAndre Przywara return load_flat_binary(kvm, fd_kernel);
361004f7684SAndre Przywara }
362004f7684SAndre Przywara
363af7b0868SMatt Evans /**
364af7b0868SMatt Evans * kvm__arch_setup_firmware - inject BIOS into guest system memory
365af7b0868SMatt Evans * @kvm - guest system descriptor
366af7b0868SMatt Evans *
367af7b0868SMatt Evans * This function is a main routine where we poke guest memory
368af7b0868SMatt Evans * and install BIOS there.
369af7b0868SMatt Evans */
kvm__arch_setup_firmware(struct kvm * kvm)370f7f9d02bSCyrill Gorcunov int kvm__arch_setup_firmware(struct kvm *kvm)
371af7b0868SMatt Evans {
372af7b0868SMatt Evans /* standart minimal configuration */
373af7b0868SMatt Evans setup_bios(kvm);
374af7b0868SMatt Evans
375af7b0868SMatt Evans /* FIXME: SMP, ACPI and friends here */
376af7b0868SMatt Evans
3773d34111eSSasha Levin return 0;
3781add9f73SSasha Levin }
3791add9f73SSasha Levin
kvm__arch_free_firmware(struct kvm * kvm)3801add9f73SSasha Levin int kvm__arch_free_firmware(struct kvm *kvm)
3811add9f73SSasha Levin {
3823d34111eSSasha Levin return 0;
383af7b0868SMatt Evans }
3840b69bdefSMatt Evans
kvm__arch_read_term(struct kvm * kvm)38512c406a8SJonathan Austin void kvm__arch_read_term(struct kvm *kvm)
3860b69bdefSMatt Evans {
387f6b8ccc1SThomas Gleixner serial8250__update_consoles(kvm);
3880b69bdefSMatt Evans virtio_console__inject_interrupt(kvm);
3890b69bdefSMatt Evans }
390