|
1 /* |
|
2 * PowerPC implementation of KVM hooks |
|
3 * |
|
4 * Copyright IBM Corp. 2007 |
|
5 * |
|
6 * Authors: |
|
7 * Jerone Young <jyoung5@us.ibm.com> |
|
8 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> |
|
9 * Hollis Blanchard <hollisb@us.ibm.com> |
|
10 * |
|
11 * This work is licensed under the terms of the GNU GPL, version 2 or later. |
|
12 * See the COPYING file in the top-level directory. |
|
13 * |
|
14 */ |
|
15 |
|
16 #include <sys/types.h> |
|
17 #include <sys/ioctl.h> |
|
18 #include <sys/mman.h> |
|
19 |
|
20 #include <linux/kvm.h> |
|
21 |
|
22 #include "qemu-common.h" |
|
23 #include "qemu-timer.h" |
|
24 #include "sysemu.h" |
|
25 #include "kvm.h" |
|
26 #include "kvm_ppc.h" |
|
27 #include "cpu.h" |
|
28 #include "device_tree.h" |
|
29 |
|
30 //#define DEBUG_KVM |
|
31 |
|
32 #ifdef DEBUG_KVM |
|
33 #define dprintf(fmt, ...) \ |
|
34 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) |
|
35 #else |
|
36 #define dprintf(fmt, ...) \ |
|
37 do { } while (0) |
|
38 #endif |
|
39 |
|
40 int kvm_arch_init(KVMState *s, int smp_cpus) |
|
41 { |
|
42 return 0; |
|
43 } |
|
44 |
|
45 int kvm_arch_init_vcpu(CPUState *cenv) |
|
46 { |
|
47 return 0; |
|
48 } |
|
49 |
|
50 int kvm_arch_put_registers(CPUState *env) |
|
51 { |
|
52 struct kvm_regs regs; |
|
53 int ret; |
|
54 int i; |
|
55 |
|
56 ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); |
|
57 if (ret < 0) |
|
58 return ret; |
|
59 |
|
60 regs.ctr = env->ctr; |
|
61 regs.lr = env->lr; |
|
62 regs.xer = env->xer; |
|
63 regs.msr = env->msr; |
|
64 regs.pc = env->nip; |
|
65 |
|
66 regs.srr0 = env->spr[SPR_SRR0]; |
|
67 regs.srr1 = env->spr[SPR_SRR1]; |
|
68 |
|
69 regs.sprg0 = env->spr[SPR_SPRG0]; |
|
70 regs.sprg1 = env->spr[SPR_SPRG1]; |
|
71 regs.sprg2 = env->spr[SPR_SPRG2]; |
|
72 regs.sprg3 = env->spr[SPR_SPRG3]; |
|
73 regs.sprg4 = env->spr[SPR_SPRG4]; |
|
74 regs.sprg5 = env->spr[SPR_SPRG5]; |
|
75 regs.sprg6 = env->spr[SPR_SPRG6]; |
|
76 regs.sprg7 = env->spr[SPR_SPRG7]; |
|
77 |
|
78 for (i = 0;i < 32; i++) |
|
79 regs.gpr[i] = env->gpr[i]; |
|
80 |
|
81 ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); |
|
82 if (ret < 0) |
|
83 return ret; |
|
84 |
|
85 return ret; |
|
86 } |
|
87 |
|
88 int kvm_arch_get_registers(CPUState *env) |
|
89 { |
|
90 struct kvm_regs regs; |
|
91 uint32_t i, ret; |
|
92 |
|
93 ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); |
|
94 if (ret < 0) |
|
95 return ret; |
|
96 |
|
97 env->ctr = regs.ctr; |
|
98 env->lr = regs.lr; |
|
99 env->xer = regs.xer; |
|
100 env->msr = regs.msr; |
|
101 env->nip = regs.pc; |
|
102 |
|
103 env->spr[SPR_SRR0] = regs.srr0; |
|
104 env->spr[SPR_SRR1] = regs.srr1; |
|
105 |
|
106 env->spr[SPR_SPRG0] = regs.sprg0; |
|
107 env->spr[SPR_SPRG1] = regs.sprg1; |
|
108 env->spr[SPR_SPRG2] = regs.sprg2; |
|
109 env->spr[SPR_SPRG3] = regs.sprg3; |
|
110 env->spr[SPR_SPRG4] = regs.sprg4; |
|
111 env->spr[SPR_SPRG5] = regs.sprg5; |
|
112 env->spr[SPR_SPRG6] = regs.sprg6; |
|
113 env->spr[SPR_SPRG7] = regs.sprg7; |
|
114 |
|
115 for (i = 0;i < 32; i++) |
|
116 env->gpr[i] = regs.gpr[i]; |
|
117 |
|
118 return 0; |
|
119 } |
|
120 |
|
121 int kvm_arch_pre_run(CPUState *env, struct kvm_run *run) |
|
122 { |
|
123 int r; |
|
124 unsigned irq; |
|
125 |
|
126 /* PowerPC Qemu tracks the various core input pins (interrupt, critical |
|
127 * interrupt, reset, etc) in PPC-specific env->irq_input_state. */ |
|
128 if (run->ready_for_interrupt_injection && |
|
129 (env->interrupt_request & CPU_INTERRUPT_HARD) && |
|
130 (env->irq_input_state & (1<<PPC40x_INPUT_INT))) |
|
131 { |
|
132 /* For now KVM disregards the 'irq' argument. However, in the |
|
133 * future KVM could cache it in-kernel to avoid a heavyweight exit |
|
134 * when reading the UIC. |
|
135 */ |
|
136 irq = -1U; |
|
137 |
|
138 dprintf("injected interrupt %d\n", irq); |
|
139 r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq); |
|
140 if (r < 0) |
|
141 printf("cpu %d fail inject %x\n", env->cpu_index, irq); |
|
142 } |
|
143 |
|
144 /* We don't know if there are more interrupts pending after this. However, |
|
145 * the guest will return to userspace in the course of handling this one |
|
146 * anyways, so we will get a chance to deliver the rest. */ |
|
147 return 0; |
|
148 } |
|
149 |
|
150 int kvm_arch_post_run(CPUState *env, struct kvm_run *run) |
|
151 { |
|
152 return 0; |
|
153 } |
|
154 |
|
155 static int kvmppc_handle_halt(CPUState *env) |
|
156 { |
|
157 if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { |
|
158 env->halted = 1; |
|
159 env->exception_index = EXCP_HLT; |
|
160 } |
|
161 |
|
162 return 1; |
|
163 } |
|
164 |
|
165 /* map dcr access to existing qemu dcr emulation */ |
|
166 static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data) |
|
167 { |
|
168 if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) |
|
169 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); |
|
170 |
|
171 return 1; |
|
172 } |
|
173 |
|
174 static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data) |
|
175 { |
|
176 if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) |
|
177 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); |
|
178 |
|
179 return 1; |
|
180 } |
|
181 |
|
182 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) |
|
183 { |
|
184 int ret = 0; |
|
185 |
|
186 switch (run->exit_reason) { |
|
187 case KVM_EXIT_DCR: |
|
188 if (run->dcr.is_write) { |
|
189 dprintf("handle dcr write\n"); |
|
190 ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); |
|
191 } else { |
|
192 dprintf("handle dcr read\n"); |
|
193 ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); |
|
194 } |
|
195 break; |
|
196 case KVM_EXIT_HLT: |
|
197 dprintf("handle halt\n"); |
|
198 ret = kvmppc_handle_halt(env); |
|
199 break; |
|
200 } |
|
201 |
|
202 return ret; |
|
203 } |
|
204 |