1/* 2 * PAL/SAL call delegation 3 * 4 * Copyright (c) 2004 Li Susie <susie.li@intel.com> 5 * Copyright (c) 2005 Yu Ke <ke.yu@intel.com> 6 * Copyright (c) 2007 Xiantao Zhang <xiantao.zhang@intel.com> 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 55static 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; 61 if (p->exit_reason == EXIT_REASON_PAL_CALL) { 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 72static 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); 78 if (p->exit_reason == EXIT_REASON_PAL_CALL) { 79 p->u.pal_data.ret = result; 80 return ; 81 } 82 INIT_PAL_STATUS_UNIMPLEMENTED(p->u.pal_data.ret); 83} 84 85static 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); 90 if (p->exit_reason == EXIT_REASON_SAL_CALL) { 91 p->u.sal_data.ret = result; 92 return ; 93 } 94 printk(KERN_WARNING"Failed to set sal result!!\n"); 95} 96 97struct cache_flush_args { 98 u64 cache_type; 99 u64 operation; 100 u64 progress; 101 long status; 102}; 103 104cpumask_t cpu_cache_coherent_map; 105 106static 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 118static 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 164struct ia64_pal_retval pal_cache_summary(struct kvm_vcpu *vcpu) 165{ 166 167 struct ia64_pal_retval result; 168 169 PAL_CALL(result, PAL_CACHE_SUMMARY, 0, 0, 0); 170 return result; 171} 172 173static 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) { 185 result.status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, 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 */ 199static 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 204 result->status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, 205 &sal_freq, &sal_drift); 206 ratio = (struct pal_freq_ratio *)&result->v2; 207 factor = ((sal_freq * 3) + (sn_rtc_cycles_per_second / 2)) / 208 sn_rtc_cycles_per_second; 209 210 ratio->num = 3; 211 ratio->den = factor; 212} 213 214static 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 226static struct ia64_pal_retval pal_logical_to_physica(struct kvm_vcpu *vcpu) 227{ 228 struct ia64_pal_retval result; 229 230 INIT_PAL_STATUS_UNIMPLEMENTED(result); 231 return result; 232} 233 234static 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 243static 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 256static 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 268static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu) 269{ 270 271 pal_cache_config_info_t ci; 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 285static 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 306static 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 319static 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); 325 if (p->exit_reason == EXIT_REASON_PAL_CALL) 326 index = p->u.pal_data.gr28; 327 328 return index; 329} 330 331static void prepare_for_halt(struct kvm_vcpu *vcpu) 332{ 333 vcpu->arch.timer_pending = 1; 334 vcpu->arch.timer_fired = 0; 335} 336 337static 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 360static 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 380static 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 390static void remote_pal_prefetch_visibility(void *v) 391{ 392 s64 trans_type = (s64)v; 393 ia64_pal_prefetch_visibility(trans_type); 394} 395 396static 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 413static void remote_pal_mc_drain(void *v) 414{ 415 ia64_pal_mc_drain(); 416} 417 418static 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 { 431 result.status = PAL_STATUS_REQUIRES_MEMORY; 432 printk(KERN_WARNING"Invalid parameters for " 433 "PAL call:0x%lx!\n", in0); 434 } 435 436 return result; 437} 438 439int 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 472 case PAL_PREFETCH_VISIBILITY: 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 490 case PAL_LOGICAL_TO_PHYSICAL : 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; 522 case PAL_PROC_GET_FEATURES: 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: 542 case PAL_CACHE_SHARED_INFO: 543 INIT_PAL_STATUS_UNIMPLEMENTED(result); 544 break; 545 default: 546 INIT_PAL_STATUS_UNIMPLEMENTED(result); 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 554static 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; 574 case SAL_PCI_CONFIG_WRITE: 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; 596 case SAL_GET_STATE_INFO_SIZE: 597 /* Return a dummy size. */ 598 status = 0; 599 r9 = 128; 600 break; 601 case SAL_CLEAR_STATE_INFO: 602 /* Noop. */ 603 break; 604 case SAL_MC_RENDEZ: 605 printk(KERN_WARNING 606 "kvm: called SAL_MC_RENDEZ. ignored...\n"); 607 break; 608 case SAL_MC_SET_PARAMS: 609 printk(KERN_WARNING 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: 626 printk(KERN_WARNING 627 "kvm: called SAL_CACHE_INIT. ignored...\n"); 628 break; 629 case SAL_UPDATE_PAL: 630 printk(KERN_WARNING 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 642static 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 663void 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} 675