xref: /kvmtool/powerpc/kvm-cpu.c (revision d391177a7181c1ca48b76f4905740079e0226e4e)
1 /*
2  * PPC64 processor support
3  *
4  * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published
8  * by the Free Software Foundation.
9  */
10 
11 #include "kvm/kvm-cpu.h"
12 
13 #include "kvm/symbol.h"
14 #include "kvm/util.h"
15 #include "kvm/kvm.h"
16 
17 #include <sys/ioctl.h>
18 #include <sys/mman.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdio.h>
24 
25 static int debug_fd;
26 
27 void kvm_cpu__set_debug_fd(int fd)
28 {
29 	debug_fd = fd;
30 }
31 
32 int kvm_cpu__get_debug_fd(void)
33 {
34 	return debug_fd;
35 }
36 
37 static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
38 {
39 	struct kvm_cpu *vcpu;
40 
41 	vcpu		= calloc(1, sizeof *vcpu);
42 	if (!vcpu)
43 		return NULL;
44 
45 	vcpu->kvm	= kvm;
46 
47 	return vcpu;
48 }
49 
50 void kvm_cpu__delete(struct kvm_cpu *vcpu)
51 {
52 	free(vcpu);
53 }
54 
55 struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
56 {
57 	struct kvm_cpu *vcpu;
58 	int mmap_size;
59 	struct kvm_enable_cap papr_cap = { .cap = KVM_CAP_PPC_PAPR };
60 
61 	vcpu		= kvm_cpu__new(kvm);
62 	if (!vcpu)
63 		return NULL;
64 
65 	vcpu->cpu_id	= cpu_id;
66 
67 	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
68 	if (vcpu->vcpu_fd < 0)
69 		die_perror("KVM_CREATE_VCPU ioctl");
70 
71 	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
72 	if (mmap_size < 0)
73 		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
74 
75 	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
76 	if (vcpu->kvm_run == MAP_FAILED)
77 		die("unable to mmap vcpu fd");
78 
79 	if (ioctl(vcpu->vcpu_fd, KVM_ENABLE_CAP, &papr_cap) < 0)
80 		die("unable to enable PAPR capability");
81 
82 	/*
83 	 * We start all CPUs, directing non-primary threads into the kernel's
84 	 * secondary start point.  When we come to support SLOF, we will start
85 	 * only one and SLOF will RTAS call us to ask for others to be
86 	 * started.  (FIXME: make more generic & interface with whichever
87 	 * firmware a platform may be using.)
88 	 */
89 	vcpu->is_running = true;
90 
91 	return vcpu;
92 }
93 
94 static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
95 {
96 	/* Don't have to do anything, there's no expected FPU state. */
97 }
98 
99 static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
100 {
101 	/*
102 	 * FIXME: This assumes PPC64 and Linux guest.  It doesn't use the
103 	 * OpenFirmware entry method, but instead the "embedded" entry which
104 	 * passes the FDT address directly.
105 	 */
106 	struct kvm_regs *r = &vcpu->regs;
107 
108 	if (vcpu->cpu_id == 0) {
109 		r->pc = KERNEL_START_ADDR;
110 		r->gpr[3] = vcpu->kvm->fdt_gra;
111 		r->gpr[5] = 0;
112 	} else {
113 		r->pc = KERNEL_SECONDARY_START_ADDR;
114 		r->gpr[3] = vcpu->cpu_id;
115 	}
116 	r->msr = 0x8000000000001000UL; /* 64bit, non-HV, ME */
117 
118 	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
119 		die_perror("KVM_SET_REGS failed");
120 }
121 
122 static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
123 {
124 	/*
125 	 * Some sregs setup to initialise SDR1/PVR/HIOR on PPC64 SPAPR
126 	 * platforms using PR KVM.  (Technically, this is all ignored on
127 	 * SPAPR HV KVM.)  Different setup is required for non-PV non-SPAPR
128 	 * platforms!  (FIXME.)
129 	 */
130 	struct kvm_sregs sregs;
131 	struct kvm_one_reg reg = {};
132 
133 	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
134 		die("KVM_GET_SREGS failed");
135 
136 	sregs.u.s.sdr1 = vcpu->kvm->sdr1;
137 	sregs.pvr = vcpu->kvm->pvr;
138 
139 	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &sregs) < 0)
140 		die("KVM_SET_SREGS failed");
141 
142 	reg.id = KVM_ONE_REG_PPC_HIOR;
143 	reg.u.reg64 = 0;
144 	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
145 		die("KVM_SET_ONE_REG failed");
146 }
147 
148 /**
149  * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
150  */
151 void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
152 {
153 	kvm_cpu__setup_regs(vcpu);
154 	kvm_cpu__setup_sregs(vcpu);
155 	kvm_cpu__setup_fpu(vcpu);
156 }
157 
158 /* kvm_cpu__irq - set KVM's IRQ flag on this vcpu */
159 void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level)
160 {
161 }
162 
163 void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
164 {
165 }
166 
167 bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
168 {
169 	bool ret = true;
170 	struct kvm_run *run = vcpu->kvm_run;
171 	switch(run->exit_reason) {
172 	default:
173 		ret = false;
174 	}
175 	return ret;
176 }
177 
178 #define CONDSTR_BIT(m, b) (((m) & MSR_##b) ? #b" " : "")
179 
180 void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
181 {
182 	struct kvm_regs regs;
183 	struct kvm_sregs sregs;
184 	int r;
185 
186 	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
187 		die("KVM_GET_REGS failed");
188         if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
189 		die("KVM_GET_SREGS failed");
190 
191 	dprintf(debug_fd, "\n Registers:\n");
192 	dprintf(debug_fd, " NIP:   %016llx  MSR:   %016llx "
193 		"( %s%s%s%s%s%s%s%s%s%s%s%s)\n",
194 		regs.pc, regs.msr,
195 		CONDSTR_BIT(regs.msr, SF),
196 		CONDSTR_BIT(regs.msr, HV), /* ! */
197 		CONDSTR_BIT(regs.msr, VEC),
198 		CONDSTR_BIT(regs.msr, VSX),
199 		CONDSTR_BIT(regs.msr, EE),
200 		CONDSTR_BIT(regs.msr, PR),
201 		CONDSTR_BIT(regs.msr, FP),
202 		CONDSTR_BIT(regs.msr, ME),
203 		CONDSTR_BIT(regs.msr, IR),
204 		CONDSTR_BIT(regs.msr, DR),
205 		CONDSTR_BIT(regs.msr, RI),
206 		CONDSTR_BIT(regs.msr, LE));
207 	dprintf(debug_fd, " CTR:   %016llx  LR:    %016llx  CR:   %08llx\n",
208 		regs.ctr, regs.lr, regs.cr);
209 	dprintf(debug_fd, " SRR0:  %016llx  SRR1:  %016llx  XER:  %016llx\n",
210 		regs.srr0, regs.srr1, regs.xer);
211 	dprintf(debug_fd, " SPRG0: %016llx  SPRG1: %016llx\n",
212 		regs.sprg0, regs.sprg1);
213 	dprintf(debug_fd, " SPRG2: %016llx  SPRG3: %016llx\n",
214 		regs.sprg2, regs.sprg3);
215 	dprintf(debug_fd, " SPRG4: %016llx  SPRG5: %016llx\n",
216 		regs.sprg4, regs.sprg5);
217 	dprintf(debug_fd, " SPRG6: %016llx  SPRG7: %016llx\n",
218 		regs.sprg6, regs.sprg7);
219 	dprintf(debug_fd, " GPRs:\n ");
220 	for (r = 0; r < 32; r++) {
221 		dprintf(debug_fd, "%016llx  ", regs.gpr[r]);
222 		if ((r & 3) == 3)
223 			dprintf(debug_fd, "\n ");
224 	}
225 	dprintf(debug_fd, "\n");
226 
227 	/* FIXME: Assumes SLB-based (book3s) guest */
228 	for (r = 0; r < 32; r++) {
229 		dprintf(debug_fd, " SLB%02d  %016llx %016llx\n", r,
230 			sregs.u.s.ppc64.slb[r].slbe,
231 			sregs.u.s.ppc64.slb[r].slbv);
232 	}
233 	dprintf(debug_fd, "----------\n");
234 }
235 
236 void kvm_cpu__show_code(struct kvm_cpu *vcpu)
237 {
238 	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
239 		die("KVM_GET_REGS failed");
240 
241 	/* FIXME: Dump/disassemble some code...! */
242 
243 	dprintf(debug_fd, "\n Stack:\n");
244 	dprintf(debug_fd,   " ------\n");
245 	/* Only works in real mode: */
246 	kvm__dump_mem(vcpu->kvm, vcpu->regs.gpr[1], 32);
247 }
248 
249 void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
250 {
251 	/* Does nothing yet */
252 }
253