cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

spapr_vof.c (5106B)


      1/*
      2 * SPAPR machine hooks to Virtual Open Firmware,
      3 *
      4 * SPDX-License-Identifier: GPL-2.0-or-later
      5 */
      6#include "qemu/osdep.h"
      7#include "qemu-common.h"
      8#include "qapi/error.h"
      9#include "hw/ppc/spapr.h"
     10#include "hw/ppc/spapr_vio.h"
     11#include "hw/ppc/spapr_cpu_core.h"
     12#include "hw/ppc/fdt.h"
     13#include "hw/ppc/vof.h"
     14#include "sysemu/sysemu.h"
     15#include "qom/qom-qobject.h"
     16#include "trace.h"
     17
     18target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
     19                                target_ulong opcode, target_ulong *_args)
     20{
     21    int ret = vof_client_call(MACHINE(spapr), spapr->vof, spapr->fdt_blob,
     22                              ppc64_phys_to_real(_args[0]));
     23
     24    if (ret) {
     25        return H_PARAMETER;
     26    }
     27    return H_SUCCESS;
     28}
     29
     30void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
     31{
     32    char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
     33
     34    vof_build_dt(fdt, spapr->vof);
     35
     36    if (spapr->vof->bootargs) {
     37        int chosen;
     38
     39        _FDT(chosen = fdt_path_offset(fdt, "/chosen"));
     40        /*
     41         * If the client did not change "bootargs", spapr_dt_chosen() must have
     42         * stored machine->kernel_cmdline in it before getting here.
     43         */
     44        _FDT(fdt_setprop_string(fdt, chosen, "bootargs", spapr->vof->bootargs));
     45    }
     46
     47    /*
     48     * SLOF-less setup requires an open instance of stdout for early
     49     * kernel printk. By now all phandles are settled so we can open
     50     * the default serial console.
     51     */
     52    if (stdout_path) {
     53        _FDT(vof_client_open_store(fdt, spapr->vof, "/chosen", "stdout",
     54                                   stdout_path));
     55    }
     56}
     57
     58void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp)
     59{
     60    target_ulong stack_ptr;
     61    Vof *vof = spapr->vof;
     62    PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
     63
     64    vof_init(vof, spapr->rma_size, errp);
     65
     66    stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE);
     67    if (stack_ptr == -1) {
     68        error_setg(errp, "Memory allocation for stack failed");
     69        return;
     70    }
     71    /* Stack grows downwards plus reserve space for the minimum stack frame */
     72    stack_ptr += VOF_STACK_SIZE - 0x20;
     73
     74    if (spapr->kernel_size &&
     75        vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) {
     76        error_setg(errp, "Memory for kernel is in use");
     77        return;
     78    }
     79
     80    if (spapr->initrd_size &&
     81        vof_claim(vof, spapr->initrd_base, spapr->initrd_size, 0) == -1) {
     82        error_setg(errp, "Memory for initramdisk is in use");
     83        return;
     84    }
     85
     86    spapr_vof_client_dt_finalize(spapr, fdt);
     87
     88    spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
     89                              stack_ptr, spapr->initrd_base,
     90                              spapr->initrd_size);
     91    /* VOF is 32bit BE so enforce MSR here */
     92    first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE));
     93
     94    /*
     95     * At this point the expected allocation map is:
     96     *
     97     * 0..c38 - the initial firmware
     98     * 8000..10000 - stack
     99     * 400000.. - kernel
    100     * 3ea0000.. - initramdisk
    101     *
    102     * We skip writing FDT as nothing expects it; OF client interface is
    103     * going to be used for reading the device tree.
    104     */
    105}
    106
    107void spapr_vof_quiesce(MachineState *ms)
    108{
    109    SpaprMachineState *spapr = SPAPR_MACHINE(ms);
    110
    111    spapr->fdt_size = fdt_totalsize(spapr->fdt_blob);
    112    spapr->fdt_initial_size = spapr->fdt_size;
    113}
    114
    115bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname,
    116                       void *val, int vallen)
    117{
    118    SpaprMachineState *spapr = SPAPR_MACHINE(ms);
    119
    120    /*
    121     * We only allow changing properties which we know how to update in QEMU
    122     * OR
    123     * the ones which we know that they need to survive during "quiesce".
    124     */
    125
    126    if (strcmp(path, "/rtas") == 0) {
    127        if (strcmp(propname, "linux,rtas-base") == 0 ||
    128            strcmp(propname, "linux,rtas-entry") == 0) {
    129            /* These need to survive quiesce so let them store in the FDT */
    130            return true;
    131        }
    132    }
    133
    134    if (strcmp(path, "/chosen") == 0) {
    135        if (strcmp(propname, "bootargs") == 0) {
    136            Vof *vof = spapr->vof;
    137
    138            g_free(vof->bootargs);
    139            vof->bootargs = g_strndup(val, vallen);
    140            return true;
    141        }
    142        if (strcmp(propname, "linux,initrd-start") == 0) {
    143            if (vallen == sizeof(uint32_t)) {
    144                spapr->initrd_base = ldl_be_p(val);
    145                return true;
    146            }
    147            if (vallen == sizeof(uint64_t)) {
    148                spapr->initrd_base = ldq_be_p(val);
    149                return true;
    150            }
    151            return false;
    152        }
    153        if (strcmp(propname, "linux,initrd-end") == 0) {
    154            if (vallen == sizeof(uint32_t)) {
    155                spapr->initrd_size = ldl_be_p(val) - spapr->initrd_base;
    156                return true;
    157            }
    158            if (vallen == sizeof(uint64_t)) {
    159                spapr->initrd_size = ldq_be_p(val) - spapr->initrd_base;
    160                return true;
    161            }
    162            return false;
    163        }
    164    }
    165
    166    return true;
    167}