xref: /kvmtool/powerpc/kvm.c (revision 63e158a0a0a05551e8e983826bb26a2c0a78ef4b)
1*63e158a0SMatt Evans /*
2*63e158a0SMatt Evans  * PPC64 (SPAPR) platform support
3*63e158a0SMatt Evans  *
4*63e158a0SMatt Evans  * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
5*63e158a0SMatt Evans  *
6*63e158a0SMatt Evans  * This program is free software; you can redistribute it and/or modify it
7*63e158a0SMatt Evans  * under the terms of the GNU General Public License version 2 as published
8*63e158a0SMatt Evans  * by the Free Software Foundation.
9*63e158a0SMatt Evans  */
10*63e158a0SMatt Evans 
11*63e158a0SMatt Evans #include "kvm/kvm.h"
12*63e158a0SMatt Evans #include "kvm/util.h"
13*63e158a0SMatt Evans 
14*63e158a0SMatt Evans #include <linux/kvm.h>
15*63e158a0SMatt Evans 
16*63e158a0SMatt Evans #include <sys/types.h>
17*63e158a0SMatt Evans #include <sys/ioctl.h>
18*63e158a0SMatt Evans #include <sys/mman.h>
19*63e158a0SMatt Evans #include <stdbool.h>
20*63e158a0SMatt Evans #include <assert.h>
21*63e158a0SMatt Evans #include <stdlib.h>
22*63e158a0SMatt Evans #include <string.h>
23*63e158a0SMatt Evans #include <unistd.h>
24*63e158a0SMatt Evans #include <stdio.h>
25*63e158a0SMatt Evans #include <fcntl.h>
26*63e158a0SMatt Evans #include <asm/unistd.h>
27*63e158a0SMatt Evans #include <errno.h>
28*63e158a0SMatt Evans 
29*63e158a0SMatt Evans #include <linux/byteorder.h>
30*63e158a0SMatt Evans #include <libfdt.h>
31*63e158a0SMatt Evans 
32*63e158a0SMatt Evans #define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
33*63e158a0SMatt Evans 
34*63e158a0SMatt Evans static char kern_cmdline[2048];
35*63e158a0SMatt Evans 
36*63e158a0SMatt Evans struct kvm_ext kvm_req_ext[] = {
37*63e158a0SMatt Evans 	{ 0, 0 }
38*63e158a0SMatt Evans };
39*63e158a0SMatt Evans 
40*63e158a0SMatt Evans bool kvm__arch_cpu_supports_vm(void)
41*63e158a0SMatt Evans {
42*63e158a0SMatt Evans 	return true;
43*63e158a0SMatt Evans }
44*63e158a0SMatt Evans 
45*63e158a0SMatt Evans void kvm__init_ram(struct kvm *kvm)
46*63e158a0SMatt Evans {
47*63e158a0SMatt Evans 	u64	phys_start, phys_size;
48*63e158a0SMatt Evans 	void	*host_mem;
49*63e158a0SMatt Evans 
50*63e158a0SMatt Evans 	phys_start = 0;
51*63e158a0SMatt Evans 	phys_size  = kvm->ram_size;
52*63e158a0SMatt Evans 	host_mem   = kvm->ram_start;
53*63e158a0SMatt Evans 
54*63e158a0SMatt Evans 	/*
55*63e158a0SMatt Evans 	 * We put MMIO at PPC_MMIO_START, high up.  Make sure that this doesn't
56*63e158a0SMatt Evans 	 * crash into the end of RAM -- on PPC64 at least, this is so high
57*63e158a0SMatt Evans 	 * (63TB!) that this is unlikely.
58*63e158a0SMatt Evans 	 */
59*63e158a0SMatt Evans 	if (phys_size >= PPC_MMIO_START)
60*63e158a0SMatt Evans 		die("Too much memory (%lld, what a nice problem): "
61*63e158a0SMatt Evans 		    "overlaps MMIO!\n",
62*63e158a0SMatt Evans 		    phys_size);
63*63e158a0SMatt Evans 
64*63e158a0SMatt Evans 	kvm__register_mem(kvm, phys_start, phys_size, host_mem);
65*63e158a0SMatt Evans }
66*63e158a0SMatt Evans 
67*63e158a0SMatt Evans void kvm__arch_set_cmdline(char *cmdline, bool video)
68*63e158a0SMatt Evans {
69*63e158a0SMatt Evans 	/* We don't need anything unusual in here. */
70*63e158a0SMatt Evans }
71*63e158a0SMatt Evans 
72*63e158a0SMatt Evans /* Architecture-specific KVM init */
73*63e158a0SMatt Evans void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
74*63e158a0SMatt Evans {
75*63e158a0SMatt Evans 	int cap_ppc_rma;
76*63e158a0SMatt Evans 
77*63e158a0SMatt Evans 	kvm->ram_size		= ram_size;
78*63e158a0SMatt Evans 
79*63e158a0SMatt Evans 	/*
80*63e158a0SMatt Evans 	 * Currently, we must map from hugetlbfs; if --hugetlbfs not specified,
81*63e158a0SMatt Evans 	 * try a default path:
82*63e158a0SMatt Evans 	 */
83*63e158a0SMatt Evans 	if (!hugetlbfs_path) {
84*63e158a0SMatt Evans 		hugetlbfs_path = HUGETLBFS_PATH;
85*63e158a0SMatt Evans 		pr_info("Using default %s for memory", hugetlbfs_path);
86*63e158a0SMatt Evans 	}
87*63e158a0SMatt Evans 
88*63e158a0SMatt Evans 	kvm->ram_start = mmap_hugetlbfs(hugetlbfs_path, kvm->ram_size);
89*63e158a0SMatt Evans 	if (kvm->ram_start == MAP_FAILED)
90*63e158a0SMatt Evans 		die("Couldn't map %lld bytes for RAM (%d)\n",
91*63e158a0SMatt Evans 		    kvm->ram_size, errno);
92*63e158a0SMatt Evans 
93*63e158a0SMatt Evans 	/* FDT goes at top of memory, RTAS just below */
94*63e158a0SMatt Evans 	kvm->fdt_gra = kvm->ram_size - FDT_MAX_SIZE;
95*63e158a0SMatt Evans 	/* FIXME: Not all PPC systems have RTAS */
96*63e158a0SMatt Evans 	kvm->rtas_gra = kvm->fdt_gra - RTAS_MAX_SIZE;
97*63e158a0SMatt Evans 	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
98*63e158a0SMatt Evans 
99*63e158a0SMatt Evans 	/* FIXME: This is book3s-specific */
100*63e158a0SMatt Evans 	cap_ppc_rma = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_PPC_RMA);
101*63e158a0SMatt Evans 	if (cap_ppc_rma == 2)
102*63e158a0SMatt Evans 		die("Need contiguous RMA allocation on this hardware, "
103*63e158a0SMatt Evans 		    "which is not yet supported.");
104*63e158a0SMatt Evans }
105*63e158a0SMatt Evans 
106*63e158a0SMatt Evans void kvm__irq_line(struct kvm *kvm, int irq, int level)
107*63e158a0SMatt Evans {
108*63e158a0SMatt Evans 	fprintf(stderr, "irq_line(%d, %d)\n", irq, level);
109*63e158a0SMatt Evans }
110*63e158a0SMatt Evans 
111*63e158a0SMatt Evans void kvm__irq_trigger(struct kvm *kvm, int irq)
112*63e158a0SMatt Evans {
113*63e158a0SMatt Evans 	kvm__irq_line(kvm, irq, 1);
114*63e158a0SMatt Evans 	kvm__irq_line(kvm, irq, 0);
115*63e158a0SMatt Evans }
116*63e158a0SMatt Evans 
117*63e158a0SMatt Evans int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
118*63e158a0SMatt Evans {
119*63e158a0SMatt Evans 	void *p;
120*63e158a0SMatt Evans 	void *k_start;
121*63e158a0SMatt Evans 	void *i_start;
122*63e158a0SMatt Evans 	int nr;
123*63e158a0SMatt Evans 
124*63e158a0SMatt Evans 	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
125*63e158a0SMatt Evans 		die_perror("lseek");
126*63e158a0SMatt Evans 
127*63e158a0SMatt Evans 	p = k_start = guest_flat_to_host(kvm, KERNEL_LOAD_ADDR);
128*63e158a0SMatt Evans 
129*63e158a0SMatt Evans 	while ((nr = read(fd_kernel, p, 65536)) > 0)
130*63e158a0SMatt Evans 		p += nr;
131*63e158a0SMatt Evans 
132*63e158a0SMatt Evans 	pr_info("Loaded kernel to 0x%x (%ld bytes)", KERNEL_LOAD_ADDR, p-k_start);
133*63e158a0SMatt Evans 
134*63e158a0SMatt Evans 	if (fd_initrd != -1) {
135*63e158a0SMatt Evans 		if (lseek(fd_initrd, 0, SEEK_SET) < 0)
136*63e158a0SMatt Evans 			die_perror("lseek");
137*63e158a0SMatt Evans 
138*63e158a0SMatt Evans 		if (p-k_start > INITRD_LOAD_ADDR)
139*63e158a0SMatt Evans 			die("Kernel overlaps initrd!");
140*63e158a0SMatt Evans 
141*63e158a0SMatt Evans 		/* Round up kernel size to 8byte alignment, and load initrd right after. */
142*63e158a0SMatt Evans 		i_start = p = guest_flat_to_host(kvm, INITRD_LOAD_ADDR);
143*63e158a0SMatt Evans 
144*63e158a0SMatt Evans 		while (((nr = read(fd_initrd, p, 65536)) > 0) &&
145*63e158a0SMatt Evans 		       p < (kvm->ram_start + kvm->ram_size))
146*63e158a0SMatt Evans 			p += nr;
147*63e158a0SMatt Evans 
148*63e158a0SMatt Evans 		if (p >= (kvm->ram_start + kvm->ram_size))
149*63e158a0SMatt Evans 			die("initrd too big to contain in guest RAM.\n");
150*63e158a0SMatt Evans 
151*63e158a0SMatt Evans 		pr_info("Loaded initrd to 0x%x (%ld bytes)",
152*63e158a0SMatt Evans 			INITRD_LOAD_ADDR, p-i_start);
153*63e158a0SMatt Evans 		kvm->initrd_gra = INITRD_LOAD_ADDR;
154*63e158a0SMatt Evans 		kvm->initrd_size = p-i_start;
155*63e158a0SMatt Evans 	} else {
156*63e158a0SMatt Evans 		kvm->initrd_size = 0;
157*63e158a0SMatt Evans 	}
158*63e158a0SMatt Evans 	strncpy(kern_cmdline, kernel_cmdline, 2048);
159*63e158a0SMatt Evans 	kern_cmdline[2047] = '\0';
160*63e158a0SMatt Evans 
161*63e158a0SMatt Evans 	return true;
162*63e158a0SMatt Evans }
163*63e158a0SMatt Evans 
164*63e158a0SMatt Evans bool load_bzimage(struct kvm *kvm, int fd_kernel,
165*63e158a0SMatt Evans 		  int fd_initrd, const char *kernel_cmdline, u16 vidmode)
166*63e158a0SMatt Evans {
167*63e158a0SMatt Evans 	/* We don't support bzImages. */
168*63e158a0SMatt Evans 	return false;
169*63e158a0SMatt Evans }
170*63e158a0SMatt Evans 
171*63e158a0SMatt Evans static void setup_fdt(struct kvm *kvm)
172*63e158a0SMatt Evans {
173*63e158a0SMatt Evans 
174*63e158a0SMatt Evans }
175*63e158a0SMatt Evans 
176*63e158a0SMatt Evans /**
177*63e158a0SMatt Evans  * kvm__arch_setup_firmware
178*63e158a0SMatt Evans  */
179*63e158a0SMatt Evans void kvm__arch_setup_firmware(struct kvm *kvm)
180*63e158a0SMatt Evans {
181*63e158a0SMatt Evans 	/* Load RTAS */
182*63e158a0SMatt Evans 
183*63e158a0SMatt Evans 	/* Load SLOF */
184*63e158a0SMatt Evans 
185*63e158a0SMatt Evans 	/* Init FDT */
186*63e158a0SMatt Evans 	setup_fdt(kvm);
187*63e158a0SMatt Evans }
188