ia64/xen-unstable

view xen/arch/ia64/vmx/vmx_process.c @ 7066:c0ac925e8f1d

Newer compilers don't allow strings to cross newlines?
author djm@kirby.fc.hp.com
date Thu Sep 29 13:35:13 2005 -0600 (2005-09-29)
parents 06d84bf87159
children 93e27f7ca8a8
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /*
3 * vmx_process.c: handling VMX architecture-related VM exits
4 * Copyright (c) 2005, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 * Xiaoyan Feng (Fleming Feng) <fleming.feng@intel.com>
20 * Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
21 */
23 #include <xen/config.h>
24 #include <xen/lib.h>
25 #include <xen/errno.h>
26 #include <xen/sched.h>
27 #include <xen/smp.h>
28 #include <asm/ptrace.h>
29 #include <xen/delay.h>
31 #include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */
32 #include <asm/sal.h> /* FOR struct ia64_sal_retval */
34 #include <asm/system.h>
35 #include <asm/io.h>
36 #include <asm/processor.h>
37 #include <asm/desc.h>
38 //#include <asm/ldt.h>
39 #include <xen/irq.h>
40 #include <xen/event.h>
41 #include <asm/regionreg.h>
42 #include <asm/privop.h>
43 #include <asm/ia64_int.h>
44 //#include <asm/hpsim_ssc.h>
45 #include <asm/dom_fw.h>
46 #include <asm/vmx_vcpu.h>
47 #include <asm/kregs.h>
48 #include <asm/vmx.h>
49 #include <asm/vmx_mm_def.h>
50 #include <xen/mm.h>
51 /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
52 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
55 extern struct ia64_sal_retval pal_emulator_static(UINT64);
56 extern struct ia64_sal_retval sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
57 extern void rnat_consumption (VCPU *vcpu);
58 #define DOMN_PAL_REQUEST 0x110000
59 IA64FAULT
60 vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim)
61 {
62 static int first_time = 1;
63 struct domain *d = (struct domain *) current->domain;
64 struct vcpu *v = (struct domain *) current;
65 extern unsigned long running_on_sim;
66 unsigned long i, sal_param[8];
68 #if 0
69 if (first_time) {
70 if (platform_is_hp_ski()) running_on_sim = 1;
71 else running_on_sim = 0;
72 first_time = 0;
73 }
74 if (iim == 0x80001 || iim == 0x80002) { //FIXME: don't hardcode constant
75 if (running_on_sim) do_ssc(vcpu_get_gr_nat(current,36), regs);
76 else do_ssc(vcpu_get_gr_nat(current,36), regs);
77 }
78 #endif
79 if (iim == d->arch.breakimm) {
80 struct ia64_sal_retval x;
81 switch (regs->r2) {
82 case FW_HYPERCALL_PAL_CALL:
83 //printf("*** PAL hypercall: index=%d\n",regs->r28);
84 //FIXME: This should call a C routine
85 x = pal_emulator_static(VCPU(v, vgr[12]));
86 regs->r8 = x.status; regs->r9 = x.v0;
87 regs->r10 = x.v1; regs->r11 = x.v2;
88 #if 0
89 if (regs->r8)
90 printk("Failed vpal emulation, with index:0x%lx\n",
91 VCPU(v, vgr[12]));
92 #endif
93 break;
94 case FW_HYPERCALL_SAL_CALL:
95 for (i = 0; i < 8; i++)
96 vcpu_get_gr_nat(v, 32+i, &sal_param[i]);
97 x = sal_emulator(sal_param[0], sal_param[1],
98 sal_param[2], sal_param[3],
99 sal_param[4], sal_param[5],
100 sal_param[6], sal_param[7]);
101 regs->r8 = x.status; regs->r9 = x.v0;
102 regs->r10 = x.v1; regs->r11 = x.v2;
103 #if 0
104 if (regs->r8)
105 printk("Failed vsal emulation, with index:0x%lx\n",
106 sal_param[0]);
107 #endif
108 break;
109 case FW_HYPERCALL_EFI_RESET_SYSTEM:
110 printf("efi.reset_system called ");
111 if (current->domain == dom0) {
112 printf("(by dom0)\n ");
113 (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL);
114 }
115 printf("(not supported for non-0 domain)\n");
116 regs->r8 = EFI_UNSUPPORTED;
117 break;
118 case FW_HYPERCALL_EFI_GET_TIME:
119 {
120 unsigned long *tv, *tc;
121 vcpu_get_gr_nat(v, 32, &tv);
122 vcpu_get_gr_nat(v, 33, &tc);
123 printf("efi_get_time(%p,%p) called...",tv,tc);
124 tv = __va(translate_domain_mpaddr(tv));
125 if (tc) tc = __va(translate_domain_mpaddr(tc));
126 regs->r8 = (*efi.get_time)(tv,tc);
127 printf("and returns %lx\n",regs->r8);
128 }
129 break;
130 case FW_HYPERCALL_EFI_SET_TIME:
131 case FW_HYPERCALL_EFI_GET_WAKEUP_TIME:
132 case FW_HYPERCALL_EFI_SET_WAKEUP_TIME:
133 // FIXME: need fixes in efi.h from 2.6.9
134 case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
135 // FIXME: WARNING!! IF THIS EVER GETS IMPLEMENTED
136 // SOME OF THE OTHER EFI EMULATIONS WILL CHANGE AS
137 // POINTER ARGUMENTS WILL BE VIRTUAL!!
138 case FW_HYPERCALL_EFI_GET_VARIABLE:
139 // FIXME: need fixes in efi.h from 2.6.9
140 case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE:
141 case FW_HYPERCALL_EFI_SET_VARIABLE:
142 case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT:
143 // FIXME: need fixes in efi.h from 2.6.9
144 regs->r8 = EFI_UNSUPPORTED;
145 break;
146 }
147 #if 0
148 if (regs->r8)
149 printk("Failed vgfw emulation, with index:0x%lx\n",
150 regs->r2);
151 #endif
152 vmx_vcpu_increment_iip(current);
153 }else if(iim == DOMN_PAL_REQUEST){
154 pal_emul(current);
155 vmx_vcpu_increment_iip(current);
156 } else
157 vmx_reflect_interruption(ifa,isr,iim,11,regs);
158 }
160 static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
161 0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00,0x4000,
162 0x4400,0x4800,0x4c00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,
163 0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,0x6000,
164 0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,0x6800,0x6900,0x6a00,
165 0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,0x7000,0x7100,0x7200,0x7300,0x7400,
166 0x7500,0x7600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,
167 0x7f00,
168 };
172 void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
173 UINT64 vector,REGS *regs)
174 {
175 VCPU *vcpu = current;
176 UINT64 viha,vpsr = vmx_vcpu_get_psr(vcpu);
177 if(!(vpsr&IA64_PSR_IC)&&(vector!=5)){
178 panic("Guest nested fault!");
179 }
180 VCPU(vcpu,isr)=isr;
181 VCPU(vcpu,iipa) = regs->cr_iip;
182 vector=vec2off[vector];
183 if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
184 VCPU(vcpu,iim) = iim;
185 else {
186 set_ifa_itir_iha(vcpu,ifa,1,1,1);
187 }
188 inject_guest_interruption(vcpu, vector);
189 }
192 void save_banked_regs_to_vpd(VCPU *v, REGS *regs)
193 {
194 unsigned long i, * src,* dst, *sunat, *dunat;
195 IA64_PSR vpsr;
196 src=&regs->r16;
197 sunat=&regs->eml_unat;
198 vpsr.val = vmx_vcpu_get_psr(v);
199 if(vpsr.bn){
200 dst = &VCPU(v, vgr[0]);
201 dunat =&VCPU(v, vnat);
202 __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \
203 dep %2 = %0, %2, 0, 16;; \
204 st8 [%3] = %2;;"
205 ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
207 }else{
208 dst = &VCPU(v, vbgr[0]);
209 // dunat =&VCPU(v, vbnat);
210 // __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;;
211 // dep %2 = %0, %2, 16, 16;;
212 // st8 [%3] = %2;;"
213 // ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
215 }
216 for(i=0; i<16; i++)
217 *dst++ = *src++;
218 }
221 // ONLY gets called from ia64_leave_kernel
222 // ONLY call with interrupts disabled?? (else might miss one?)
223 // NEVER successful if already reflecting a trap/fault because psr.i==0
224 void leave_hypervisor_tail(struct pt_regs *regs)
225 {
226 struct domain *d = current->domain;
227 struct vcpu *v = current;
228 // FIXME: Will this work properly if doing an RFI???
229 if (!is_idle_task(d) ) { // always comes from guest
230 extern void vmx_dorfirfi(void);
231 struct pt_regs *user_regs = vcpu_regs(current);
232 if (local_softirq_pending())
233 do_softirq();
234 local_irq_disable();
236 if (user_regs != regs)
237 printk("WARNING: checking pending interrupt in nested interrupt!!!\n");
239 /* VMX Domain N has other interrupt source, saying DM */
240 if (test_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags))
241 vmx_intr_assist(v);
243 /* FIXME: Check event pending indicator, and set
244 * pending bit if necessary to inject back to guest.
245 * Should be careful about window between this check
246 * and above assist, since IOPACKET_PORT shouldn't be
247 * injected into vmx domain.
248 *
249 * Now hardcode the vector as 0x10 temporarily
250 */
251 if (event_pending(v)&&(!(VLSAPIC_INSVC(v,0)&(1UL<<0x10)))) {
252 VCPU(v, irr[0]) |= 1UL << 0x10;
253 v->arch.irq_new_pending = 1;
254 }
256 if ( v->arch.irq_new_pending ) {
257 v->arch.irq_new_pending = 0;
258 vmx_check_pending_irq(v);
259 }
260 // if (VCPU(v,vac).a_bsw){
261 // save_banked_regs_to_vpd(v,regs);
262 // }
264 }
265 }
267 extern ia64_rr vmx_vcpu_rr(VCPU *vcpu,UINT64 vadr);
269 /* We came here because the H/W VHPT walker failed to find an entry */
270 void vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
271 {
272 IA64_PSR vpsr;
273 CACHE_LINE_TYPE type;
274 u64 vhpt_adr;
275 ISR misr;
276 ia64_rr vrr;
277 REGS *regs;
278 thash_cb_t *vtlb, *vhpt;
279 thash_data_t *data, me;
280 VCPU *v = current;
281 vtlb=vmx_vcpu_get_vtlb(v);
282 #ifdef VTLB_DEBUG
283 check_vtlb_sanity(vtlb);
284 dump_vtlb(vtlb);
285 #endif
286 vpsr.val = vmx_vcpu_get_psr(v);
287 misr.val=VMX(v,cr_isr);
289 /* TODO
290 if(v->domain->id && vec == 2 &&
291 vpsr.dt == 0 && is_gpa_io(MASK_PMA(vaddr))){
292 emulate_ins(&v);
293 return;
294 }
295 */
297 if((vec==1)&&(!vpsr.it)){
298 physical_itlb_miss(v, vadr);
299 return;
300 }
301 if((vec==2)&&(!vpsr.dt)){
302 if(v->domain!=dom0&&__gpfn_is_io(v->domain,(vadr<<1)>>(PAGE_SHIFT+1))){
303 emulate_io_inst(v,((vadr<<1)>>1),4); // UC
304 }else{
305 physical_dtlb_miss(v, vadr);
306 }
307 return;
308 }
309 vrr = vmx_vcpu_rr(v, vadr);
310 if(vec == 1) type = ISIDE_TLB;
311 else if(vec == 2) type = DSIDE_TLB;
312 else panic("wrong vec\n");
314 // prepare_if_physical_mode(v);
316 if(data=vtlb_lookup_ex(vtlb, vrr.rid, vadr,type)){
317 if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,data->ppn>>(PAGE_SHIFT-12))){
318 vadr=(vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
319 emulate_io_inst(v, vadr, data->ma);
320 return IA64_FAULT;
321 }
323 if ( data->ps != vrr.ps ) {
324 machine_tlb_insert(v, data);
325 }
326 else {
327 thash_insert(vtlb->ts->vhpt,data,vadr);
328 }
329 }else if(type == DSIDE_TLB){
330 if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
331 if(vpsr.ic){
332 vcpu_set_isr(v, misr.val);
333 alt_dtlb(v, vadr);
334 return IA64_FAULT;
335 } else{
336 if(misr.sp){
337 //TODO lds emulation
338 panic("Don't support speculation load");
339 }else{
340 nested_dtlb(v);
341 return IA64_FAULT;
342 }
343 }
344 } else{
345 vmx_vcpu_thash(v, vadr, &vhpt_adr);
346 vrr=vmx_vcpu_rr(v,vhpt_adr);
347 data = vtlb_lookup_ex(vtlb, vrr.rid, vhpt_adr, DSIDE_TLB);
348 if(data){
349 if(vpsr.ic){
350 vcpu_set_isr(v, misr.val);
351 dtlb_fault(v, vadr);
352 return IA64_FAULT;
353 }else{
354 if(misr.sp){
355 //TODO lds emulation
356 panic("Don't support speculation load");
357 }else{
358 nested_dtlb(v);
359 return IA64_FAULT;
360 }
361 }
362 }else{
363 if(vpsr.ic){
364 vcpu_set_isr(v, misr.val);
365 dvhpt_fault(v, vadr);
366 return IA64_FAULT;
367 }else{
368 if(misr.sp){
369 //TODO lds emulation
370 panic("Don't support speculation load");
371 }else{
372 nested_dtlb(v);
373 return IA64_FAULT;
374 }
375 }
376 }
377 }
378 }else if(type == ISIDE_TLB){
379 if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
380 if(!vpsr.ic){
381 misr.ni=1;
382 }
383 vcpu_set_isr(v, misr.val);
384 alt_itlb(v, vadr);
385 return IA64_FAULT;
386 } else{
387 vmx_vcpu_thash(v, vadr, &vhpt_adr);
388 vrr=vmx_vcpu_rr(v,vhpt_adr);
389 data = vtlb_lookup_ex(vtlb, vrr.rid, vhpt_adr, DSIDE_TLB);
390 if(data){
391 if(!vpsr.ic){
392 misr.ni=1;
393 }
394 vcpu_set_isr(v, misr.val);
395 itlb_fault(v, vadr);
396 return IA64_FAULT;
397 }else{
398 if(!vpsr.ic){
399 misr.ni=1;
400 }
401 vcpu_set_isr(v, misr.val);
402 ivhpt_fault(v, vadr);
403 return IA64_FAULT;
404 }
405 }
406 }
407 }