qemu/hw/ppc/spapr_hcall.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "qapi/error.h"
   3#include "sysemu/sysemu.h"
   4#include "qemu/log.h"
   5#include "cpu.h"
   6#include "exec/exec-all.h"
   7#include "helper_regs.h"
   8#include "hw/ppc/spapr.h"
   9#include "mmu-hash64.h"
  10#include "cpu-models.h"
  11#include "trace.h"
  12#include "sysemu/kvm.h"
  13#include "kvm_ppc.h"
  14
  15struct SPRSyncState {
  16    CPUState *cs;
  17    int spr;
  18    target_ulong value;
  19    target_ulong mask;
  20};
  21
  22static void do_spr_sync(void *arg)
  23{
  24    struct SPRSyncState *s = arg;
  25    PowerPCCPU *cpu = POWERPC_CPU(s->cs);
  26    CPUPPCState *env = &cpu->env;
  27
  28    cpu_synchronize_state(s->cs);
  29    env->spr[s->spr] &= ~s->mask;
  30    env->spr[s->spr] |= s->value;
  31}
  32
  33static void set_spr(CPUState *cs, int spr, target_ulong value,
  34                    target_ulong mask)
  35{
  36    struct SPRSyncState s = {
  37        .cs = cs,
  38        .spr = spr,
  39        .value = value,
  40        .mask = mask
  41    };
  42    run_on_cpu(cs, do_spr_sync, &s);
  43}
  44
  45static bool has_spr(PowerPCCPU *cpu, int spr)
  46{
  47    /* We can test whether the SPR is defined by checking for a valid name */
  48    return cpu->env.spr_cb[spr].name != NULL;
  49}
  50
  51static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
  52{
  53    /*
  54     * hash value/pteg group index is normalized by htab_mask
  55     */
  56    if (((pte_index & ~7ULL) / HPTES_PER_GROUP) & ~env->htab_mask) {
  57        return false;
  58    }
  59    return true;
  60}
  61
  62static bool is_ram_address(sPAPRMachineState *spapr, hwaddr addr)
  63{
  64    MachineState *machine = MACHINE(spapr);
  65    MemoryHotplugState *hpms = &spapr->hotplug_memory;
  66
  67    if (addr < machine->ram_size) {
  68        return true;
  69    }
  70    if ((addr >= hpms->base)
  71        && ((addr - hpms->base) < memory_region_size(&hpms->mr))) {
  72        return true;
  73    }
  74
  75    return false;
  76}
  77
  78static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
  79                            target_ulong opcode, target_ulong *args)
  80{
  81    CPUPPCState *env = &cpu->env;
  82    target_ulong flags = args[0];
  83    target_ulong pte_index = args[1];
  84    target_ulong pteh = args[2];
  85    target_ulong ptel = args[3];
  86    unsigned apshift;
  87    target_ulong raddr;
  88    target_ulong index;
  89    uint64_t token;
  90
  91    apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel);
  92    if (!apshift) {
  93        /* Bad page size encoding */
  94        return H_PARAMETER;
  95    }
  96
  97    raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << apshift) - 1);
  98
  99    if (is_ram_address(spapr, raddr)) {
 100        /* Regular RAM - should have WIMG=0010 */
 101        if ((ptel & HPTE64_R_WIMG) != HPTE64_R_M) {
 102            return H_PARAMETER;
 103        }
 104    } else {
 105        target_ulong wimg_flags;
 106        /* Looks like an IO address */
 107        /* FIXME: What WIMG combinations could be sensible for IO?
 108         * For now we allow WIMG=010x, but are there others? */
 109        /* FIXME: Should we check against registered IO addresses? */
 110        wimg_flags = (ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M));
 111
 112        if (wimg_flags != HPTE64_R_I &&
 113            wimg_flags != (HPTE64_R_I | HPTE64_R_M)) {
 114            return H_PARAMETER;
 115        }
 116    }
 117
 118    pteh &= ~0x60ULL;
 119
 120    if (!valid_pte_index(env, pte_index)) {
 121        return H_PARAMETER;
 122    }
 123
 124    index = 0;
 125    if (likely((flags & H_EXACT) == 0)) {
 126        pte_index &= ~7ULL;
 127        token = ppc_hash64_start_access(cpu, pte_index);
 128        for (; index < 8; index++) {
 129            if (!(ppc_hash64_load_hpte0(cpu, token, index) & HPTE64_V_VALID)) {
 130                break;
 131            }
 132        }
 133        ppc_hash64_stop_access(cpu, token);
 134        if (index == 8) {
 135            return H_PTEG_FULL;
 136        }
 137    } else {
 138        token = ppc_hash64_start_access(cpu, pte_index);
 139        if (ppc_hash64_load_hpte0(cpu, token, 0) & HPTE64_V_VALID) {
 140            ppc_hash64_stop_access(cpu, token);
 141            return H_PTEG_FULL;
 142        }
 143        ppc_hash64_stop_access(cpu, token);
 144    }
 145
 146    ppc_hash64_store_hpte(cpu, pte_index + index,
 147                          pteh | HPTE64_V_HPTE_DIRTY, ptel);
 148
 149    args[0] = pte_index + index;
 150    return H_SUCCESS;
 151}
 152
 153typedef enum {
 154    REMOVE_SUCCESS = 0,
 155    REMOVE_NOT_FOUND = 1,
 156    REMOVE_PARM = 2,
 157    REMOVE_HW = 3,
 158} RemoveResult;
 159
 160static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
 161                                target_ulong avpn,
 162                                target_ulong flags,
 163                                target_ulong *vp, target_ulong *rp)
 164{
 165    CPUPPCState *env = &cpu->env;
 166    uint64_t token;
 167    target_ulong v, r;
 168
 169    if (!valid_pte_index(env, ptex)) {
 170        return REMOVE_PARM;
 171    }
 172
 173    token = ppc_hash64_start_access(cpu, ptex);
 174    v = ppc_hash64_load_hpte0(cpu, token, 0);
 175    r = ppc_hash64_load_hpte1(cpu, token, 0);
 176    ppc_hash64_stop_access(cpu, token);
 177
 178    if ((v & HPTE64_V_VALID) == 0 ||
 179        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
 180        ((flags & H_ANDCOND) && (v & avpn) != 0)) {
 181        return REMOVE_NOT_FOUND;
 182    }
 183    *vp = v;
 184    *rp = r;
 185    ppc_hash64_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0);
 186    ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r);
 187    return REMOVE_SUCCESS;
 188}
 189
 190static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 191                             target_ulong opcode, target_ulong *args)
 192{
 193    CPUPPCState *env = &cpu->env;
 194    target_ulong flags = args[0];
 195    target_ulong pte_index = args[1];
 196    target_ulong avpn = args[2];
 197    RemoveResult ret;
 198
 199    ret = remove_hpte(cpu, pte_index, avpn, flags,
 200                      &args[0], &args[1]);
 201
 202    switch (ret) {
 203    case REMOVE_SUCCESS:
 204        check_tlb_flush(env);
 205        return H_SUCCESS;
 206
 207    case REMOVE_NOT_FOUND:
 208        return H_NOT_FOUND;
 209
 210    case REMOVE_PARM:
 211        return H_PARAMETER;
 212
 213    case REMOVE_HW:
 214        return H_HARDWARE;
 215    }
 216
 217    g_assert_not_reached();
 218}
 219
 220#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
 221#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
 222#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
 223#define   H_BULK_REMOVE_END            0xc000000000000000ULL
 224#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
 225#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
 226#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
 227#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
 228#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
 229#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
 230#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
 231#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
 232#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
 233#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
 234#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
 235
 236#define H_BULK_REMOVE_MAX_BATCH        4
 237
 238static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 239                                  target_ulong opcode, target_ulong *args)
 240{
 241    CPUPPCState *env = &cpu->env;
 242    int i;
 243    target_ulong rc = H_SUCCESS;
 244
 245    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
 246        target_ulong *tsh = &args[i*2];
 247        target_ulong tsl = args[i*2 + 1];
 248        target_ulong v, r, ret;
 249
 250        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
 251            break;
 252        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
 253            return H_PARAMETER;
 254        }
 255
 256        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
 257        *tsh |= H_BULK_REMOVE_RESPONSE;
 258
 259        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
 260            *tsh |= H_BULK_REMOVE_PARM;
 261            return H_PARAMETER;
 262        }
 263
 264        ret = remove_hpte(cpu, *tsh & H_BULK_REMOVE_PTEX, tsl,
 265                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
 266                          &v, &r);
 267
 268        *tsh |= ret << 60;
 269
 270        switch (ret) {
 271        case REMOVE_SUCCESS:
 272            *tsh |= (r & (HPTE64_R_C | HPTE64_R_R)) << 43;
 273            break;
 274
 275        case REMOVE_PARM:
 276            rc = H_PARAMETER;
 277            goto exit;
 278
 279        case REMOVE_HW:
 280            rc = H_HARDWARE;
 281            goto exit;
 282        }
 283    }
 284 exit:
 285    check_tlb_flush(env);
 286
 287    return rc;
 288}
 289
 290static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 291                              target_ulong opcode, target_ulong *args)
 292{
 293    CPUPPCState *env = &cpu->env;
 294    target_ulong flags = args[0];
 295    target_ulong pte_index = args[1];
 296    target_ulong avpn = args[2];
 297    uint64_t token;
 298    target_ulong v, r;
 299
 300    if (!valid_pte_index(env, pte_index)) {
 301        return H_PARAMETER;
 302    }
 303
 304    token = ppc_hash64_start_access(cpu, pte_index);
 305    v = ppc_hash64_load_hpte0(cpu, token, 0);
 306    r = ppc_hash64_load_hpte1(cpu, token, 0);
 307    ppc_hash64_stop_access(cpu, token);
 308
 309    if ((v & HPTE64_V_VALID) == 0 ||
 310        ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
 311        return H_NOT_FOUND;
 312    }
 313
 314    r &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N |
 315           HPTE64_R_KEY_HI | HPTE64_R_KEY_LO);
 316    r |= (flags << 55) & HPTE64_R_PP0;
 317    r |= (flags << 48) & HPTE64_R_KEY_HI;
 318    r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
 319    ppc_hash64_store_hpte(cpu, pte_index,
 320                          (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
 321    ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r);
 322    /* Don't need a memory barrier, due to qemu's global lock */
 323    ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
 324    return H_SUCCESS;
 325}
 326
 327static target_ulong h_read(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 328                           target_ulong opcode, target_ulong *args)
 329{
 330    CPUPPCState *env = &cpu->env;
 331    target_ulong flags = args[0];
 332    target_ulong pte_index = args[1];
 333    uint8_t *hpte;
 334    int i, ridx, n_entries = 1;
 335
 336    if (!valid_pte_index(env, pte_index)) {
 337        return H_PARAMETER;
 338    }
 339
 340    if (flags & H_READ_4) {
 341        /* Clear the two low order bits */
 342        pte_index &= ~(3ULL);
 343        n_entries = 4;
 344    }
 345
 346    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
 347
 348    for (i = 0, ridx = 0; i < n_entries; i++) {
 349        args[ridx++] = ldq_p(hpte);
 350        args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
 351        hpte += HASH_PTE_SIZE_64;
 352    }
 353
 354    return H_SUCCESS;
 355}
 356
 357static target_ulong h_set_sprg0(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 358                                target_ulong opcode, target_ulong *args)
 359{
 360    cpu_synchronize_state(CPU(cpu));
 361    cpu->env.spr[SPR_SPRG0] = args[0];
 362
 363    return H_SUCCESS;
 364}
 365
 366static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 367                               target_ulong opcode, target_ulong *args)
 368{
 369    if (!has_spr(cpu, SPR_DABR)) {
 370        return H_HARDWARE;              /* DABR register not available */
 371    }
 372    cpu_synchronize_state(CPU(cpu));
 373
 374    if (has_spr(cpu, SPR_DABRX)) {
 375        cpu->env.spr[SPR_DABRX] = 0x3;  /* Use Problem and Privileged state */
 376    } else if (!(args[0] & 0x4)) {      /* Breakpoint Translation set? */
 377        return H_RESERVED_DABR;
 378    }
 379
 380    cpu->env.spr[SPR_DABR] = args[0];
 381    return H_SUCCESS;
 382}
 383
 384static target_ulong h_set_xdabr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 385                                target_ulong opcode, target_ulong *args)
 386{
 387    target_ulong dabrx = args[1];
 388
 389    if (!has_spr(cpu, SPR_DABR) || !has_spr(cpu, SPR_DABRX)) {
 390        return H_HARDWARE;
 391    }
 392
 393    if ((dabrx & ~0xfULL) != 0 || (dabrx & H_DABRX_HYPERVISOR) != 0
 394        || (dabrx & (H_DABRX_KERNEL | H_DABRX_USER)) == 0) {
 395        return H_PARAMETER;
 396    }
 397
 398    cpu_synchronize_state(CPU(cpu));
 399    cpu->env.spr[SPR_DABRX] = dabrx;
 400    cpu->env.spr[SPR_DABR] = args[0];
 401
 402    return H_SUCCESS;
 403}
 404
 405static target_ulong h_page_init(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 406                                target_ulong opcode, target_ulong *args)
 407{
 408    target_ulong flags = args[0];
 409    hwaddr dst = args[1];
 410    hwaddr src = args[2];
 411    hwaddr len = TARGET_PAGE_SIZE;
 412    uint8_t *pdst, *psrc;
 413    target_long ret = H_SUCCESS;
 414
 415    if (flags & ~(H_ICACHE_SYNCHRONIZE | H_ICACHE_INVALIDATE
 416                  | H_COPY_PAGE | H_ZERO_PAGE)) {
 417        qemu_log_mask(LOG_UNIMP, "h_page_init: Bad flags (" TARGET_FMT_lx "\n",
 418                      flags);
 419        return H_PARAMETER;
 420    }
 421
 422    /* Map-in destination */
 423    if (!is_ram_address(spapr, dst) || (dst & ~TARGET_PAGE_MASK) != 0) {
 424        return H_PARAMETER;
 425    }
 426    pdst = cpu_physical_memory_map(dst, &len, 1);
 427    if (!pdst || len != TARGET_PAGE_SIZE) {
 428        return H_PARAMETER;
 429    }
 430
 431    if (flags & H_COPY_PAGE) {
 432        /* Map-in source, copy to destination, and unmap source again */
 433        if (!is_ram_address(spapr, src) || (src & ~TARGET_PAGE_MASK) != 0) {
 434            ret = H_PARAMETER;
 435            goto unmap_out;
 436        }
 437        psrc = cpu_physical_memory_map(src, &len, 0);
 438        if (!psrc || len != TARGET_PAGE_SIZE) {
 439            ret = H_PARAMETER;
 440            goto unmap_out;
 441        }
 442        memcpy(pdst, psrc, len);
 443        cpu_physical_memory_unmap(psrc, len, 0, len);
 444    } else if (flags & H_ZERO_PAGE) {
 445        memset(pdst, 0, len);          /* Just clear the destination page */
 446    }
 447
 448    if (kvm_enabled() && (flags & H_ICACHE_SYNCHRONIZE) != 0) {
 449        kvmppc_dcbst_range(cpu, pdst, len);
 450    }
 451    if (flags & (H_ICACHE_SYNCHRONIZE | H_ICACHE_INVALIDATE)) {
 452        if (kvm_enabled()) {
 453            kvmppc_icbi_range(cpu, pdst, len);
 454        } else {
 455            tb_flush(CPU(cpu));
 456        }
 457    }
 458
 459unmap_out:
 460    cpu_physical_memory_unmap(pdst, TARGET_PAGE_SIZE, 1, len);
 461    return ret;
 462}
 463
 464#define FLAGS_REGISTER_VPA         0x0000200000000000ULL
 465#define FLAGS_REGISTER_DTL         0x0000400000000000ULL
 466#define FLAGS_REGISTER_SLBSHADOW   0x0000600000000000ULL
 467#define FLAGS_DEREGISTER_VPA       0x0000a00000000000ULL
 468#define FLAGS_DEREGISTER_DTL       0x0000c00000000000ULL
 469#define FLAGS_DEREGISTER_SLBSHADOW 0x0000e00000000000ULL
 470
 471#define VPA_MIN_SIZE           640
 472#define VPA_SIZE_OFFSET        0x4
 473#define VPA_SHARED_PROC_OFFSET 0x9
 474#define VPA_SHARED_PROC_VAL    0x2
 475
 476static target_ulong register_vpa(CPUPPCState *env, target_ulong vpa)
 477{
 478    CPUState *cs = CPU(ppc_env_get_cpu(env));
 479    uint16_t size;
 480    uint8_t tmp;
 481
 482    if (vpa == 0) {
 483        hcall_dprintf("Can't cope with registering a VPA at logical 0\n");
 484        return H_HARDWARE;
 485    }
 486
 487    if (vpa % env->dcache_line_size) {
 488        return H_PARAMETER;
 489    }
 490    /* FIXME: bounds check the address */
 491
 492    size = lduw_be_phys(cs->as, vpa + 0x4);
 493
 494    if (size < VPA_MIN_SIZE) {
 495        return H_PARAMETER;
 496    }
 497
 498    /* VPA is not allowed to cross a page boundary */
 499    if ((vpa / 4096) != ((vpa + size - 1) / 4096)) {
 500        return H_PARAMETER;
 501    }
 502
 503    env->vpa_addr = vpa;
 504
 505    tmp = ldub_phys(cs->as, env->vpa_addr + VPA_SHARED_PROC_OFFSET);
 506    tmp |= VPA_SHARED_PROC_VAL;
 507    stb_phys(cs->as, env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
 508
 509    return H_SUCCESS;
 510}
 511
 512static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
 513{
 514    if (env->slb_shadow_addr) {
 515        return H_RESOURCE;
 516    }
 517
 518    if (env->dtl_addr) {
 519        return H_RESOURCE;
 520    }
 521
 522    env->vpa_addr = 0;
 523    return H_SUCCESS;
 524}
 525
 526static target_ulong register_slb_shadow(CPUPPCState *env, target_ulong addr)
 527{
 528    CPUState *cs = CPU(ppc_env_get_cpu(env));
 529    uint32_t size;
 530
 531    if (addr == 0) {
 532        hcall_dprintf("Can't cope with SLB shadow at logical 0\n");
 533        return H_HARDWARE;
 534    }
 535
 536    size = ldl_be_phys(cs->as, addr + 0x4);
 537    if (size < 0x8) {
 538        return H_PARAMETER;
 539    }
 540
 541    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
 542        return H_PARAMETER;
 543    }
 544
 545    if (!env->vpa_addr) {
 546        return H_RESOURCE;
 547    }
 548
 549    env->slb_shadow_addr = addr;
 550    env->slb_shadow_size = size;
 551
 552    return H_SUCCESS;
 553}
 554
 555static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
 556{
 557    env->slb_shadow_addr = 0;
 558    env->slb_shadow_size = 0;
 559    return H_SUCCESS;
 560}
 561
 562static target_ulong register_dtl(CPUPPCState *env, target_ulong addr)
 563{
 564    CPUState *cs = CPU(ppc_env_get_cpu(env));
 565    uint32_t size;
 566
 567    if (addr == 0) {
 568        hcall_dprintf("Can't cope with DTL at logical 0\n");
 569        return H_HARDWARE;
 570    }
 571
 572    size = ldl_be_phys(cs->as, addr + 0x4);
 573
 574    if (size < 48) {
 575        return H_PARAMETER;
 576    }
 577
 578    if (!env->vpa_addr) {
 579        return H_RESOURCE;
 580    }
 581
 582    env->dtl_addr = addr;
 583    env->dtl_size = size;
 584
 585    return H_SUCCESS;
 586}
 587
 588static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
 589{
 590    env->dtl_addr = 0;
 591    env->dtl_size = 0;
 592
 593    return H_SUCCESS;
 594}
 595
 596static target_ulong h_register_vpa(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 597                                   target_ulong opcode, target_ulong *args)
 598{
 599    target_ulong flags = args[0];
 600    target_ulong procno = args[1];
 601    target_ulong vpa = args[2];
 602    target_ulong ret = H_PARAMETER;
 603    CPUPPCState *tenv;
 604    PowerPCCPU *tcpu;
 605
 606    tcpu = ppc_get_vcpu_by_dt_id(procno);
 607    if (!tcpu) {
 608        return H_PARAMETER;
 609    }
 610    tenv = &tcpu->env;
 611
 612    switch (flags) {
 613    case FLAGS_REGISTER_VPA:
 614        ret = register_vpa(tenv, vpa);
 615        break;
 616
 617    case FLAGS_DEREGISTER_VPA:
 618        ret = deregister_vpa(tenv, vpa);
 619        break;
 620
 621    case FLAGS_REGISTER_SLBSHADOW:
 622        ret = register_slb_shadow(tenv, vpa);
 623        break;
 624
 625    case FLAGS_DEREGISTER_SLBSHADOW:
 626        ret = deregister_slb_shadow(tenv, vpa);
 627        break;
 628
 629    case FLAGS_REGISTER_DTL:
 630        ret = register_dtl(tenv, vpa);
 631        break;
 632
 633    case FLAGS_DEREGISTER_DTL:
 634        ret = deregister_dtl(tenv, vpa);
 635        break;
 636    }
 637
 638    return ret;
 639}
 640
 641static target_ulong h_cede(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 642                           target_ulong opcode, target_ulong *args)
 643{
 644    CPUPPCState *env = &cpu->env;
 645    CPUState *cs = CPU(cpu);
 646
 647    env->msr |= (1ULL << MSR_EE);
 648    hreg_compute_hflags(env);
 649    if (!cpu_has_work(cs)) {
 650        cs->halted = 1;
 651        cs->exception_index = EXCP_HLT;
 652        cs->exit_request = 1;
 653    }
 654    return H_SUCCESS;
 655}
 656
 657static target_ulong h_rtas(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 658                           target_ulong opcode, target_ulong *args)
 659{
 660    target_ulong rtas_r3 = args[0];
 661    uint32_t token = rtas_ld(rtas_r3, 0);
 662    uint32_t nargs = rtas_ld(rtas_r3, 1);
 663    uint32_t nret = rtas_ld(rtas_r3, 2);
 664
 665    return spapr_rtas_call(cpu, spapr, token, nargs, rtas_r3 + 12,
 666                           nret, rtas_r3 + 12 + 4*nargs);
 667}
 668
 669static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 670                                   target_ulong opcode, target_ulong *args)
 671{
 672    CPUState *cs = CPU(cpu);
 673    target_ulong size = args[0];
 674    target_ulong addr = args[1];
 675
 676    switch (size) {
 677    case 1:
 678        args[0] = ldub_phys(cs->as, addr);
 679        return H_SUCCESS;
 680    case 2:
 681        args[0] = lduw_phys(cs->as, addr);
 682        return H_SUCCESS;
 683    case 4:
 684        args[0] = ldl_phys(cs->as, addr);
 685        return H_SUCCESS;
 686    case 8:
 687        args[0] = ldq_phys(cs->as, addr);
 688        return H_SUCCESS;
 689    }
 690    return H_PARAMETER;
 691}
 692
 693static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 694                                    target_ulong opcode, target_ulong *args)
 695{
 696    CPUState *cs = CPU(cpu);
 697
 698    target_ulong size = args[0];
 699    target_ulong addr = args[1];
 700    target_ulong val  = args[2];
 701
 702    switch (size) {
 703    case 1:
 704        stb_phys(cs->as, addr, val);
 705        return H_SUCCESS;
 706    case 2:
 707        stw_phys(cs->as, addr, val);
 708        return H_SUCCESS;
 709    case 4:
 710        stl_phys(cs->as, addr, val);
 711        return H_SUCCESS;
 712    case 8:
 713        stq_phys(cs->as, addr, val);
 714        return H_SUCCESS;
 715    }
 716    return H_PARAMETER;
 717}
 718
 719static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 720                                    target_ulong opcode, target_ulong *args)
 721{
 722    CPUState *cs = CPU(cpu);
 723
 724    target_ulong dst   = args[0]; /* Destination address */
 725    target_ulong src   = args[1]; /* Source address */
 726    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
 727    target_ulong count = args[3]; /* Element count */
 728    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
 729    uint64_t tmp;
 730    unsigned int mask = (1 << esize) - 1;
 731    int step = 1 << esize;
 732
 733    if (count > 0x80000000) {
 734        return H_PARAMETER;
 735    }
 736
 737    if ((dst & mask) || (src & mask) || (op > 1)) {
 738        return H_PARAMETER;
 739    }
 740
 741    if (dst >= src && dst < (src + (count << esize))) {
 742            dst = dst + ((count - 1) << esize);
 743            src = src + ((count - 1) << esize);
 744            step = -step;
 745    }
 746
 747    while (count--) {
 748        switch (esize) {
 749        case 0:
 750            tmp = ldub_phys(cs->as, src);
 751            break;
 752        case 1:
 753            tmp = lduw_phys(cs->as, src);
 754            break;
 755        case 2:
 756            tmp = ldl_phys(cs->as, src);
 757            break;
 758        case 3:
 759            tmp = ldq_phys(cs->as, src);
 760            break;
 761        default:
 762            return H_PARAMETER;
 763        }
 764        if (op == 1) {
 765            tmp = ~tmp;
 766        }
 767        switch (esize) {
 768        case 0:
 769            stb_phys(cs->as, dst, tmp);
 770            break;
 771        case 1:
 772            stw_phys(cs->as, dst, tmp);
 773            break;
 774        case 2:
 775            stl_phys(cs->as, dst, tmp);
 776            break;
 777        case 3:
 778            stq_phys(cs->as, dst, tmp);
 779            break;
 780        }
 781        dst = dst + step;
 782        src = src + step;
 783    }
 784
 785    return H_SUCCESS;
 786}
 787
 788static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 789                                   target_ulong opcode, target_ulong *args)
 790{
 791    /* Nothing to do on emulation, KVM will trap this in the kernel */
 792    return H_SUCCESS;
 793}
 794
 795static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 796                                   target_ulong opcode, target_ulong *args)
 797{
 798    /* Nothing to do on emulation, KVM will trap this in the kernel */
 799    return H_SUCCESS;
 800}
 801
 802static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
 803                                           target_ulong mflags,
 804                                           target_ulong value1,
 805                                           target_ulong value2)
 806{
 807    CPUState *cs;
 808
 809    if (value1) {
 810        return H_P3;
 811    }
 812    if (value2) {
 813        return H_P4;
 814    }
 815
 816    switch (mflags) {
 817    case H_SET_MODE_ENDIAN_BIG:
 818        CPU_FOREACH(cs) {
 819            set_spr(cs, SPR_LPCR, 0, LPCR_ILE);
 820        }
 821        spapr_pci_switch_vga(true);
 822        return H_SUCCESS;
 823
 824    case H_SET_MODE_ENDIAN_LITTLE:
 825        CPU_FOREACH(cs) {
 826            set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE);
 827        }
 828        spapr_pci_switch_vga(false);
 829        return H_SUCCESS;
 830    }
 831
 832    return H_UNSUPPORTED_FLAG;
 833}
 834
 835static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
 836                                                        target_ulong mflags,
 837                                                        target_ulong value1,
 838                                                        target_ulong value2)
 839{
 840    CPUState *cs;
 841    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
 842
 843    if (!(pcc->insns_flags2 & PPC2_ISA207S)) {
 844        return H_P2;
 845    }
 846    if (value1) {
 847        return H_P3;
 848    }
 849    if (value2) {
 850        return H_P4;
 851    }
 852
 853    if (mflags == AIL_RESERVED) {
 854        return H_UNSUPPORTED_FLAG;
 855    }
 856
 857    CPU_FOREACH(cs) {
 858        set_spr(cs, SPR_LPCR, mflags << LPCR_AIL_SHIFT, LPCR_AIL);
 859    }
 860
 861    return H_SUCCESS;
 862}
 863
 864static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr,
 865                               target_ulong opcode, target_ulong *args)
 866{
 867    target_ulong resource = args[1];
 868    target_ulong ret = H_P2;
 869
 870    switch (resource) {
 871    case H_SET_MODE_RESOURCE_LE:
 872        ret = h_set_mode_resource_le(cpu, args[0], args[2], args[3]);
 873        break;
 874    case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
 875        ret = h_set_mode_resource_addr_trans_mode(cpu, args[0],
 876                                                  args[2], args[3]);
 877        break;
 878    }
 879
 880    return ret;
 881}
 882
 883/*
 884 * Return the offset to the requested option vector @vector in the
 885 * option vector table @table.
 886 */
 887static target_ulong cas_get_option_vector(int vector, target_ulong table)
 888{
 889    int i;
 890    char nr_vectors, nr_entries;
 891
 892    if (!table) {
 893        return 0;
 894    }
 895
 896    nr_vectors = (ldl_phys(&address_space_memory, table) >> 24) + 1;
 897    if (!vector || vector > nr_vectors) {
 898        return 0;
 899    }
 900    table++; /* skip nr option vectors */
 901
 902    for (i = 0; i < vector - 1; i++) {
 903        nr_entries = ldl_phys(&address_space_memory, table) >> 24;
 904        table += nr_entries + 2;
 905    }
 906    return table;
 907}
 908
 909typedef struct {
 910    PowerPCCPU *cpu;
 911    uint32_t cpu_version;
 912    Error *err;
 913} SetCompatState;
 914
 915static void do_set_compat(void *arg)
 916{
 917    SetCompatState *s = arg;
 918
 919    cpu_synchronize_state(CPU(s->cpu));
 920    ppc_set_compat(s->cpu, s->cpu_version, &s->err);
 921}
 922
 923#define get_compat_level(cpuver) ( \
 924    ((cpuver) == CPU_POWERPC_LOGICAL_2_05) ? 2050 : \
 925    ((cpuver) == CPU_POWERPC_LOGICAL_2_06) ? 2060 : \
 926    ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
 927    ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
 928
 929static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr,
 930                                  unsigned max_lvl, unsigned *compat_lvl,
 931                                  unsigned *cpu_version)
 932{
 933    unsigned lvl = get_compat_level(pvr);
 934    bool is205, is206, is207;
 935
 936    if (!lvl) {
 937        return;
 938    }
 939
 940    /* If it is a logical PVR, try to determine the highest level */
 941    is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) &&
 942            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
 943    is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) &&
 944            ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
 945             (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
 946    is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) &&
 947            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07));
 948
 949    if (is205 || is206 || is207) {
 950        if (!max_lvl) {
 951            /* User did not set the level, choose the highest */
 952            if (*compat_lvl <= lvl) {
 953                *compat_lvl = lvl;
 954                *cpu_version = pvr;
 955            }
 956        } else if (max_lvl >= lvl) {
 957            /* User chose the level, don't set higher than this */
 958            *compat_lvl = lvl;
 959            *cpu_version = pvr;
 960        }
 961    }
 962}
 963
 964#define OV5_DRCONF_MEMORY 0x20
 965
 966static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
 967                                                  sPAPRMachineState *spapr,
 968                                                  target_ulong opcode,
 969                                                  target_ulong *args)
 970{
 971    target_ulong list = ppc64_phys_to_real(args[0]);
 972    target_ulong ov_table, ov5;
 973    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_);
 974    CPUState *cs;
 975    bool cpu_match = false, cpu_update = true, memory_update = false;
 976    unsigned old_cpu_version = cpu_->cpu_version;
 977    unsigned compat_lvl = 0, cpu_version = 0;
 978    unsigned max_lvl = get_compat_level(cpu_->max_compat);
 979    int counter;
 980    char ov5_byte2;
 981
 982    /* Parse PVR list */
 983    for (counter = 0; counter < 512; ++counter) {
 984        uint32_t pvr, pvr_mask;
 985
 986        pvr_mask = ldl_be_phys(&address_space_memory, list);
 987        list += 4;
 988        pvr = ldl_be_phys(&address_space_memory, list);
 989        list += 4;
 990
 991        trace_spapr_cas_pvr_try(pvr);
 992        if (!max_lvl &&
 993            ((cpu_->env.spr[SPR_PVR] & pvr_mask) == (pvr & pvr_mask))) {
 994            cpu_match = true;
 995            cpu_version = 0;
 996        } else if (pvr == cpu_->cpu_version) {
 997            cpu_match = true;
 998            cpu_version = cpu_->cpu_version;
 999        } else if (!cpu_match) {
1000            cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version);
1001        }
1002        /* Terminator record */
1003        if (~pvr_mask & pvr) {
1004            break;
1005        }
1006    }
1007
1008    /* Parsing finished */
1009    trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
1010                        cpu_version, pcc->pcr_mask);
1011
1012    /* Update CPUs */
1013    if (old_cpu_version != cpu_version) {
1014        CPU_FOREACH(cs) {
1015            SetCompatState s = {
1016                .cpu = POWERPC_CPU(cs),
1017                .cpu_version = cpu_version,
1018                .err = NULL,
1019            };
1020
1021            run_on_cpu(cs, do_set_compat, &s);
1022
1023            if (s.err) {
1024                error_report_err(s.err);
1025                return H_HARDWARE;
1026            }
1027        }
1028    }
1029
1030    if (!cpu_version) {
1031        cpu_update = false;
1032    }
1033
1034    /* For the future use: here @ov_table points to the first option vector */
1035    ov_table = list;
1036
1037    ov5 = cas_get_option_vector(5, ov_table);
1038    if (!ov5) {
1039        return H_SUCCESS;
1040    }
1041
1042    /* @list now points to OV 5 */
1043    ov5_byte2 = ldub_phys(&address_space_memory, ov5 + 2);
1044    if (ov5_byte2 & OV5_DRCONF_MEMORY) {
1045        memory_update = true;
1046    }
1047
1048    if (spapr_h_cas_compose_response(spapr, args[1], args[2],
1049                                     cpu_update, memory_update)) {
1050        qemu_system_reset_request();
1051    }
1052
1053    return H_SUCCESS;
1054}
1055
1056static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
1057static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
1058
1059void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
1060{
1061    spapr_hcall_fn *slot;
1062
1063    if (opcode <= MAX_HCALL_OPCODE) {
1064        assert((opcode & 0x3) == 0);
1065
1066        slot = &papr_hypercall_table[opcode / 4];
1067    } else {
1068        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
1069
1070        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
1071    }
1072
1073    assert(!(*slot));
1074    *slot = fn;
1075}
1076
1077target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
1078                             target_ulong *args)
1079{
1080    sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
1081
1082    if ((opcode <= MAX_HCALL_OPCODE)
1083        && ((opcode & 0x3) == 0)) {
1084        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
1085
1086        if (fn) {
1087            return fn(cpu, spapr, opcode, args);
1088        }
1089    } else if ((opcode >= KVMPPC_HCALL_BASE) &&
1090               (opcode <= KVMPPC_HCALL_MAX)) {
1091        spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
1092
1093        if (fn) {
1094            return fn(cpu, spapr, opcode, args);
1095        }
1096    }
1097
1098    qemu_log_mask(LOG_UNIMP, "Unimplemented SPAPR hcall 0x" TARGET_FMT_lx "\n",
1099                  opcode);
1100    return H_FUNCTION;
1101}
1102
1103static void hypercall_register_types(void)
1104{
1105    /* hcall-pft */
1106    spapr_register_hypercall(H_ENTER, h_enter);
1107    spapr_register_hypercall(H_REMOVE, h_remove);
1108    spapr_register_hypercall(H_PROTECT, h_protect);
1109    spapr_register_hypercall(H_READ, h_read);
1110
1111    /* hcall-bulk */
1112    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
1113
1114    /* hcall-splpar */
1115    spapr_register_hypercall(H_REGISTER_VPA, h_register_vpa);
1116    spapr_register_hypercall(H_CEDE, h_cede);
1117
1118    /* processor register resource access h-calls */
1119    spapr_register_hypercall(H_SET_SPRG0, h_set_sprg0);
1120    spapr_register_hypercall(H_SET_DABR, h_set_dabr);
1121    spapr_register_hypercall(H_SET_XDABR, h_set_xdabr);
1122    spapr_register_hypercall(H_PAGE_INIT, h_page_init);
1123    spapr_register_hypercall(H_SET_MODE, h_set_mode);
1124
1125    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
1126     * here between the "CI" and the "CACHE" variants, they will use whatever
1127     * mapping attributes qemu is using. When using KVM, the kernel will
1128     * enforce the attributes more strongly
1129     */
1130    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
1131    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
1132    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
1133    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
1134    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
1135    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
1136    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
1137
1138    /* qemu/KVM-PPC specific hcalls */
1139    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
1140
1141    /* ibm,client-architecture-support support */
1142    spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
1143}
1144
1145type_init(hypercall_register_types)
1146