1 #include "sysemu/sysemu.h" 2 #include "cpu.h" 3 #include "sysemu/sysemu.h" 4 #include "helper_regs.h" 5 #include "hw/spapr.h" 6 7 #define HPTES_PER_GROUP 8 8 9 #define HPTE_V_SSIZE_SHIFT 62 10 #define HPTE_V_AVPN_SHIFT 7 11 #define HPTE_V_AVPN 0x3fffffffffffff80ULL 12 #define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) 13 #define HPTE_V_COMPARE(x, y) (!(((x) ^ (y)) & 0xffffffffffffff80UL)) 14 #define HPTE_V_BOLTED 0x0000000000000010ULL 15 #define HPTE_V_LOCK 0x0000000000000008ULL 16 #define HPTE_V_LARGE 0x0000000000000004ULL 17 #define HPTE_V_SECONDARY 0x0000000000000002ULL 18 #define HPTE_V_VALID 0x0000000000000001ULL 19 20 #define HPTE_R_PP0 0x8000000000000000ULL 21 #define HPTE_R_TS 0x4000000000000000ULL 22 #define HPTE_R_KEY_HI 0x3000000000000000ULL 23 #define HPTE_R_RPN_SHIFT 12 24 #define HPTE_R_RPN 0x3ffffffffffff000ULL 25 #define HPTE_R_FLAGS 0x00000000000003ffULL 26 #define HPTE_R_PP 0x0000000000000003ULL 27 #define HPTE_R_N 0x0000000000000004ULL 28 #define HPTE_R_G 0x0000000000000008ULL 29 #define HPTE_R_M 0x0000000000000010ULL 30 #define HPTE_R_I 0x0000000000000020ULL 31 #define HPTE_R_W 0x0000000000000040ULL 32 #define HPTE_R_WIMG 0x0000000000000078ULL 33 #define HPTE_R_C 0x0000000000000080ULL 34 #define HPTE_R_R 0x0000000000000100ULL 35 #define HPTE_R_KEY_LO 0x0000000000000e00ULL 36 37 #define HPTE_V_1TB_SEG 0x4000000000000000ULL 38 #define HPTE_V_VRMA_MASK 0x4001ffffff000000ULL 39 40 static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r, 41 target_ulong pte_index) 42 { 43 target_ulong rb, va_low; 44 45 rb = (v & ~0x7fULL) << 16; /* AVA field */ 46 va_low = pte_index >> 3; 47 if (v & HPTE_V_SECONDARY) { 48 va_low = ~va_low; 49 } 50 /* xor vsid from AVA */ 51 if (!(v & HPTE_V_1TB_SEG)) { 52 va_low ^= v >> 12; 53 } else { 54 va_low ^= v >> 24; 55 } 56 va_low &= 0x7ff; 57 if (v & HPTE_V_LARGE) { 58 rb |= 1; /* L field */ 59 #if 0 /* Disable that P7 specific bit for now */ 60 if (r & 0xff000) { 61 /* non-16MB large page, must be 64k */ 62 /* (masks depend on page size) */ 63 rb |= 0x1000; /* page encoding in LP field */ 64 rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */ 65 rb |= (va_low & 0xfe); /* AVAL field */ 66 } 67 #endif 68 } else { 69 /* 4kB page */ 70 rb |= (va_low & 0x7ff) << 12; /* remaining 11b of AVA */ 71 } 72 rb |= (v >> 54) & 0x300; /* B field */ 73 return rb; 74 } 75 76 static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, 77 target_ulong opcode, target_ulong *args) 78 { 79 CPUPPCState *env = &cpu->env; 80 target_ulong flags = args[0]; 81 target_ulong pte_index = args[1]; 82 target_ulong pteh = args[2]; 83 target_ulong ptel = args[3]; 84 target_ulong page_shift = 12; 85 target_ulong raddr; 86 target_ulong i; 87 uint8_t *hpte; 88 89 /* only handle 4k and 16M pages for now */ 90 if (pteh & HPTE_V_LARGE) { 91 #if 0 /* We don't support 64k pages yet */ 92 if ((ptel & 0xf000) == 0x1000) { 93 /* 64k page */ 94 } else 95 #endif 96 if ((ptel & 0xff000) == 0) { 97 /* 16M page */ 98 page_shift = 24; 99 /* lowest AVA bit must be 0 for 16M pages */ 100 if (pteh & 0x80) { 101 return H_PARAMETER; 102 } 103 } else { 104 return H_PARAMETER; 105 } 106 } 107 108 raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1); 109 110 if (raddr < spapr->ram_limit) { 111 /* Regular RAM - should have WIMG=0010 */ 112 if ((ptel & HPTE_R_WIMG) != HPTE_R_M) { 113 return H_PARAMETER; 114 } 115 } else { 116 /* Looks like an IO address */ 117 /* FIXME: What WIMG combinations could be sensible for IO? 118 * For now we allow WIMG=010x, but are there others? */ 119 /* FIXME: Should we check against registered IO addresses? */ 120 if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) { 121 return H_PARAMETER; 122 } 123 } 124 125 pteh &= ~0x60ULL; 126 127 if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) { 128 return H_PARAMETER; 129 } 130 if (likely((flags & H_EXACT) == 0)) { 131 pte_index &= ~7ULL; 132 hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); 133 for (i = 0; ; ++i) { 134 if (i == 8) { 135 return H_PTEG_FULL; 136 } 137 if ((ldq_p(hpte) & HPTE_V_VALID) == 0) { 138 break; 139 } 140 hpte += HASH_PTE_SIZE_64; 141 } 142 } else { 143 i = 0; 144 hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); 145 if (ldq_p(hpte) & HPTE_V_VALID) { 146 return H_PTEG_FULL; 147 } 148 } 149 stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel); 150 /* eieio(); FIXME: need some sort of barrier for smp? */ 151 stq_p(hpte, pteh); 152 153 args[0] = pte_index + i; 154 return H_SUCCESS; 155 } 156 157 enum { 158 REMOVE_SUCCESS = 0, 159 REMOVE_NOT_FOUND = 1, 160 REMOVE_PARM = 2, 161 REMOVE_HW = 3, 162 }; 163 164 static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, 165 target_ulong avpn, 166 target_ulong flags, 167 target_ulong *vp, target_ulong *rp) 168 { 169 uint8_t *hpte; 170 target_ulong v, r, rb; 171 172 if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) { 173 return REMOVE_PARM; 174 } 175 176 hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64); 177 178 v = ldq_p(hpte); 179 r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); 180 181 if ((v & HPTE_V_VALID) == 0 || 182 ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) || 183 ((flags & H_ANDCOND) && (v & avpn) != 0)) { 184 return REMOVE_NOT_FOUND; 185 } 186 *vp = v; 187 *rp = r; 188 stq_p(hpte, 0); 189 rb = compute_tlbie_rb(v, r, ptex); 190 ppc_tlb_invalidate_one(env, rb); 191 return REMOVE_SUCCESS; 192 } 193 194 static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, 195 target_ulong opcode, target_ulong *args) 196 { 197 CPUPPCState *env = &cpu->env; 198 target_ulong flags = args[0]; 199 target_ulong pte_index = args[1]; 200 target_ulong avpn = args[2]; 201 int ret; 202 203 ret = remove_hpte(env, pte_index, avpn, flags, 204 &args[0], &args[1]); 205 206 switch (ret) { 207 case REMOVE_SUCCESS: 208 return H_SUCCESS; 209 210 case REMOVE_NOT_FOUND: 211 return H_NOT_FOUND; 212 213 case REMOVE_PARM: 214 return H_PARAMETER; 215 216 case REMOVE_HW: 217 return H_HARDWARE; 218 } 219 220 assert(0); 221 } 222 223 #define H_BULK_REMOVE_TYPE 0xc000000000000000ULL 224 #define H_BULK_REMOVE_REQUEST 0x4000000000000000ULL 225 #define H_BULK_REMOVE_RESPONSE 0x8000000000000000ULL 226 #define H_BULK_REMOVE_END 0xc000000000000000ULL 227 #define H_BULK_REMOVE_CODE 0x3000000000000000ULL 228 #define H_BULK_REMOVE_SUCCESS 0x0000000000000000ULL 229 #define H_BULK_REMOVE_NOT_FOUND 0x1000000000000000ULL 230 #define H_BULK_REMOVE_PARM 0x2000000000000000ULL 231 #define H_BULK_REMOVE_HW 0x3000000000000000ULL 232 #define H_BULK_REMOVE_RC 0x0c00000000000000ULL 233 #define H_BULK_REMOVE_FLAGS 0x0300000000000000ULL 234 #define H_BULK_REMOVE_ABSOLUTE 0x0000000000000000ULL 235 #define H_BULK_REMOVE_ANDCOND 0x0100000000000000ULL 236 #define H_BULK_REMOVE_AVPN 0x0200000000000000ULL 237 #define H_BULK_REMOVE_PTEX 0x00ffffffffffffffULL 238 239 #define H_BULK_REMOVE_MAX_BATCH 4 240 241 static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, 242 target_ulong opcode, target_ulong *args) 243 { 244 CPUPPCState *env = &cpu->env; 245 int i; 246 247 for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { 248 target_ulong *tsh = &args[i*2]; 249 target_ulong tsl = args[i*2 + 1]; 250 target_ulong v, r, ret; 251 252 if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) { 253 break; 254 } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) { 255 return H_PARAMETER; 256 } 257 258 *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS; 259 *tsh |= H_BULK_REMOVE_RESPONSE; 260 261 if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) { 262 *tsh |= H_BULK_REMOVE_PARM; 263 return H_PARAMETER; 264 } 265 266 ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl, 267 (*tsh & H_BULK_REMOVE_FLAGS) >> 26, 268 &v, &r); 269 270 *tsh |= ret << 60; 271 272 switch (ret) { 273 case REMOVE_SUCCESS: 274 *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43; 275 break; 276 277 case REMOVE_PARM: 278 return H_PARAMETER; 279 280 case REMOVE_HW: 281 return H_HARDWARE; 282 } 283 } 284 285 return H_SUCCESS; 286 } 287 288 static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr, 289 target_ulong opcode, target_ulong *args) 290 { 291 CPUPPCState *env = &cpu->env; 292 target_ulong flags = args[0]; 293 target_ulong pte_index = args[1]; 294 target_ulong avpn = args[2]; 295 uint8_t *hpte; 296 target_ulong v, r, rb; 297 298 if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) { 299 return H_PARAMETER; 300 } 301 302 hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64); 303 304 v = ldq_p(hpte); 305 r = ldq_p(hpte + (HASH_PTE_SIZE_64/2)); 306 307 if ((v & HPTE_V_VALID) == 0 || 308 ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) { 309 return H_NOT_FOUND; 310 } 311 312 r &= ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N | 313 HPTE_R_KEY_HI | HPTE_R_KEY_LO); 314 r |= (flags << 55) & HPTE_R_PP0; 315 r |= (flags << 48) & HPTE_R_KEY_HI; 316 r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO); 317 rb = compute_tlbie_rb(v, r, pte_index); 318 stq_p(hpte, v & ~HPTE_V_VALID); 319 ppc_tlb_invalidate_one(env, rb); 320 stq_p(hpte + (HASH_PTE_SIZE_64/2), r); 321 /* Don't need a memory barrier, due to qemu's global lock */ 322 stq_p(hpte, v); 323 return H_SUCCESS; 324 } 325 326 static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr, 327 target_ulong opcode, target_ulong *args) 328 { 329 /* FIXME: actually implement this */ 330 return H_HARDWARE; 331 } 332 333 #define FLAGS_REGISTER_VPA 0x0000200000000000ULL 334 #define FLAGS_REGISTER_DTL 0x0000400000000000ULL 335 #define FLAGS_REGISTER_SLBSHADOW 0x0000600000000000ULL 336 #define FLAGS_DEREGISTER_VPA 0x0000a00000000000ULL 337 #define FLAGS_DEREGISTER_DTL 0x0000c00000000000ULL 338 #define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL 339 340 #define VPA_MIN_SIZE 640 341 #define VPA_SIZE_OFFSET 0x4 342 #define VPA_SHARED_PROC_OFFSET 0x9 343 #define VPA_SHARED_PROC_VAL 0x2 344 345 static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa) 346 { 347 uint16_t size; 348 uint8_t tmp; 349 350 if (vpa == 0) { 351 hcall_dprintf("Can't cope with registering a VPA at logical 0\n"); 352 return H_HARDWARE; 353 } 354 355 if (vpa % env->dcache_line_size) { 356 return H_PARAMETER; 357 } 358 /* FIXME: bounds check the address */ 359 360 size = lduw_be_phys(vpa + 0x4); 361 362 if (size < VPA_MIN_SIZE) { 363 return H_PARAMETER; 364 } 365 366 /* VPA is not allowed to cross a page boundary */ 367 if ((vpa / 4096) != ((vpa + size - 1) / 4096)) { 368 return H_PARAMETER; 369 } 370 371 env->vpa_addr = vpa; 372 373 tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET); 374 tmp |= VPA_SHARED_PROC_VAL; 375 stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp); 376 377 return H_SUCCESS; 378 } 379 380 static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa) 381 { 382 if (env->slb_shadow_addr) { 383 return H_RESOURCE; 384 } 385 386 if (env->dtl_addr) { 387 return H_RESOURCE; 388 } 389 390 env->vpa_addr = 0; 391 return H_SUCCESS; 392 } 393 394 static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr) 395 { 396 uint32_t size; 397 398 if (addr == 0) { 399 hcall_dprintf("Can't cope with SLB shadow at logical 0\n"); 400 return H_HARDWARE; 401 } 402 403 size = ldl_be_phys(addr + 0x4); 404 if (size < 0x8) { 405 return H_PARAMETER; 406 } 407 408 if ((addr / 4096) != ((addr + size - 1) / 4096)) { 409 return H_PARAMETER; 410 } 411 412 if (!env->vpa_addr) { 413 return H_RESOURCE; 414 } 415 416 env->slb_shadow_addr = addr; 417 env->slb_shadow_size = size; 418 419 return H_SUCCESS; 420 } 421 422 static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr) 423 { 424 env->slb_shadow_addr = 0; 425 env->slb_shadow_size = 0; 426 return H_SUCCESS; 427 } 428 429 static target_ulong register_dtl(CPUPPCState *env, target_ulong addr) 430 { 431 uint32_t size; 432 433 if (addr == 0) { 434 hcall_dprintf("Can't cope with DTL at logical 0\n"); 435 return H_HARDWARE; 436 } 437 438 size = ldl_be_phys(addr + 0x4); 439 440 if (size < 48) { 441 return H_PARAMETER; 442 } 443 444 if (!env->vpa_addr) { 445 return H_RESOURCE; 446 } 447 448 env->dtl_addr = addr; 449 env->dtl_size = size; 450 451 return H_SUCCESS; 452 } 453 454 static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr) 455 { 456 env->dtl_addr = 0; 457 env->dtl_size = 0; 458 459 return H_SUCCESS; 460 } 461 462 static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPREnvironment *spapr, 463 target_ulong opcode, target_ulong *args) 464 { 465 target_ulong flags = args[0]; 466 target_ulong procno = args[1]; 467 target_ulong vpa = args[2]; 468 target_ulong ret = H_PARAMETER; 469 CPUPPCState *tenv; 470 CPUState *tcpu; 471 472 tcpu = qemu_get_cpu(procno); 473 if (!tcpu) { 474 return H_PARAMETER; 475 } 476 tenv = tcpu->env_ptr; 477 478 switch (flags) { 479 case FLAGS_REGISTER_VPA: 480 ret = register_vpa(tenv, vpa); 481 break; 482 483 case FLAGS_DEREGISTER_VPA: 484 ret = deregister_vpa(tenv, vpa); 485 break; 486 487 case FLAGS_REGISTER_SLBSHADOW: 488 ret = register_slb_shadow(tenv, vpa); 489 break; 490 491 case FLAGS_DEREGISTER_SLBSHADOW: 492 ret = deregister_slb_shadow(tenv, vpa); 493 break; 494 495 case FLAGS_REGISTER_DTL: 496 ret = register_dtl(tenv, vpa); 497 break; 498 499 case FLAGS_DEREGISTER_DTL: 500 ret = deregister_dtl(tenv, vpa); 501 break; 502 } 503 504 return ret; 505 } 506 507 static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr, 508 target_ulong opcode, target_ulong *args) 509 { 510 CPUPPCState *env = &cpu->env; 511 CPUState *cs = CPU(cpu); 512 513 env->msr |= (1ULL << MSR_EE); 514 hreg_compute_hflags(env); 515 if (!cpu_has_work(cs)) { 516 env->halted = 1; 517 env->exception_index = EXCP_HLT; 518 cs->exit_request = 1; 519 } 520 return H_SUCCESS; 521 } 522 523 static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr, 524 target_ulong opcode, target_ulong *args) 525 { 526 target_ulong rtas_r3 = args[0]; 527 uint32_t token = ldl_be_phys(rtas_r3); 528 uint32_t nargs = ldl_be_phys(rtas_r3 + 4); 529 uint32_t nret = ldl_be_phys(rtas_r3 + 8); 530 531 return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12, 532 nret, rtas_r3 + 12 + 4*nargs); 533 } 534 535 static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr, 536 target_ulong opcode, target_ulong *args) 537 { 538 target_ulong size = args[0]; 539 target_ulong addr = args[1]; 540 541 switch (size) { 542 case 1: 543 args[0] = ldub_phys(addr); 544 return H_SUCCESS; 545 case 2: 546 args[0] = lduw_phys(addr); 547 return H_SUCCESS; 548 case 4: 549 args[0] = ldl_phys(addr); 550 return H_SUCCESS; 551 case 8: 552 args[0] = ldq_phys(addr); 553 return H_SUCCESS; 554 } 555 return H_PARAMETER; 556 } 557 558 static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, 559 target_ulong opcode, target_ulong *args) 560 { 561 target_ulong size = args[0]; 562 target_ulong addr = args[1]; 563 target_ulong val = args[2]; 564 565 switch (size) { 566 case 1: 567 stb_phys(addr, val); 568 return H_SUCCESS; 569 case 2: 570 stw_phys(addr, val); 571 return H_SUCCESS; 572 case 4: 573 stl_phys(addr, val); 574 return H_SUCCESS; 575 case 8: 576 stq_phys(addr, val); 577 return H_SUCCESS; 578 } 579 return H_PARAMETER; 580 } 581 582 static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr, 583 target_ulong opcode, target_ulong *args) 584 { 585 target_ulong dst = args[0]; /* Destination address */ 586 target_ulong src = args[1]; /* Source address */ 587 target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */ 588 target_ulong count = args[3]; /* Element count */ 589 target_ulong op = args[4]; /* 0 = copy, 1 = invert */ 590 uint64_t tmp; 591 unsigned int mask = (1 << esize) - 1; 592 int step = 1 << esize; 593 594 if (count > 0x80000000) { 595 return H_PARAMETER; 596 } 597 598 if ((dst & mask) || (src & mask) || (op > 1)) { 599 return H_PARAMETER; 600 } 601 602 if (dst >= src && dst < (src + (count << esize))) { 603 dst = dst + ((count - 1) << esize); 604 src = src + ((count - 1) << esize); 605 step = -step; 606 } 607 608 while (count--) { 609 switch (esize) { 610 case 0: 611 tmp = ldub_phys(src); 612 break; 613 case 1: 614 tmp = lduw_phys(src); 615 break; 616 case 2: 617 tmp = ldl_phys(src); 618 break; 619 case 3: 620 tmp = ldq_phys(src); 621 break; 622 default: 623 return H_PARAMETER; 624 } 625 if (op == 1) { 626 tmp = ~tmp; 627 } 628 switch (esize) { 629 case 0: 630 stb_phys(dst, tmp); 631 break; 632 case 1: 633 stw_phys(dst, tmp); 634 break; 635 case 2: 636 stl_phys(dst, tmp); 637 break; 638 case 3: 639 stq_phys(dst, tmp); 640 break; 641 } 642 dst = dst + step; 643 src = src + step; 644 } 645 646 return H_SUCCESS; 647 } 648 649 static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr, 650 target_ulong opcode, target_ulong *args) 651 { 652 /* Nothing to do on emulation, KVM will trap this in the kernel */ 653 return H_SUCCESS; 654 } 655 656 static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr, 657 target_ulong opcode, target_ulong *args) 658 { 659 /* Nothing to do on emulation, KVM will trap this in the kernel */ 660 return H_SUCCESS; 661 } 662 663 static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; 664 static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1]; 665 666 void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn) 667 { 668 spapr_hcall_fn *slot; 669 670 if (opcode <= MAX_HCALL_OPCODE) { 671 assert((opcode & 0x3) == 0); 672 673 slot = &papr_hypercall_table[opcode / 4]; 674 } else { 675 assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX)); 676 677 slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE]; 678 } 679 680 assert(!(*slot)); 681 *slot = fn; 682 } 683 684 target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, 685 target_ulong *args) 686 { 687 if ((opcode <= MAX_HCALL_OPCODE) 688 && ((opcode & 0x3) == 0)) { 689 spapr_hcall_fn fn = papr_hypercall_table[opcode / 4]; 690 691 if (fn) { 692 return fn(cpu, spapr, opcode, args); 693 } 694 } else if ((opcode >= KVMPPC_HCALL_BASE) && 695 (opcode <= KVMPPC_HCALL_MAX)) { 696 spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE]; 697 698 if (fn) { 699 return fn(cpu, spapr, opcode, args); 700 } 701 } 702 703 hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode); 704 return H_FUNCTION; 705 } 706 707 static void hypercall_register_types(void) 708 { 709 /* hcall-pft */ 710 spapr_register_hypercall(H_ENTER, h_enter); 711 spapr_register_hypercall(H_REMOVE, h_remove); 712 spapr_register_hypercall(H_PROTECT, h_protect); 713 714 /* hcall-bulk */ 715 spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove); 716 717 /* hcall-dabr */ 718 spapr_register_hypercall(H_SET_DABR, h_set_dabr); 719 720 /* hcall-splpar */ 721 spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa); 722 spapr_register_hypercall(H_CEDE, h_cede); 723 724 /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate 725 * here between the "CI" and the "CACHE" variants, they will use whatever 726 * mapping attributes qemu is using. When using KVM, the kernel will 727 * enforce the attributes more strongly 728 */ 729 spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load); 730 spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store); 731 spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load); 732 spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store); 733 spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi); 734 spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf); 735 spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop); 736 737 /* qemu/KVM-PPC specific hcalls */ 738 spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); 739 } 740 741 type_init(hypercall_register_types) 742