qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

spapr_rtas.c (21099B)


      1 /*
      2  * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
      3  *
      4  * Hypercall based emulated RTAS
      5  *
      6  * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a copy
      9  * of this software and associated documentation files (the "Software"), to deal
     10  * in the Software without restriction, including without limitation the rights
     11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12  * copies of the Software, and to permit persons to whom the Software is
     13  * furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     24  * THE SOFTWARE.
     25  *
     26  */
     27 
     28 #include "qemu/osdep.h"
     29 #include "qemu/log.h"
     30 #include "qemu/error-report.h"
     31 #include "sysemu/sysemu.h"
     32 #include "sysemu/device_tree.h"
     33 #include "sysemu/cpus.h"
     34 #include "sysemu/hw_accel.h"
     35 #include "sysemu/runstate.h"
     36 #include "kvm_ppc.h"
     37 
     38 #include "hw/ppc/spapr.h"
     39 #include "hw/ppc/spapr_vio.h"
     40 #include "hw/ppc/spapr_rtas.h"
     41 #include "hw/ppc/spapr_cpu_core.h"
     42 #include "hw/ppc/ppc.h"
     43 
     44 #include <libfdt.h>
     45 #include "hw/ppc/spapr_drc.h"
     46 #include "qemu/cutils.h"
     47 #include "trace.h"
     48 #include "hw/ppc/fdt.h"
     49 #include "target/ppc/mmu-hash64.h"
     50 #include "target/ppc/mmu-book3s-v3.h"
     51 #include "migration/blocker.h"
     52 #include "helper_regs.h"
     53 
     54 static void rtas_display_character(PowerPCCPU *cpu, SpaprMachineState *spapr,
     55                                    uint32_t token, uint32_t nargs,
     56                                    target_ulong args,
     57                                    uint32_t nret, target_ulong rets)
     58 {
     59     uint8_t c = rtas_ld(args, 0);
     60     SpaprVioDevice *sdev = vty_lookup(spapr, 0);
     61 
     62     if (!sdev) {
     63         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
     64     } else {
     65         vty_putchars(sdev, &c, sizeof(c));
     66         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
     67     }
     68 }
     69 
     70 static void rtas_power_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
     71                            uint32_t token, uint32_t nargs, target_ulong args,
     72                            uint32_t nret, target_ulong rets)
     73 {
     74     if (nargs != 2 || nret != 1) {
     75         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
     76         return;
     77     }
     78     qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     79     cpu_stop_current();
     80     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
     81 }
     82 
     83 static void rtas_system_reboot(PowerPCCPU *cpu, SpaprMachineState *spapr,
     84                                uint32_t token, uint32_t nargs,
     85                                target_ulong args,
     86                                uint32_t nret, target_ulong rets)
     87 {
     88     if (nargs != 0 || nret != 1) {
     89         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
     90         return;
     91     }
     92     qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     93     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
     94 }
     95 
     96 static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
     97                                          SpaprMachineState *spapr,
     98                                          uint32_t token, uint32_t nargs,
     99                                          target_ulong args,
    100                                          uint32_t nret, target_ulong rets)
    101 {
    102     target_ulong id;
    103     PowerPCCPU *cpu;
    104 
    105     if (nargs != 1 || nret != 2) {
    106         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    107         return;
    108     }
    109 
    110     id = rtas_ld(args, 0);
    111     cpu = spapr_find_cpu(id);
    112     if (cpu != NULL) {
    113         if (CPU(cpu)->halted) {
    114             rtas_st(rets, 1, 0);
    115         } else {
    116             rtas_st(rets, 1, 2);
    117         }
    118 
    119         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    120         return;
    121     }
    122 
    123     /* Didn't find a matching cpu */
    124     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    125 }
    126 
    127 static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
    128                            uint32_t token, uint32_t nargs,
    129                            target_ulong args,
    130                            uint32_t nret, target_ulong rets)
    131 {
    132     target_ulong id, start, r3;
    133     PowerPCCPU *newcpu;
    134     CPUPPCState *env;
    135     target_ulong lpcr;
    136     target_ulong caller_lpcr;
    137 
    138     if (nargs != 3 || nret != 1) {
    139         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    140         return;
    141     }
    142 
    143     id = rtas_ld(args, 0);
    144     start = rtas_ld(args, 1);
    145     r3 = rtas_ld(args, 2);
    146 
    147     newcpu = spapr_find_cpu(id);
    148     if (!newcpu) {
    149         /* Didn't find a matching cpu */
    150         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    151         return;
    152     }
    153 
    154     env = &newcpu->env;
    155 
    156     if (!CPU(newcpu)->halted) {
    157         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
    158         return;
    159     }
    160 
    161     cpu_synchronize_state(CPU(newcpu));
    162 
    163     env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
    164     hreg_compute_hflags(env);
    165 
    166     caller_lpcr = callcpu->env.spr[SPR_LPCR];
    167     lpcr = env->spr[SPR_LPCR];
    168 
    169     /* Set ILE the same way */
    170     lpcr = (lpcr & ~LPCR_ILE) | (caller_lpcr & LPCR_ILE);
    171 
    172     /* Set AIL the same way */
    173     lpcr = (lpcr & ~LPCR_AIL) | (caller_lpcr & LPCR_AIL);
    174 
    175     if (env->mmu_model == POWERPC_MMU_3_00) {
    176         /*
    177          * New cpus are expected to start in the same radix/hash mode
    178          * as the existing CPUs
    179          */
    180         if (ppc64_v3_radix(callcpu)) {
    181             lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
    182         } else {
    183             lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
    184         }
    185         env->spr[SPR_PSSCR] &= ~PSSCR_EC;
    186     }
    187     ppc_store_lpcr(newcpu, lpcr);
    188 
    189     /*
    190      * Set the timebase offset of the new CPU to that of the invoking
    191      * CPU.  This helps hotplugged CPU to have the correct timebase
    192      * offset.
    193      */
    194     newcpu->env.tb_env->tb_offset = callcpu->env.tb_env->tb_offset;
    195 
    196     spapr_cpu_set_entry_state(newcpu, start, 0, r3, 0);
    197 
    198     qemu_cpu_kick(CPU(newcpu));
    199 
    200     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    201 }
    202 
    203 static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
    204                            uint32_t token, uint32_t nargs,
    205                            target_ulong args,
    206                            uint32_t nret, target_ulong rets)
    207 {
    208     CPUState *cs = CPU(cpu);
    209     CPUPPCState *env = &cpu->env;
    210     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
    211 
    212     /* Disable Power-saving mode Exit Cause exceptions for the CPU.
    213      * This could deliver an interrupt on a dying CPU and crash the
    214      * guest.
    215      * For the same reason, set PSSCR_EC.
    216      */
    217     env->spr[SPR_PSSCR] |= PSSCR_EC;
    218     cs->halted = 1;
    219     ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
    220     kvmppc_set_reg_ppc_online(cpu, 0);
    221     qemu_cpu_kick(cs);
    222 }
    223 
    224 static void rtas_ibm_suspend_me(PowerPCCPU *cpu, SpaprMachineState *spapr,
    225                                 uint32_t token, uint32_t nargs,
    226                                 target_ulong args,
    227                                 uint32_t nret, target_ulong rets)
    228 {
    229     CPUState *cs;
    230 
    231     if (nargs != 0 || nret != 1) {
    232         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    233         return;
    234     }
    235 
    236     CPU_FOREACH(cs) {
    237         PowerPCCPU *c = POWERPC_CPU(cs);
    238         CPUPPCState *e = &c->env;
    239         if (c == cpu) {
    240             continue;
    241         }
    242 
    243         /* See h_join */
    244         if (!cs->halted || (e->msr & (1ULL << MSR_EE))) {
    245             rtas_st(rets, 0, H_MULTI_THREADS_ACTIVE);
    246             return;
    247         }
    248     }
    249 
    250     qemu_system_suspend_request();
    251     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    252 }
    253 
    254 static inline int sysparm_st(target_ulong addr, target_ulong len,
    255                              const void *val, uint16_t vallen)
    256 {
    257     hwaddr phys = ppc64_phys_to_real(addr);
    258 
    259     if (len < 2) {
    260         return RTAS_OUT_SYSPARM_PARAM_ERROR;
    261     }
    262     stw_be_phys(&address_space_memory, phys, vallen);
    263     cpu_physical_memory_write(phys + 2, val, MIN(len - 2, vallen));
    264     return RTAS_OUT_SUCCESS;
    265 }
    266 
    267 static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
    268                                           SpaprMachineState *spapr,
    269                                           uint32_t token, uint32_t nargs,
    270                                           target_ulong args,
    271                                           uint32_t nret, target_ulong rets)
    272 {
    273     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
    274     MachineState *ms = MACHINE(spapr);
    275     target_ulong parameter = rtas_ld(args, 0);
    276     target_ulong buffer = rtas_ld(args, 1);
    277     target_ulong length = rtas_ld(args, 2);
    278     target_ulong ret;
    279 
    280     switch (parameter) {
    281     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
    282         g_autofree char *param_val = g_strdup_printf("MaxEntCap=%d,"
    283                                                      "DesMem=%" PRIu64 ","
    284                                                      "DesProcs=%d,"
    285                                                      "MaxPlatProcs=%d",
    286                                                      ms->smp.max_cpus,
    287                                                      ms->ram_size / MiB,
    288                                                      ms->smp.cpus,
    289                                                      ms->smp.max_cpus);
    290         if (pcc->n_host_threads > 0) {
    291             /*
    292              * Add HostThrs property. This property is not present in PAPR but
    293              * is expected by some guests to communicate the number of physical
    294              * host threads per core on the system so that they can scale
    295              * information which varies based on the thread configuration.
    296              */
    297             g_autofree char *hostthr_val = g_strdup_printf(",HostThrs=%d",
    298                                                            pcc->n_host_threads);
    299             char *old = param_val;
    300 
    301             param_val = g_strconcat(param_val, hostthr_val, NULL);
    302             g_free(old);
    303         }
    304         ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
    305         break;
    306     }
    307     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
    308         uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
    309 
    310         ret = sysparm_st(buffer, length, &param_val, sizeof(param_val));
    311         break;
    312     }
    313     case RTAS_SYSPARM_UUID:
    314         ret = sysparm_st(buffer, length, (unsigned char *)&qemu_uuid,
    315                          (qemu_uuid_set ? 16 : 0));
    316         break;
    317     default:
    318         ret = RTAS_OUT_NOT_SUPPORTED;
    319     }
    320 
    321     rtas_st(rets, 0, ret);
    322 }
    323 
    324 static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
    325                                           SpaprMachineState *spapr,
    326                                           uint32_t token, uint32_t nargs,
    327                                           target_ulong args,
    328                                           uint32_t nret, target_ulong rets)
    329 {
    330     target_ulong parameter = rtas_ld(args, 0);
    331     target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
    332 
    333     switch (parameter) {
    334     case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS:
    335     case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE:
    336     case RTAS_SYSPARM_UUID:
    337         ret = RTAS_OUT_NOT_AUTHORIZED;
    338         break;
    339     }
    340 
    341     rtas_st(rets, 0, ret);
    342 }
    343 
    344 static void rtas_ibm_os_term(PowerPCCPU *cpu,
    345                             SpaprMachineState *spapr,
    346                             uint32_t token, uint32_t nargs,
    347                             target_ulong args,
    348                             uint32_t nret, target_ulong rets)
    349 {
    350     target_ulong msgaddr = rtas_ld(args, 0);
    351     char msg[512];
    352 
    353     cpu_physical_memory_read(msgaddr, msg, sizeof(msg) - 1);
    354     msg[sizeof(msg) - 1] = 0;
    355 
    356     error_report("OS terminated: %s", msg);
    357     qemu_system_guest_panicked(NULL);
    358 
    359     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    360 }
    361 
    362 static void rtas_set_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
    363                                  uint32_t token, uint32_t nargs,
    364                                  target_ulong args, uint32_t nret,
    365                                  target_ulong rets)
    366 {
    367     int32_t power_domain;
    368 
    369     if (nargs != 2 || nret != 2) {
    370         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    371         return;
    372     }
    373 
    374     /* we currently only use a single, "live insert" powerdomain for
    375      * hotplugged/dlpar'd resources, so the power is always live/full (100)
    376      */
    377     power_domain = rtas_ld(args, 0);
    378     if (power_domain != -1) {
    379         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    380         return;
    381     }
    382 
    383     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    384     rtas_st(rets, 1, 100);
    385 }
    386 
    387 static void rtas_get_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
    388                                   uint32_t token, uint32_t nargs,
    389                                   target_ulong args, uint32_t nret,
    390                                   target_ulong rets)
    391 {
    392     int32_t power_domain;
    393 
    394     if (nargs != 1 || nret != 2) {
    395         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    396         return;
    397     }
    398 
    399     /* we currently only use a single, "live insert" powerdomain for
    400      * hotplugged/dlpar'd resources, so the power is always live/full (100)
    401      */
    402     power_domain = rtas_ld(args, 0);
    403     if (power_domain != -1) {
    404         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    405         return;
    406     }
    407 
    408     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    409     rtas_st(rets, 1, 100);
    410 }
    411 
    412 static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
    413                                   SpaprMachineState *spapr,
    414                                   uint32_t token, uint32_t nargs,
    415                                   target_ulong args,
    416                                   uint32_t nret, target_ulong rets)
    417 {
    418     hwaddr rtas_addr;
    419     target_ulong sreset_addr, mce_addr;
    420 
    421     if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
    422         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    423         return;
    424     }
    425 
    426     rtas_addr = spapr_get_rtas_addr();
    427     if (!rtas_addr) {
    428         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    429         return;
    430     }
    431 
    432     sreset_addr = rtas_ld(args, 0);
    433     mce_addr = rtas_ld(args, 1);
    434 
    435     /* PAPR requires these are in the first 32M of memory and within RMA */
    436     if (sreset_addr >= 32 * MiB || sreset_addr >= spapr->rma_size ||
    437            mce_addr >= 32 * MiB ||    mce_addr >= spapr->rma_size) {
    438         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    439         return;
    440     }
    441 
    442     if (kvm_enabled()) {
    443         if (kvmppc_set_fwnmi(cpu) < 0) {
    444             rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    445             return;
    446         }
    447     }
    448 
    449     spapr->fwnmi_system_reset_addr = sreset_addr;
    450     spapr->fwnmi_machine_check_addr = mce_addr;
    451 
    452     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    453 }
    454 
    455 static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
    456                                    SpaprMachineState *spapr,
    457                                    uint32_t token, uint32_t nargs,
    458                                    target_ulong args,
    459                                    uint32_t nret, target_ulong rets)
    460 {
    461     if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
    462         rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
    463         return;
    464     }
    465 
    466     if (spapr->fwnmi_machine_check_addr == -1) {
    467         qemu_log_mask(LOG_GUEST_ERROR,
    468 "FWNMI: ibm,nmi-interlock RTAS called with FWNMI not registered.\n");
    469 
    470         /* NMI register not called */
    471         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    472         return;
    473     }
    474 
    475     if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) {
    476         /*
    477          * The vCPU that hit the NMI should invoke "ibm,nmi-interlock"
    478          * This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock"
    479          * for system reset interrupts, despite them not being interlocked.
    480          * PowerVM silently ignores this and returns success here. Returning
    481          * failure causes Linux to print the error "FWNMI: nmi-interlock
    482          * failed: -3", although no other apparent ill effects, this is a
    483          * regression for the user when enabling FWNMI. So for now, match
    484          * PowerVM. When most Linux clients are fixed, this could be
    485          * changed.
    486          */
    487         rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    488         return;
    489     }
    490 
    491     /*
    492      * vCPU issuing "ibm,nmi-interlock" is done with NMI handling,
    493      * hence unset fwnmi_machine_check_interlock.
    494      */
    495     spapr->fwnmi_machine_check_interlock = -1;
    496     qemu_cond_signal(&spapr->fwnmi_machine_check_interlock_cond);
    497     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
    498     migrate_del_blocker(spapr->fwnmi_migration_blocker);
    499 }
    500 
    501 static struct rtas_call {
    502     const char *name;
    503     spapr_rtas_fn fn;
    504 } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
    505 
    506 target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *spapr,
    507                              uint32_t token, uint32_t nargs, target_ulong args,
    508                              uint32_t nret, target_ulong rets)
    509 {
    510     if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
    511         struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
    512 
    513         if (call->fn) {
    514             call->fn(cpu, spapr, token, nargs, args, nret, rets);
    515             return H_SUCCESS;
    516         }
    517     }
    518 
    519     /* HACK: Some Linux early debug code uses RTAS display-character,
    520      * but assumes the token value is 0xa (which it is on some real
    521      * machines) without looking it up in the device tree.  This
    522      * special case makes this work */
    523     if (token == 0xa) {
    524         rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
    525         return H_SUCCESS;
    526     }
    527 
    528     hcall_dprintf("Unknown RTAS token 0x%x\n", token);
    529     rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
    530     return H_PARAMETER;
    531 }
    532 
    533 uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
    534                          uint32_t nret, uint64_t rets)
    535 {
    536     int token;
    537 
    538     for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) {
    539         if (strcmp(cmd, rtas_table[token].name) == 0) {
    540             SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
    541             PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
    542 
    543             rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE,
    544                                  nargs, args, nret, rets);
    545             return H_SUCCESS;
    546         }
    547     }
    548     return H_PARAMETER;
    549 }
    550 
    551 void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
    552 {
    553     assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
    554 
    555     token -= RTAS_TOKEN_BASE;
    556 
    557     assert(!name || !rtas_table[token].name);
    558 
    559     rtas_table[token].name = name;
    560     rtas_table[token].fn = fn;
    561 }
    562 
    563 void spapr_dt_rtas_tokens(void *fdt, int rtas)
    564 {
    565     int i;
    566 
    567     for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
    568         struct rtas_call *call = &rtas_table[i];
    569 
    570         if (!call->name) {
    571             continue;
    572         }
    573 
    574         _FDT(fdt_setprop_cell(fdt, rtas, call->name, i + RTAS_TOKEN_BASE));
    575     }
    576 }
    577 
    578 hwaddr spapr_get_rtas_addr(void)
    579 {
    580     SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
    581     int rtas_node;
    582     const fdt32_t *rtas_data;
    583     void *fdt = spapr->fdt_blob;
    584 
    585     /* fetch rtas addr from fdt */
    586     rtas_node = fdt_path_offset(fdt, "/rtas");
    587     if (rtas_node < 0) {
    588         return 0;
    589     }
    590 
    591     rtas_data = fdt_getprop(fdt, rtas_node, "linux,rtas-base", NULL);
    592     if (!rtas_data) {
    593         return 0;
    594     }
    595 
    596     /*
    597      * We assume that the OS called RTAS instantiate-rtas, but some other
    598      * OS might call RTAS instantiate-rtas-64 instead. This fine as of now
    599      * as SLOF only supports 32-bit variant.
    600      */
    601     return (hwaddr)fdt32_to_cpu(*rtas_data);
    602 }
    603 
    604 static void core_rtas_register_types(void)
    605 {
    606     spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
    607                         rtas_display_character);
    608     spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
    609     spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
    610                         rtas_system_reboot);
    611     spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
    612                         rtas_query_cpu_stopped_state);
    613     spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
    614     spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
    615     spapr_rtas_register(RTAS_IBM_SUSPEND_ME, "ibm,suspend-me",
    616                         rtas_ibm_suspend_me);
    617     spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
    618                         "ibm,get-system-parameter",
    619                         rtas_ibm_get_system_parameter);
    620     spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
    621                         "ibm,set-system-parameter",
    622                         rtas_ibm_set_system_parameter);
    623     spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
    624                         rtas_ibm_os_term);
    625     spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
    626                         rtas_set_power_level);
    627     spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
    628                         rtas_get_power_level);
    629     spapr_rtas_register(RTAS_IBM_NMI_REGISTER, "ibm,nmi-register",
    630                         rtas_ibm_nmi_register);
    631     spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
    632                         rtas_ibm_nmi_interlock);
    633 }
    634 
    635 type_init(core_rtas_register_types)