Fix apic -no-kvm with SMP
[qemu-kvm/fedora.git] / qemu-kvm-powerpc.c
blob19fde40dcbefb290f5d4e9dc35639d43142a0069
1 /*
2 * qemu-kvm-power.c
4 * Add KVM PowerPC specific calls for qemu.
6 * Copyright 2007 IBM Corporation.
7 * Added by & Authors:
8 * Jerone Young <jyoung5@us.ibm.com>
9 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
11 * This work is licensed under the GNU GPL licence version 2 or later.
15 #include "config.h"
16 #include "config-host.h"
18 #include <string.h>
19 #include "hw/hw.h"
20 #include "sysemu.h"
21 #include "cpu.h"
22 #include "exec-all.h"
23 #include "helper_regs.h"
25 #include "qemu-kvm.h"
26 #include <libkvm.h>
27 #include <pthread.h>
28 #include <sys/utsname.h>
30 extern kvm_context_t kvm_context;
32 void cpu_reset(CPUState *env)
34 memset(env->breakpoints, 0, sizeof(env->breakpoints));
35 cpu_ppc_reset(env);
39 int kvm_arch_qemu_create_context(void)
41 return 0;
44 void kvm_arch_load_regs(CPUState *env)
46 struct kvm_regs regs;
47 int rc,i;
49 rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
50 if (rc == -1)
51 perror("kvm_get_regs FAILED");
53 /* cr is untouched in qemu and not existant in CPUState fr ppr */
54 /* hflags is a morphed to MSR on ppc, no need to sync that down to kvm */
56 regs.pc = env->nip;
58 regs.ctr = env->ctr;
59 regs.lr = env->lr;
60 regs.xer = env->xer;
61 regs.msr = env->msr;
63 regs.srr0 = env->spr[SPR_SRR0];
64 regs.srr1 = env->spr[SPR_SRR1];
66 regs.sprg0 = env->spr[SPR_SPRG0];
67 regs.sprg1 = env->spr[SPR_SPRG1];
68 regs.sprg2 = env->spr[SPR_SPRG2];
69 regs.sprg3 = env->spr[SPR_SPRG3];
70 regs.sprg4 = env->spr[SPR_SPRG4];
71 regs.sprg5 = env->spr[SPR_SPRG5];
72 regs.sprg6 = env->spr[SPR_SPRG6];
73 regs.sprg7 = env->spr[SPR_SPRG7];
75 for (i = 0;i < 32; i++){
76 regs.gpr[i] = env->gpr[i];
79 rc = kvm_set_regs(kvm_context, env->cpu_index, &regs);
80 if (rc == -1)
81 perror("kvm_set_regs FAILED");
85 void kvm_arch_save_regs(CPUState *env)
87 struct kvm_regs regs;
88 uint32_t i, rc;
90 rc = kvm_get_regs(kvm_context, env->cpu_index, &regs);
91 if (rc == -1)
92 perror("kvm_get_regs FAILED");
94 env->ctr =regs.ctr;
95 env->lr = regs.lr;
96 env->xer = regs.xer;
97 env->msr = regs.msr;
98 /* calculate hflags based on the current msr using the ppc qemu helper */
99 hreg_compute_hflags(env);
101 env->nip = regs.pc;
103 env->spr[SPR_SRR0] = regs.srr0;
104 env->spr[SPR_SRR1] = regs.srr1;
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;
115 for (i = 0;i < 32; i++){
116 env->gpr[i] = regs.gpr[i];
121 int kvm_arch_qemu_init_env(CPUState *cenv)
123 if (cenv->cpu_index == 0) {
124 /* load any registers set in env into
125 kvm for the first guest vcpu */
126 kvm_load_registers(cenv);
129 return 0;
132 int kvm_arch_halt(void *opaque, int vcpu)
134 CPUState *env = cpu_single_env;
136 if (!(env->interrupt_request & CPU_INTERRUPT_HARD)
137 && (msr_ee))
139 env->halted = 1;
140 env->exception_index = EXCP_HLT;
142 return 1;
145 void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
147 return;
150 void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
152 cpu_single_env = env;
155 int kvm_arch_has_work(CPUState *env)
157 if ((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT)) &&
158 (msr_ee))
159 return 1;
160 return 0;
163 int kvm_arch_try_push_interrupts(void *opaque)
165 CPUState *env = cpu_single_env;
166 int r;
167 unsigned irq;
169 /* PowerPC Qemu tracks the various core input pins (interrupt, critical
170 * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
171 if (kvm_is_ready_for_interrupt_injection(kvm_context, env->cpu_index) &&
172 (env->irq_input_state & (1<<PPC40x_INPUT_INT)))
174 /* For now KVM disregards the 'irq' argument. However, in the
175 * future KVM could cache it in-kernel to avoid a heavyweight exit
176 * when reading the UIC.
178 irq = -1U;
180 r = kvm_inject_irq(kvm_context, env->cpu_index, irq);
181 if (r < 0)
182 printf("cpu %d fail inject %x\n", env->cpu_index, irq);
185 /* We don't know if there are more interrupts pending after this. However,
186 * the guest will return to userspace in the course of handling this one
187 * anyways, so we will get a chance to deliver the rest. */
188 return 0;
191 int kvm_arch_try_push_nmi(void *opaque)
193 /* no nmi irq, so discard that call for now and return success.
194 * This might later get mapped to something on powerpc too if we want
195 * to support the nmi monitor command somwhow */
196 return 0;
199 void kvm_arch_update_regs_for_sipi(CPUState *env)
201 printf("%s: no kvm-powerpc multi processor support yet!\n", __func__);
204 /* map dcr access to existing qemu dcr emulation */
205 int handle_powerpc_dcr_read(int vcpu, uint32_t dcrn, uint32_t *data)
207 CPUState *env = cpu_single_env;
208 if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
209 fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
211 return 0; /* XXX ignore failed DCR ops */
214 int handle_powerpc_dcr_write(int vcpu, uint32_t dcrn, uint32_t data)
216 CPUState *env = cpu_single_env;
217 if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
218 fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
220 return 0; /* XXX ignore failed DCR ops */
223 void kvm_arch_cpu_reset(CPUState *env)