qemu

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

spapr_vof.c (4965B)


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