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

pc_sysfw.c (9261B)


      1/*
      2 * QEMU PC System Firmware
      3 *
      4 * Copyright (c) 2003-2004 Fabrice Bellard
      5 * Copyright (c) 2011-2012 Intel Corporation
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 */
     25
     26#include "qemu/osdep.h"
     27#include "qemu-common.h"
     28#include "qapi/error.h"
     29#include "sysemu/block-backend.h"
     30#include "qemu/error-report.h"
     31#include "qemu/option.h"
     32#include "qemu/units.h"
     33#include "hw/sysbus.h"
     34#include "hw/i386/x86.h"
     35#include "hw/i386/pc.h"
     36#include "hw/loader.h"
     37#include "hw/qdev-properties.h"
     38#include "hw/block/flash.h"
     39#include "sysemu/kvm.h"
     40#include "sysemu/sev.h"
     41
     42#define FLASH_SECTOR_SIZE 4096
     43
     44static void pc_isa_bios_init(MemoryRegion *rom_memory,
     45                             MemoryRegion *flash_mem,
     46                             int ram_size)
     47{
     48    int isa_bios_size;
     49    MemoryRegion *isa_bios;
     50    uint64_t flash_size;
     51    void *flash_ptr, *isa_bios_ptr;
     52
     53    flash_size = memory_region_size(flash_mem);
     54
     55    /* map the last 128KB of the BIOS in ISA space */
     56    isa_bios_size = MIN(flash_size, 128 * KiB);
     57    isa_bios = g_malloc(sizeof(*isa_bios));
     58    memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
     59                           &error_fatal);
     60    memory_region_add_subregion_overlap(rom_memory,
     61                                        0x100000 - isa_bios_size,
     62                                        isa_bios,
     63                                        1);
     64
     65    /* copy ISA rom image from top of flash memory */
     66    flash_ptr = memory_region_get_ram_ptr(flash_mem);
     67    isa_bios_ptr = memory_region_get_ram_ptr(isa_bios);
     68    memcpy(isa_bios_ptr,
     69           ((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
     70           isa_bios_size);
     71
     72    memory_region_set_readonly(isa_bios, true);
     73}
     74
     75static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms,
     76                                     const char *name,
     77                                     const char *alias_prop_name)
     78{
     79    DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
     80
     81    qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE);
     82    qdev_prop_set_uint8(dev, "width", 1);
     83    qdev_prop_set_string(dev, "name", name);
     84    object_property_add_child(OBJECT(pcms), name, OBJECT(dev));
     85    object_property_add_alias(OBJECT(pcms), alias_prop_name,
     86                              OBJECT(dev), "drive");
     87    /*
     88     * The returned reference is tied to the child property and
     89     * will be removed with object_unparent.
     90     */
     91    object_unref(OBJECT(dev));
     92    return PFLASH_CFI01(dev);
     93}
     94
     95void pc_system_flash_create(PCMachineState *pcms)
     96{
     97    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     98
     99    if (pcmc->pci_enabled) {
    100        pcms->flash[0] = pc_pflash_create(pcms, "system.flash0",
    101                                          "pflash0");
    102        pcms->flash[1] = pc_pflash_create(pcms, "system.flash1",
    103                                          "pflash1");
    104    }
    105}
    106
    107void pc_system_flash_cleanup_unused(PCMachineState *pcms)
    108{
    109    char *prop_name;
    110    int i;
    111    Object *dev_obj;
    112
    113    assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
    114
    115    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
    116        dev_obj = OBJECT(pcms->flash[i]);
    117        if (!object_property_get_bool(dev_obj, "realized", &error_abort)) {
    118            prop_name = g_strdup_printf("pflash%d", i);
    119            object_property_del(OBJECT(pcms), prop_name);
    120            g_free(prop_name);
    121            object_unparent(dev_obj);
    122            pcms->flash[i] = NULL;
    123        }
    124    }
    125}
    126
    127/*
    128 * Map the pcms->flash[] from 4GiB downward, and realize.
    129 * Map them in descending order, i.e. pcms->flash[0] at the top,
    130 * without gaps.
    131 * Stop at the first pcms->flash[0] lacking a block backend.
    132 * Set each flash's size from its block backend.  Fatal error if the
    133 * size isn't a non-zero multiple of 4KiB, or the total size exceeds
    134 * pcms->max_fw_size.
    135 *
    136 * If pcms->flash[0] has a block backend, its memory is passed to
    137 * pc_isa_bios_init().  Merging several flash devices for isa-bios is
    138 * not supported.
    139 */
    140static void pc_system_flash_map(PCMachineState *pcms,
    141                                MemoryRegion *rom_memory)
    142{
    143    hwaddr total_size = 0;
    144    int i;
    145    BlockBackend *blk;
    146    int64_t size;
    147    PFlashCFI01 *system_flash;
    148    MemoryRegion *flash_mem;
    149    void *flash_ptr;
    150    int flash_size;
    151    int ret;
    152    hwaddr gpa;
    153
    154    assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
    155
    156    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
    157        system_flash = pcms->flash[i];
    158        blk = pflash_cfi01_get_blk(system_flash);
    159        if (!blk) {
    160            break;
    161        }
    162        size = blk_getlength(blk);
    163        if (size < 0) {
    164            error_report("can't get size of block device %s: %s",
    165                         blk_name(blk), strerror(-size));
    166            exit(1);
    167        }
    168        if (size == 0 || !QEMU_IS_ALIGNED(size, FLASH_SECTOR_SIZE)) {
    169            error_report("system firmware block device %s has invalid size "
    170                         "%" PRId64,
    171                         blk_name(blk), size);
    172            info_report("its size must be a non-zero multiple of 0x%x",
    173                        FLASH_SECTOR_SIZE);
    174            exit(1);
    175        }
    176        if ((hwaddr)size != size
    177            || total_size > HWADDR_MAX - size
    178            || total_size + size > pcms->max_fw_size) {
    179            error_report("combined size of system firmware exceeds "
    180                         "%" PRIu64 " bytes",
    181                         pcms->max_fw_size);
    182            exit(1);
    183        }
    184
    185        total_size += size;
    186        gpa = 0x100000000ULL - total_size; /* where the flash is mapped */
    187        qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks",
    188                             size / FLASH_SECTOR_SIZE);
    189        sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal);
    190        sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, gpa);
    191
    192        if (i == 0) {
    193            flash_mem = pflash_cfi01_get_memory(system_flash);
    194            pc_isa_bios_init(rom_memory, flash_mem, size);
    195
    196            /* Encrypt the pflash boot ROM */
    197            if (sev_enabled()) {
    198                flash_ptr = memory_region_get_ram_ptr(flash_mem);
    199                flash_size = memory_region_size(flash_mem);
    200                /*
    201                 * OVMF places a GUIDed structures in the flash, so
    202                 * search for them
    203                 */
    204                pc_system_parse_ovmf_flash(flash_ptr, flash_size);
    205
    206                ret = sev_es_save_reset_vector(flash_ptr, flash_size);
    207                if (ret) {
    208                    error_report("failed to locate and/or save reset vector");
    209                    exit(1);
    210                }
    211
    212                sev_encrypt_flash(gpa, flash_ptr, flash_size, &error_fatal);
    213            }
    214        }
    215    }
    216}
    217
    218void pc_system_firmware_init(PCMachineState *pcms,
    219                             MemoryRegion *rom_memory)
    220{
    221    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
    222    int i;
    223    BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
    224
    225    if (!pcmc->pci_enabled) {
    226        x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, true);
    227        return;
    228    }
    229
    230    /* Map legacy -drive if=pflash to machine properties */
    231    for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
    232        pflash_cfi01_legacy_drive(pcms->flash[i],
    233                                  drive_get(IF_PFLASH, 0, i));
    234        pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
    235    }
    236
    237    /* Reject gaps */
    238    for (i = 1; i < ARRAY_SIZE(pcms->flash); i++) {
    239        if (pflash_blk[i] && !pflash_blk[i - 1]) {
    240            error_report("pflash%d requires pflash%d", i, i - 1);
    241            exit(1);
    242        }
    243    }
    244
    245    if (!pflash_blk[0]) {
    246        /* Machine property pflash0 not set, use ROM mode */
    247        x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, false);
    248    } else {
    249        if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
    250            /*
    251             * Older KVM cannot execute from device memory. So, flash
    252             * memory cannot be used unless the readonly memory kvm
    253             * capability is present.
    254             */
    255            error_report("pflash with kvm requires KVM readonly memory support");
    256            exit(1);
    257        }
    258
    259        pc_system_flash_map(pcms, rom_memory);
    260    }
    261
    262    pc_system_flash_cleanup_unused(pcms);
    263}