ia64/xen-unstable

view xen/arch/ia64/vmx/vmx_process.c @ 9765:7c7bcf173f8b

[IA64] cleanup vtlb code

This patch is to clean up vtlb code.

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
author awilliam@xenbuild.aw
date Tue Apr 25 20:53:38 2006 -0600 (2006-04-25)
parents 633e8bbabf76
children 6e979aa0e6d2
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/debugger.h>
45 //#include <asm/hpsim_ssc.h>
46 #include <asm/dom_fw.h>
47 #include <asm/vmx_vcpu.h>
48 #include <asm/kregs.h>
49 #include <asm/vmx.h>
50 #include <asm/vmmu.h>
51 #include <asm/vmx_mm_def.h>
52 #include <asm/vmx_phy_mode.h>
53 #include <xen/mm.h>
54 #include <asm/vmx_pal.h>
55 /* reset all PSR field to 0, except up,mfl,mfh,pk,dt,rt,mc,it */
56 #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
59 extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
60 extern void rnat_consumption (VCPU *vcpu);
61 extern unsigned long translate_domain_mpaddr(unsigned long mpaddr);
62 extern void alt_itlb (VCPU *vcpu, u64 vadr);
63 extern void itlb_fault (VCPU *vcpu, u64 vadr);
64 extern void ivhpt_fault (VCPU *vcpu, u64 vadr);
66 #define DOMN_PAL_REQUEST 0x110000
68 static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
69 0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00,0x4000,
70 0x4400,0x4800,0x4c00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,
71 0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,0x6000,
72 0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,0x6800,0x6900,0x6a00,
73 0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,0x7000,0x7100,0x7200,0x7300,0x7400,
74 0x7500,0x7600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,
75 0x7f00
76 };
80 void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
81 UINT64 vector,REGS *regs)
82 {
83 VCPU *vcpu = current;
84 UINT64 vpsr = vmx_vcpu_get_psr(vcpu);
85 vector=vec2off[vector];
86 if(!(vpsr&IA64_PSR_IC)&&(vector!=0x1400)){
87 panic_domain(regs, "Guest nested fault vector=%lx!\n", vector);
88 }
89 VCPU(vcpu,isr)=isr;
90 VCPU(vcpu,iipa) = regs->cr_iip;
91 if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
92 VCPU(vcpu,iim) = iim;
93 else {
94 set_ifa_itir_iha(vcpu,ifa,1,1,1);
95 }
96 inject_guest_interruption(vcpu, vector);
97 }
99 static void
100 vmx_handle_hypercall (VCPU *v, REGS *regs)
101 {
102 struct ia64_pal_retval y;
103 struct sal_ret_values x;
104 unsigned long i, sal_param[8];
106 switch (regs->r2) {
107 case FW_HYPERCALL_PAL_CALL:
108 //printf("*** PAL hypercall: index=%d\n",regs->r28);
109 //FIXME: This should call a C routine
110 y = pal_emulator_static(VCPU(v, vgr[12]));
111 regs->r8 = y.status; regs->r9 = y.v0;
112 regs->r10 = y.v1; regs->r11 = y.v2;
113 #if 0
114 if (regs->r8)
115 printk("Failed vpal emulation, with index:0x%lx\n",
116 VCPU(v, vgr[12]));
117 #endif
118 break;
119 case FW_HYPERCALL_SAL_CALL:
120 for (i = 0; i < 8; i++)
121 vcpu_get_gr_nat(v, 32+i, &sal_param[i]);
122 x = sal_emulator(sal_param[0], sal_param[1],
123 sal_param[2], sal_param[3],
124 sal_param[4], sal_param[5],
125 sal_param[6], sal_param[7]);
126 regs->r8 = x.r8; regs->r9 = x.r9;
127 regs->r10 = x.r10; regs->r11 = x.r11;
128 #if 0
129 if (regs->r8)
130 printk("Failed vsal emulation, with index:0x%lx\n",
131 sal_param[0]);
132 #endif
133 break;
134 case FW_HYPERCALL_EFI_RESET_SYSTEM:
135 printf("efi.reset_system called ");
136 if (current->domain == dom0) {
137 printf("(by dom0)\n ");
138 (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL);
139 }
140 printf("(not supported for non-0 domain)\n");
141 regs->r8 = EFI_UNSUPPORTED;
142 break;
143 case FW_HYPERCALL_EFI_GET_TIME:
144 {
145 unsigned long *tv, *tc;
146 vcpu_get_gr_nat(v, 32, (u64 *)&tv);
147 vcpu_get_gr_nat(v, 33, (u64 *)&tc);
148 printf("efi_get_time(%p,%p) called...",tv,tc);
149 tv = __va(translate_domain_mpaddr((unsigned long)tv));
150 if (tc) tc = __va(translate_domain_mpaddr((unsigned long)tc));
151 regs->r8 = (*efi.get_time)((efi_time_t *)tv,(efi_time_cap_t *)tc);
152 printf("and returns %lx\n",regs->r8);
153 }
154 break;
155 case FW_HYPERCALL_EFI_SET_TIME:
156 case FW_HYPERCALL_EFI_GET_WAKEUP_TIME:
157 case FW_HYPERCALL_EFI_SET_WAKEUP_TIME:
158 // FIXME: need fixes in efi.h from 2.6.9
159 case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
160 // FIXME: WARNING!! IF THIS EVER GETS IMPLEMENTED
161 // SOME OF THE OTHER EFI EMULATIONS WILL CHANGE AS
162 // POINTER ARGUMENTS WILL BE VIRTUAL!!
163 case FW_HYPERCALL_EFI_GET_VARIABLE:
164 // FIXME: need fixes in efi.h from 2.6.9
165 case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE:
166 case FW_HYPERCALL_EFI_SET_VARIABLE:
167 case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT:
168 // FIXME: need fixes in efi.h from 2.6.9
169 regs->r8 = EFI_UNSUPPORTED;
170 break;
171 }
172 #if 0
173 if (regs->r8)
174 printk("Failed vgfw emulation, with index:0x%lx\n",
175 regs->r2);
176 #endif
177 }
179 IA64FAULT
180 vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim)
181 {
182 struct domain *d = current->domain;
183 struct vcpu *v = current;
185 #ifdef CRASH_DEBUG
186 if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs) &&
187 IS_VMM_ADDRESS(regs->cr_iip)) {
188 if (iim == 0)
189 show_registers(regs);
190 debugger_trap_fatal(0 /* don't care */, regs);
191 } else
192 #endif
193 {
194 if (iim == 0)
195 die_if_kernel("bug check", regs, iim);
197 if (!user_mode(regs)) {
198 /* Allow hypercalls only when cpl = 0. */
199 if (iim == d->arch.breakimm) {
200 vmx_handle_hypercall (v ,regs);
201 vmx_vcpu_increment_iip(current);
202 return IA64_NO_FAULT;
203 }
204 else if(iim == DOMN_PAL_REQUEST){
205 pal_emul(current);
206 vmx_vcpu_increment_iip(current);
207 return IA64_NO_FAULT;
208 }
209 }
210 vmx_reflect_interruption(ifa,isr,iim,11,regs);
211 }
212 return IA64_NO_FAULT;
213 }
216 void save_banked_regs_to_vpd(VCPU *v, REGS *regs)
217 {
218 unsigned long i=0UL, * src,* dst, *sunat, *dunat;
219 IA64_PSR vpsr;
220 src=&regs->r16;
221 sunat=&regs->eml_unat;
222 vpsr.val = vmx_vcpu_get_psr(v);
223 if(vpsr.bn){
224 dst = &VCPU(v, vgr[0]);
225 dunat =&VCPU(v, vnat);
226 __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;; \
227 dep %2 = %0, %2, 0, 16;; \
228 st8 [%3] = %2;;"
229 ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
231 }else{
232 dst = &VCPU(v, vbgr[0]);
233 // dunat =&VCPU(v, vbnat);
234 // __asm__ __volatile__ (";;extr.u %0 = %1,%4,16;;
235 // dep %2 = %0, %2, 16, 16;;
236 // st8 [%3] = %2;;"
237 // ::"r"(i),"r"(*sunat),"r"(*dunat),"r"(dunat),"i"(IA64_PT_REGS_R16_SLOT):"memory");
239 }
240 for(i=0; i<16; i++)
241 *dst++ = *src++;
242 }
245 // ONLY gets called from ia64_leave_kernel
246 // ONLY call with interrupts disabled?? (else might miss one?)
247 // NEVER successful if already reflecting a trap/fault because psr.i==0
248 void leave_hypervisor_tail(struct pt_regs *regs)
249 {
250 struct domain *d = current->domain;
251 struct vcpu *v = current;
252 // FIXME: Will this work properly if doing an RFI???
253 if (!is_idle_domain(d) ) { // always comes from guest
254 extern void vmx_dorfirfi(void);
255 struct pt_regs *user_regs = vcpu_regs(current);
256 if (local_softirq_pending())
257 do_softirq();
258 local_irq_disable();
260 if (user_regs != regs)
261 printk("WARNING: checking pending interrupt in nested interrupt!!!\n");
263 /* VMX Domain N has other interrupt source, saying DM */
264 if (test_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags))
265 vmx_intr_assist(v);
267 /* FIXME: Check event pending indicator, and set
268 * pending bit if necessary to inject back to guest.
269 * Should be careful about window between this check
270 * and above assist, since IOPACKET_PORT shouldn't be
271 * injected into vmx domain.
272 *
273 * Now hardcode the vector as 0x10 temporarily
274 */
275 // if (event_pending(v)&&(!(VLSAPIC_INSVC(v,0)&(1UL<<0x10)))) {
276 // VCPU(v, irr[0]) |= 1UL << 0x10;
277 // v->arch.irq_new_pending = 1;
278 // }
280 if ( v->arch.irq_new_pending ) {
281 v->arch.irq_new_pending = 0;
282 vmx_check_pending_irq(v);
283 }
284 // if (VCPU(v,vac).a_bsw){
285 // save_banked_regs_to_vpd(v,regs);
286 // }
288 }
289 }
291 extern ia64_rr vmx_vcpu_rr(VCPU *vcpu,UINT64 vadr);
293 static int vmx_handle_lds(REGS* regs)
294 {
295 regs->cr_ipsr |=IA64_PSR_ED;
296 return IA64_FAULT;
297 }
299 /* We came here because the H/W VHPT walker failed to find an entry */
300 IA64FAULT
301 vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
302 {
303 IA64_PSR vpsr;
304 int type=ISIDE_TLB;
305 u64 vhpt_adr, gppa;
306 ISR misr;
307 // REGS *regs;
308 thash_data_t *data;
309 VCPU *v = current;
310 #ifdef VTLB_DEBUG
311 check_vtlb_sanity(vtlb);
312 dump_vtlb(vtlb);
313 #endif
314 vpsr.val = vmx_vcpu_get_psr(v);
315 misr.val=VMX(v,cr_isr);
317 /* TODO
318 if(v->domain->id && vec == 2 &&
319 vpsr.dt == 0 && is_gpa_io(MASK_PMA(vaddr))){
320 emulate_ins(&v);
321 return;
322 }
323 */
324 /* if(vadr == 0x1ea18c00 ){
325 ia64_clear_ic();
326 while(1);
327 }
328 */
329 if(is_physical_mode(v)&&(!(vadr<<1>>62))){
330 if(vec==2){
331 if(v->domain!=dom0&&__gpfn_is_io(v->domain,(vadr<<1)>>(PAGE_SHIFT+1))){
332 emulate_io_inst(v,((vadr<<1)>>1),4); // UC
333 return IA64_FAULT;
334 }
335 }
336 physical_tlb_miss(v, vadr, vec);
337 return IA64_FAULT;
338 }
339 if(vec == 1) type = ISIDE_TLB;
340 else if(vec == 2) type = DSIDE_TLB;
341 else panic("wrong vec\n");
343 // prepare_if_physical_mode(v);
345 if((data=vtlb_lookup(v, vadr,type))!=0){
346 // gppa = (vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
347 // if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,gppa>>PAGE_SHIFT)){
348 if(v->domain!=dom0 && data->io && type==DSIDE_TLB ){
349 gppa = (vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
350 emulate_io_inst(v, gppa, data->ma);
351 return IA64_FAULT;
352 }
354 // if ( data->ps != vrr.ps ) {
355 // machine_tlb_insert(v, data);
356 // }
357 // else {
358 /* if ( data->contiguous&&(!data->tc)){
359 machine_tlb_insert(v, data);
360 }
361 else{
362 */
363 thash_vhpt_insert(&v->arch.vhpt,data->page_flags, data->itir ,vadr);
364 // }
365 // }
366 }else if(type == DSIDE_TLB){
367 if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
368 if(vpsr.ic){
369 vcpu_set_isr(v, misr.val);
370 alt_dtlb(v, vadr);
371 return IA64_FAULT;
372 } else{
373 if(misr.sp){
374 //TODO lds emulation
375 //panic("Don't support speculation load");
376 return vmx_handle_lds(regs);
377 }else{
378 nested_dtlb(v);
379 return IA64_FAULT;
380 }
381 }
382 } else{
383 vmx_vcpu_thash(v, vadr, &vhpt_adr);
384 if(vhpt_lookup(vhpt_adr) || vtlb_lookup(v, vhpt_adr, DSIDE_TLB)){
385 if(vpsr.ic){
386 vcpu_set_isr(v, misr.val);
387 dtlb_fault(v, vadr);
388 return IA64_FAULT;
389 }else{
390 if(misr.sp){
391 //TODO lds emulation
392 //panic("Don't support speculation load");
393 return vmx_handle_lds(regs);
394 }else{
395 nested_dtlb(v);
396 return IA64_FAULT;
397 }
398 }
399 }else{
400 if(vpsr.ic){
401 vcpu_set_isr(v, misr.val);
402 dvhpt_fault(v, vadr);
403 return IA64_FAULT;
404 }else{
405 if(misr.sp){
406 //TODO lds emulation
407 //panic("Don't support speculation load");
408 return vmx_handle_lds(regs);
409 }else{
410 nested_dtlb(v);
411 return IA64_FAULT;
412 }
413 }
414 }
415 }
416 }else if(type == ISIDE_TLB){
417 if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
418 if(!vpsr.ic){
419 misr.ni=1;
420 }
421 vcpu_set_isr(v, misr.val);
422 alt_itlb(v, vadr);
423 return IA64_FAULT;
424 } else{
425 vmx_vcpu_thash(v, vadr, &vhpt_adr);
426 if(vhpt_lookup(vhpt_adr) || vtlb_lookup(v, vhpt_adr, DSIDE_TLB)){
427 if(!vpsr.ic){
428 misr.ni=1;
429 }
430 vcpu_set_isr(v, misr.val);
431 itlb_fault(v, vadr);
432 return IA64_FAULT;
433 }else{
434 if(!vpsr.ic){
435 misr.ni=1;
436 }
437 vcpu_set_isr(v, misr.val);
438 ivhpt_fault(v, vadr);
439 return IA64_FAULT;
440 }
441 }
442 }
443 return IA64_NO_FAULT;
444 }