Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
kvm_fw.c
Go to the documentation of this file.
1 /*
2  * PAL/SAL call delegation
3  *
4  * Copyright (c) 2004 Li Susie <[email protected]>
5  * Copyright (c) 2005 Yu Ke <[email protected]>
6  * Copyright (c) 2007 Xiantao Zhang <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms and conditions of the GNU General Public License,
10  * version 2, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place - Suite 330, Boston, MA 02111-1307 USA.
20  */
21 
22 #include <linux/kvm_host.h>
23 #include <linux/smp.h>
24 #include <asm/sn/addrs.h>
25 #include <asm/sn/clksupport.h>
26 #include <asm/sn/shub_mmr.h>
27 
28 #include "vti.h"
29 #include "misc.h"
30 
31 #include <asm/pal.h>
32 #include <asm/sal.h>
33 #include <asm/tlb.h>
34 
35 /*
36  * Handy macros to make sure that the PAL return values start out
37  * as something meaningful.
38  */
39 #define INIT_PAL_STATUS_UNIMPLEMENTED(x) \
40  { \
41  x.status = PAL_STATUS_UNIMPLEMENTED; \
42  x.v0 = 0; \
43  x.v1 = 0; \
44  x.v2 = 0; \
45  }
46 
47 #define INIT_PAL_STATUS_SUCCESS(x) \
48  { \
49  x.status = PAL_STATUS_SUCCESS; \
50  x.v0 = 0; \
51  x.v1 = 0; \
52  x.v2 = 0; \
53  }
54 
55 static void kvm_get_pal_call_data(struct kvm_vcpu *vcpu,
56  u64 *gr28, u64 *gr29, u64 *gr30, u64 *gr31) {
57  struct exit_ctl_data *p;
58 
59  if (vcpu) {
60  p = &vcpu->arch.exit_data;
62  *gr28 = p->u.pal_data.gr28;
63  *gr29 = p->u.pal_data.gr29;
64  *gr30 = p->u.pal_data.gr30;
65  *gr31 = p->u.pal_data.gr31;
66  return ;
67  }
68  }
69  printk(KERN_DEBUG"Failed to get vcpu pal data!!!\n");
70 }
71 
72 static void set_pal_result(struct kvm_vcpu *vcpu,
73  struct ia64_pal_retval result) {
74 
75  struct exit_ctl_data *p;
76 
77  p = kvm_get_exit_data(vcpu);
79  p->u.pal_data.ret = result;
80  return ;
81  }
83 }
84 
85 static void set_sal_result(struct kvm_vcpu *vcpu,
86  struct sal_ret_values result) {
87  struct exit_ctl_data *p;
88 
89  p = kvm_get_exit_data(vcpu);
91  p->u.sal_data.ret = result;
92  return ;
93  }
94  printk(KERN_WARNING"Failed to set sal result!!\n");
95 }
96 
101  long status;
102 };
103 
105 
106 static void remote_pal_cache_flush(void *data)
107 {
108  struct cache_flush_args *args = data;
109  long status;
110  u64 progress = args->progress;
111 
112  status = ia64_pal_cache_flush(args->cache_type, args->operation,
113  &progress, NULL);
114  if (status != 0)
115  args->status = status;
116 }
117 
118 static struct ia64_pal_retval pal_cache_flush(struct kvm_vcpu *vcpu)
119 {
120  u64 gr28, gr29, gr30, gr31;
121  struct ia64_pal_retval result = {0, 0, 0, 0};
122  struct cache_flush_args args = {0, 0, 0, 0};
123  long psr;
124 
125  gr28 = gr29 = gr30 = gr31 = 0;
126  kvm_get_pal_call_data(vcpu, &gr28, &gr29, &gr30, &gr31);
127 
128  if (gr31 != 0)
129  printk(KERN_ERR"vcpu:%p called cache_flush error!\n", vcpu);
130 
131  /* Always call Host Pal in int=1 */
132  gr30 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
133  args.cache_type = gr29;
134  args.operation = gr30;
135  smp_call_function(remote_pal_cache_flush,
136  (void *)&args, 1);
137  if (args.status != 0)
138  printk(KERN_ERR"pal_cache_flush error!,"
139  "status:0x%lx\n", args.status);
140  /*
141  * Call Host PAL cache flush
142  * Clear psr.ic when call PAL_CACHE_FLUSH
143  */
144  local_irq_save(psr);
145  result.status = ia64_pal_cache_flush(gr29, gr30, &result.v1,
146  &result.v0);
147  local_irq_restore(psr);
148  if (result.status != 0)
149  printk(KERN_ERR"vcpu:%p crashed due to cache_flush err:%ld"
150  "in1:%lx,in2:%lx\n",
151  vcpu, result.status, gr29, gr30);
152 
153 #if 0
154  if (gr29 == PAL_CACHE_TYPE_COHERENT) {
155  cpus_setall(vcpu->arch.cache_coherent_map);
156  cpu_clear(vcpu->cpu, vcpu->arch.cache_coherent_map);
157  cpus_setall(cpu_cache_coherent_map);
158  cpu_clear(vcpu->cpu, cpu_cache_coherent_map);
159  }
160 #endif
161  return result;
162 }
163 
165 {
166 
167  struct ia64_pal_retval result;
168 
169  PAL_CALL(result, PAL_CACHE_SUMMARY, 0, 0, 0);
170  return result;
171 }
172 
173 static struct ia64_pal_retval pal_freq_base(struct kvm_vcpu *vcpu)
174 {
175 
176  struct ia64_pal_retval result;
177 
178  PAL_CALL(result, PAL_FREQ_BASE, 0, 0, 0);
179 
180  /*
181  * PAL_FREQ_BASE may not be implemented in some platforms,
182  * call SAL instead.
183  */
184  if (result.v0 == 0) {
186  &result.v0,
187  &result.v1);
188  result.v2 = 0;
189  }
190 
191  return result;
192 }
193 
194 /*
195  * On the SGI SN2, the ITC isn't stable. Emulation backed by the SN2
196  * RTC is used instead. This function patches the ratios from SAL
197  * to match the RTC before providing them to the guest.
198  */
199 static void sn2_patch_itc_freq_ratios(struct ia64_pal_retval *result)
200 {
201  struct pal_freq_ratio *ratio;
202  unsigned long sal_freq, sal_drift, factor;
203 
205  &sal_freq, &sal_drift);
206  ratio = (struct pal_freq_ratio *)&result->v2;
207  factor = ((sal_freq * 3) + (sn_rtc_cycles_per_second / 2)) /
209 
210  ratio->num = 3;
211  ratio->den = factor;
212 }
213 
214 static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
215 {
216  struct ia64_pal_retval result;
217 
218  PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
219 
220  if (vcpu->kvm->arch.is_sn2)
221  sn2_patch_itc_freq_ratios(&result);
222 
223  return result;
224 }
225 
226 static struct ia64_pal_retval pal_logical_to_physica(struct kvm_vcpu *vcpu)
227 {
228  struct ia64_pal_retval result;
229 
231  return result;
232 }
233 
234 static struct ia64_pal_retval pal_platform_addr(struct kvm_vcpu *vcpu)
235 {
236 
237  struct ia64_pal_retval result;
238 
239  INIT_PAL_STATUS_SUCCESS(result);
240  return result;
241 }
242 
243 static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu)
244 {
245 
246  struct ia64_pal_retval result = {0, 0, 0, 0};
247  long in0, in1, in2, in3;
248 
249  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
250  result.status = ia64_pal_proc_get_features(&result.v0, &result.v1,
251  &result.v2, in2);
252 
253  return result;
254 }
255 
256 static struct ia64_pal_retval pal_register_info(struct kvm_vcpu *vcpu)
257 {
258 
259  struct ia64_pal_retval result = {0, 0, 0, 0};
260  long in0, in1, in2, in3;
261 
262  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
263  result.status = ia64_pal_register_info(in1, &result.v1, &result.v2);
264 
265  return result;
266 }
267 
268 static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu)
269 {
270 
272  long status;
273  unsigned long in0, in1, in2, in3, r9, r10;
274 
275  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
276  status = ia64_pal_cache_config_info(in1, in2, &ci);
277  r9 = ci.pcci_info_1.pcci1_data;
278  r10 = ci.pcci_info_2.pcci2_data;
279  return ((struct ia64_pal_retval){status, r9, r10, 0});
280 }
281 
282 #define GUEST_IMPL_VA_MSB 59
283 #define GUEST_RID_BITS 18
284 
285 static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu)
286 {
287 
288  pal_vm_info_1_u_t vminfo1;
289  pal_vm_info_2_u_t vminfo2;
290  struct ia64_pal_retval result;
291 
292  PAL_CALL(result, PAL_VM_SUMMARY, 0, 0, 0);
293  if (!result.status) {
294  vminfo1.pvi1_val = result.v0;
295  vminfo1.pal_vm_info_1_s.max_itr_entry = 8;
296  vminfo1.pal_vm_info_1_s.max_dtr_entry = 8;
297  result.v0 = vminfo1.pvi1_val;
298  vminfo2.pal_vm_info_2_s.impl_va_msb = GUEST_IMPL_VA_MSB;
299  vminfo2.pal_vm_info_2_s.rid_size = GUEST_RID_BITS;
300  result.v1 = vminfo2.pvi2_val;
301  }
302 
303  return result;
304 }
305 
306 static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu)
307 {
308  struct ia64_pal_retval result;
309  unsigned long in0, in1, in2, in3;
310 
311  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
312 
313  result.status = ia64_pal_vm_info(in1, in2,
314  (pal_tc_info_u_t *)&result.v1, &result.v2);
315 
316  return result;
317 }
318 
319 static u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu)
320 {
321  u64 index = 0;
322  struct exit_ctl_data *p;
323 
324  p = kvm_get_exit_data(vcpu);
326  index = p->u.pal_data.gr28;
327 
328  return index;
329 }
330 
331 static void prepare_for_halt(struct kvm_vcpu *vcpu)
332 {
333  vcpu->arch.timer_pending = 1;
334  vcpu->arch.timer_fired = 0;
335 }
336 
337 static struct ia64_pal_retval pal_perf_mon_info(struct kvm_vcpu *vcpu)
338 {
339  long status;
340  unsigned long in0, in1, in2, in3, r9;
341  unsigned long pm_buffer[16];
342 
343  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
344  status = ia64_pal_perf_mon_info(pm_buffer,
345  (pal_perf_mon_info_u_t *) &r9);
346  if (status != 0) {
347  printk(KERN_DEBUG"PAL_PERF_MON_INFO fails ret=%ld\n", status);
348  } else {
349  if (in1)
350  memcpy((void *)in1, pm_buffer, sizeof(pm_buffer));
351  else {
352  status = PAL_STATUS_EINVAL;
353  printk(KERN_WARNING"Invalid parameters "
354  "for PAL call:0x%lx!\n", in0);
355  }
356  }
357  return (struct ia64_pal_retval){status, r9, 0, 0};
358 }
359 
360 static struct ia64_pal_retval pal_halt_info(struct kvm_vcpu *vcpu)
361 {
362  unsigned long in0, in1, in2, in3;
363  long status;
364  unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32)
365  | (1UL << 61) | (1UL << 60);
366 
367  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
368  if (in1) {
369  memcpy((void *)in1, &res, sizeof(res));
370  status = 0;
371  } else{
372  status = PAL_STATUS_EINVAL;
373  printk(KERN_WARNING"Invalid parameters "
374  "for PAL call:0x%lx!\n", in0);
375  }
376 
377  return (struct ia64_pal_retval){status, 0, 0, 0};
378 }
379 
380 static struct ia64_pal_retval pal_mem_attrib(struct kvm_vcpu *vcpu)
381 {
382  unsigned long r9;
383  long status;
384 
385  status = ia64_pal_mem_attrib(&r9);
386 
387  return (struct ia64_pal_retval){status, r9, 0, 0};
388 }
389 
390 static void remote_pal_prefetch_visibility(void *v)
391 {
392  s64 trans_type = (s64)v;
393  ia64_pal_prefetch_visibility(trans_type);
394 }
395 
396 static struct ia64_pal_retval pal_prefetch_visibility(struct kvm_vcpu *vcpu)
397 {
398  struct ia64_pal_retval result = {0, 0, 0, 0};
399  unsigned long in0, in1, in2, in3;
400  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
401  result.status = ia64_pal_prefetch_visibility(in1);
402  if (result.status == 0) {
403  /* Must be performed on all remote processors
404  in the coherence domain. */
405  smp_call_function(remote_pal_prefetch_visibility,
406  (void *)in1, 1);
407  /* Unnecessary on remote processor for other vcpus!*/
408  result.status = 1;
409  }
410  return result;
411 }
412 
413 static void remote_pal_mc_drain(void *v)
414 {
415  ia64_pal_mc_drain();
416 }
417 
418 static struct ia64_pal_retval pal_get_brand_info(struct kvm_vcpu *vcpu)
419 {
420  struct ia64_pal_retval result = {0, 0, 0, 0};
421  unsigned long in0, in1, in2, in3;
422 
423  kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
424 
425  if (in1 == 0 && in2) {
426  char brand_info[128];
427  result.status = ia64_pal_get_brand_info(brand_info);
428  if (result.status == PAL_STATUS_SUCCESS)
429  memcpy((void *)in2, brand_info, 128);
430  } else {
432  printk(KERN_WARNING"Invalid parameters for "
433  "PAL call:0x%lx!\n", in0);
434  }
435 
436  return result;
437 }
438 
439 int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
440 {
441 
442  u64 gr28;
443  struct ia64_pal_retval result;
444  int ret = 1;
445 
446  gr28 = kvm_get_pal_call_index(vcpu);
447  switch (gr28) {
448  case PAL_CACHE_FLUSH:
449  result = pal_cache_flush(vcpu);
450  break;
451  case PAL_MEM_ATTRIB:
452  result = pal_mem_attrib(vcpu);
453  break;
454  case PAL_CACHE_SUMMARY:
455  result = pal_cache_summary(vcpu);
456  break;
457  case PAL_PERF_MON_INFO:
458  result = pal_perf_mon_info(vcpu);
459  break;
460  case PAL_HALT_INFO:
461  result = pal_halt_info(vcpu);
462  break;
463  case PAL_HALT_LIGHT:
464  {
465  INIT_PAL_STATUS_SUCCESS(result);
466  prepare_for_halt(vcpu);
467  if (kvm_highest_pending_irq(vcpu) == -1)
468  ret = kvm_emulate_halt(vcpu);
469  }
470  break;
471 
473  result = pal_prefetch_visibility(vcpu);
474  break;
475  case PAL_MC_DRAIN:
476  result.status = ia64_pal_mc_drain();
477  /* FIXME: All vcpus likely call PAL_MC_DRAIN.
478  That causes the congestion. */
479  smp_call_function(remote_pal_mc_drain, NULL, 1);
480  break;
481 
482  case PAL_FREQ_RATIOS:
483  result = pal_freq_ratios(vcpu);
484  break;
485 
486  case PAL_FREQ_BASE:
487  result = pal_freq_base(vcpu);
488  break;
489 
491  result = pal_logical_to_physica(vcpu);
492  break;
493 
494  case PAL_VM_SUMMARY :
495  result = pal_vm_summary(vcpu);
496  break;
497 
498  case PAL_VM_INFO :
499  result = pal_vm_info(vcpu);
500  break;
501  case PAL_PLATFORM_ADDR :
502  result = pal_platform_addr(vcpu);
503  break;
504  case PAL_CACHE_INFO:
505  result = pal_cache_info(vcpu);
506  break;
507  case PAL_PTCE_INFO:
508  INIT_PAL_STATUS_SUCCESS(result);
509  result.v1 = (1L << 32) | 1L;
510  break;
511  case PAL_REGISTER_INFO:
512  result = pal_register_info(vcpu);
513  break;
514  case PAL_VM_PAGE_SIZE:
515  result.status = ia64_pal_vm_page_size(&result.v0,
516  &result.v1);
517  break;
518  case PAL_RSE_INFO:
519  result.status = ia64_pal_rse_info(&result.v0,
520  (pal_hints_u_t *)&result.v1);
521  break;
523  result = pal_proc_get_features(vcpu);
524  break;
525  case PAL_DEBUG_INFO:
526  result.status = ia64_pal_debug_info(&result.v0,
527  &result.v1);
528  break;
529  case PAL_VERSION:
530  result.status = ia64_pal_version(
531  (pal_version_u_t *)&result.v0,
532  (pal_version_u_t *)&result.v1);
533  break;
534  case PAL_FIXED_ADDR:
535  result.status = PAL_STATUS_SUCCESS;
536  result.v0 = vcpu->vcpu_id;
537  break;
538  case PAL_BRAND_INFO:
539  result = pal_get_brand_info(vcpu);
540  break;
541  case PAL_GET_PSTATE:
544  break;
545  default:
547  printk(KERN_WARNING"kvm: Unsupported pal call,"
548  " index:0x%lx\n", gr28);
549  }
550  set_pal_result(vcpu, result);
551  return ret;
552 }
553 
554 static struct sal_ret_values sal_emulator(struct kvm *kvm,
555  long index, unsigned long in1,
556  unsigned long in2, unsigned long in3,
557  unsigned long in4, unsigned long in5,
558  unsigned long in6, unsigned long in7)
559 {
560  unsigned long r9 = 0;
561  unsigned long r10 = 0;
562  long r11 = 0;
563  long status;
564 
565  status = 0;
566  switch (index) {
567  case SAL_FREQ_BASE:
568  status = ia64_sal_freq_base(in1, &r9, &r10);
569  break;
570  case SAL_PCI_CONFIG_READ:
571  printk(KERN_WARNING"kvm: Not allowed to call here!"
572  " SAL_PCI_CONFIG_READ\n");
573  break;
575  printk(KERN_WARNING"kvm: Not allowed to call here!"
576  " SAL_PCI_CONFIG_WRITE\n");
577  break;
578  case SAL_SET_VECTORS:
579  if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
580  if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) {
581  status = -2;
582  } else {
583  kvm->arch.rdv_sal_data.boot_ip = in2;
584  kvm->arch.rdv_sal_data.boot_gp = in3;
585  }
586  printk("Rendvous called! iip:%lx\n\n", in2);
587  } else
588  printk(KERN_WARNING"kvm: CALLED SAL_SET_VECTORS %lu."
589  "ignored...\n", in1);
590  break;
591  case SAL_GET_STATE_INFO:
592  /* No more info. */
593  status = -5;
594  r9 = 0;
595  break;
597  /* Return a dummy size. */
598  status = 0;
599  r9 = 128;
600  break;
602  /* Noop. */
603  break;
604  case SAL_MC_RENDEZ:
606  "kvm: called SAL_MC_RENDEZ. ignored...\n");
607  break;
608  case SAL_MC_SET_PARAMS:
610  "kvm: called SAL_MC_SET_PARAMS.ignored!\n");
611  break;
612  case SAL_CACHE_FLUSH:
613  if (1) {
614  /*Flush using SAL.
615  This method is faster but has a side
616  effect on other vcpu running on
617  this cpu. */
618  status = ia64_sal_cache_flush(in1);
619  } else {
620  /*Maybe need to implement the method
621  without side effect!*/
622  status = 0;
623  }
624  break;
625  case SAL_CACHE_INIT:
627  "kvm: called SAL_CACHE_INIT. ignored...\n");
628  break;
629  case SAL_UPDATE_PAL:
631  "kvm: CALLED SAL_UPDATE_PAL. ignored...\n");
632  break;
633  default:
634  printk(KERN_WARNING"kvm: called SAL_CALL with unknown index."
635  " index:%ld\n", index);
636  status = -1;
637  break;
638  }
639  return ((struct sal_ret_values) {status, r9, r10, r11});
640 }
641 
642 static void kvm_get_sal_call_data(struct kvm_vcpu *vcpu, u64 *in0, u64 *in1,
643  u64 *in2, u64 *in3, u64 *in4, u64 *in5, u64 *in6, u64 *in7){
644 
645  struct exit_ctl_data *p;
646 
647  p = kvm_get_exit_data(vcpu);
648 
649  if (p->exit_reason == EXIT_REASON_SAL_CALL) {
650  *in0 = p->u.sal_data.in0;
651  *in1 = p->u.sal_data.in1;
652  *in2 = p->u.sal_data.in2;
653  *in3 = p->u.sal_data.in3;
654  *in4 = p->u.sal_data.in4;
655  *in5 = p->u.sal_data.in5;
656  *in6 = p->u.sal_data.in6;
657  *in7 = p->u.sal_data.in7;
658  return ;
659  }
660  *in0 = 0;
661 }
662 
663 void kvm_sal_emul(struct kvm_vcpu *vcpu)
664 {
665 
666  struct sal_ret_values result;
667  u64 index, in1, in2, in3, in4, in5, in6, in7;
668 
669  kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
670  &in3, &in4, &in5, &in6, &in7);
671  result = sal_emulator(vcpu->kvm, index, in1, in2, in3,
672  in4, in5, in6, in7);
673  set_sal_result(vcpu, result);
674 }