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

vga-pci.c (13112B)


      1/*
      2 * QEMU PCI VGA Emulator.
      3 *
      4 * see docs/specs/standard-vga.txt for virtual hardware specs.
      5 *
      6 * Copyright (c) 2003 Fabrice Bellard
      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#include "qemu/osdep.h"
     28#include "hw/pci/pci.h"
     29#include "hw/qdev-properties.h"
     30#include "migration/vmstate.h"
     31#include "vga_int.h"
     32#include "ui/pixel_ops.h"
     33#include "qemu/module.h"
     34#include "qemu/timer.h"
     35#include "hw/loader.h"
     36#include "hw/display/edid.h"
     37#include "qom/object.h"
     38
     39enum vga_pci_flags {
     40    PCI_VGA_FLAG_ENABLE_MMIO = 1,
     41    PCI_VGA_FLAG_ENABLE_QEXT = 2,
     42    PCI_VGA_FLAG_ENABLE_EDID = 3,
     43};
     44
     45struct PCIVGAState {
     46    PCIDevice dev;
     47    VGACommonState vga;
     48    uint32_t flags;
     49    qemu_edid_info edid_info;
     50    MemoryRegion mmio;
     51    MemoryRegion mrs[4];
     52    uint8_t edid[384];
     53};
     54
     55#define TYPE_PCI_VGA "pci-vga"
     56OBJECT_DECLARE_SIMPLE_TYPE(PCIVGAState, PCI_VGA)
     57
     58static const VMStateDescription vmstate_vga_pci = {
     59    .name = "vga",
     60    .version_id = 2,
     61    .minimum_version_id = 2,
     62    .fields = (VMStateField[]) {
     63        VMSTATE_PCI_DEVICE(dev, PCIVGAState),
     64        VMSTATE_STRUCT(vga, PCIVGAState, 0, vmstate_vga_common, VGACommonState),
     65        VMSTATE_END_OF_LIST()
     66    }
     67};
     68
     69static uint64_t pci_vga_ioport_read(void *ptr, hwaddr addr,
     70                                    unsigned size)
     71{
     72    VGACommonState *s = ptr;
     73    uint64_t ret = 0;
     74
     75    switch (size) {
     76    case 1:
     77        ret = vga_ioport_read(s, addr + 0x3c0);
     78        break;
     79    case 2:
     80        ret  = vga_ioport_read(s, addr + 0x3c0);
     81        ret |= vga_ioport_read(s, addr + 0x3c1) << 8;
     82        break;
     83    }
     84    return ret;
     85}
     86
     87static void pci_vga_ioport_write(void *ptr, hwaddr addr,
     88                                 uint64_t val, unsigned size)
     89{
     90    VGACommonState *s = ptr;
     91
     92    switch (size) {
     93    case 1:
     94        vga_ioport_write(s, addr + 0x3c0, val);
     95        break;
     96    case 2:
     97        /*
     98         * Update bytes in little endian order.  Allows to update
     99         * indexed registers with a single word write because the
    100         * index byte is updated first.
    101         */
    102        vga_ioport_write(s, addr + 0x3c0, val & 0xff);
    103        vga_ioport_write(s, addr + 0x3c1, (val >> 8) & 0xff);
    104        break;
    105    }
    106}
    107
    108static const MemoryRegionOps pci_vga_ioport_ops = {
    109    .read = pci_vga_ioport_read,
    110    .write = pci_vga_ioport_write,
    111    .valid.min_access_size = 1,
    112    .valid.max_access_size = 4,
    113    .impl.min_access_size = 1,
    114    .impl.max_access_size = 2,
    115    .endianness = DEVICE_LITTLE_ENDIAN,
    116};
    117
    118static uint64_t pci_vga_bochs_read(void *ptr, hwaddr addr,
    119                                   unsigned size)
    120{
    121    VGACommonState *s = ptr;
    122    int index = addr >> 1;
    123
    124    vbe_ioport_write_index(s, 0, index);
    125    return vbe_ioport_read_data(s, 0);
    126}
    127
    128static void pci_vga_bochs_write(void *ptr, hwaddr addr,
    129                                uint64_t val, unsigned size)
    130{
    131    VGACommonState *s = ptr;
    132    int index = addr >> 1;
    133
    134    vbe_ioport_write_index(s, 0, index);
    135    vbe_ioport_write_data(s, 0, val);
    136}
    137
    138static const MemoryRegionOps pci_vga_bochs_ops = {
    139    .read = pci_vga_bochs_read,
    140    .write = pci_vga_bochs_write,
    141    .valid.min_access_size = 1,
    142    .valid.max_access_size = 4,
    143    .impl.min_access_size = 2,
    144    .impl.max_access_size = 2,
    145    .endianness = DEVICE_LITTLE_ENDIAN,
    146};
    147
    148static uint64_t pci_vga_qext_read(void *ptr, hwaddr addr, unsigned size)
    149{
    150    VGACommonState *s = ptr;
    151
    152    switch (addr) {
    153    case PCI_VGA_QEXT_REG_SIZE:
    154        return PCI_VGA_QEXT_SIZE;
    155    case PCI_VGA_QEXT_REG_BYTEORDER:
    156        return s->big_endian_fb ?
    157            PCI_VGA_QEXT_BIG_ENDIAN : PCI_VGA_QEXT_LITTLE_ENDIAN;
    158    default:
    159        return 0;
    160    }
    161}
    162
    163static void pci_vga_qext_write(void *ptr, hwaddr addr,
    164                               uint64_t val, unsigned size)
    165{
    166    VGACommonState *s = ptr;
    167
    168    switch (addr) {
    169    case PCI_VGA_QEXT_REG_BYTEORDER:
    170        if (val == PCI_VGA_QEXT_BIG_ENDIAN) {
    171            s->big_endian_fb = true;
    172        }
    173        if (val == PCI_VGA_QEXT_LITTLE_ENDIAN) {
    174            s->big_endian_fb = false;
    175        }
    176        break;
    177    }
    178}
    179
    180static bool vga_get_big_endian_fb(Object *obj, Error **errp)
    181{
    182    PCIVGAState *d = PCI_VGA(PCI_DEVICE(obj));
    183
    184    return d->vga.big_endian_fb;
    185}
    186
    187static void vga_set_big_endian_fb(Object *obj, bool value, Error **errp)
    188{
    189    PCIVGAState *d = PCI_VGA(PCI_DEVICE(obj));
    190
    191    d->vga.big_endian_fb = value;
    192}
    193
    194static const MemoryRegionOps pci_vga_qext_ops = {
    195    .read = pci_vga_qext_read,
    196    .write = pci_vga_qext_write,
    197    .valid.min_access_size = 4,
    198    .valid.max_access_size = 4,
    199    .endianness = DEVICE_LITTLE_ENDIAN,
    200};
    201
    202void pci_std_vga_mmio_region_init(VGACommonState *s,
    203                                  Object *owner,
    204                                  MemoryRegion *parent,
    205                                  MemoryRegion *subs,
    206                                  bool qext, bool edid)
    207{
    208    PCIVGAState *d = container_of(s, PCIVGAState, vga);
    209
    210    memory_region_init_io(&subs[0], owner, &pci_vga_ioport_ops, s,
    211                          "vga ioports remapped", PCI_VGA_IOPORT_SIZE);
    212    memory_region_add_subregion(parent, PCI_VGA_IOPORT_OFFSET,
    213                                &subs[0]);
    214
    215    memory_region_init_io(&subs[1], owner, &pci_vga_bochs_ops, s,
    216                          "bochs dispi interface", PCI_VGA_BOCHS_SIZE);
    217    memory_region_add_subregion(parent, PCI_VGA_BOCHS_OFFSET,
    218                                &subs[1]);
    219
    220    if (qext) {
    221        memory_region_init_io(&subs[2], owner, &pci_vga_qext_ops, s,
    222                              "qemu extended regs", PCI_VGA_QEXT_SIZE);
    223        memory_region_add_subregion(parent, PCI_VGA_QEXT_OFFSET,
    224                                    &subs[2]);
    225    }
    226
    227    if (edid) {
    228        qemu_edid_generate(d->edid, sizeof(d->edid), &d->edid_info);
    229        qemu_edid_region_io(&subs[3], owner, d->edid, sizeof(d->edid));
    230        memory_region_add_subregion(parent, 0, &subs[3]);
    231    }
    232}
    233
    234static void pci_std_vga_realize(PCIDevice *dev, Error **errp)
    235{
    236    PCIVGAState *d = PCI_VGA(dev);
    237    VGACommonState *s = &d->vga;
    238    bool qext = false;
    239    bool edid = false;
    240
    241    /* vga + console init */
    242    vga_common_init(s, OBJECT(dev));
    243    vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev),
    244             true);
    245
    246    s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
    247
    248    /* XXX: VGA_RAM_SIZE must be a power of two */
    249    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
    250
    251    /* mmio bar for vga register access */
    252    if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) {
    253        memory_region_init_io(&d->mmio, OBJECT(dev), &unassigned_io_ops, NULL,
    254                              "vga.mmio", PCI_VGA_MMIO_SIZE);
    255
    256        if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) {
    257            qext = true;
    258            pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2);
    259        }
    260        if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_EDID)) {
    261            edid = true;
    262        }
    263        pci_std_vga_mmio_region_init(s, OBJECT(dev), &d->mmio, d->mrs,
    264                                     qext, edid);
    265
    266        pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
    267    }
    268}
    269
    270static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
    271{
    272    PCIVGAState *d = PCI_VGA(dev);
    273    VGACommonState *s = &d->vga;
    274    bool qext = false;
    275    bool edid = false;
    276
    277    /* vga + console init */
    278    vga_common_init(s, OBJECT(dev));
    279    s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
    280
    281    /* mmio bar */
    282    memory_region_init_io(&d->mmio, OBJECT(dev), &unassigned_io_ops, NULL,
    283                          "vga.mmio", PCI_VGA_MMIO_SIZE);
    284
    285    if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) {
    286        qext = true;
    287        pci_set_byte(&d->dev.config[PCI_REVISION_ID], 2);
    288    }
    289    if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_EDID)) {
    290        edid = true;
    291    }
    292    pci_std_vga_mmio_region_init(s, OBJECT(dev), &d->mmio, d->mrs, qext, edid);
    293
    294    pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
    295    pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
    296}
    297
    298static void pci_secondary_vga_exit(PCIDevice *dev)
    299{
    300    PCIVGAState *d = PCI_VGA(dev);
    301    VGACommonState *s = &d->vga;
    302
    303    graphic_console_close(s->con);
    304    memory_region_del_subregion(&d->mmio, &d->mrs[0]);
    305    memory_region_del_subregion(&d->mmio, &d->mrs[1]);
    306    if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_QEXT)) {
    307        memory_region_del_subregion(&d->mmio, &d->mrs[2]);
    308    }
    309    if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_EDID)) {
    310        memory_region_del_subregion(&d->mmio, &d->mrs[3]);
    311    }
    312}
    313
    314static void pci_secondary_vga_init(Object *obj)
    315{
    316    /* Expose framebuffer byteorder via QOM */
    317    object_property_add_bool(obj, "big-endian-framebuffer",
    318                             vga_get_big_endian_fb, vga_set_big_endian_fb);
    319}
    320
    321static void pci_secondary_vga_reset(DeviceState *dev)
    322{
    323    PCIVGAState *d = PCI_VGA(PCI_DEVICE(dev));
    324    vga_common_reset(&d->vga);
    325}
    326
    327static Property vga_pci_properties[] = {
    328    DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
    329    DEFINE_PROP_BIT("mmio", PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_MMIO, true),
    330    DEFINE_PROP_BIT("qemu-extended-regs",
    331                    PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_QEXT, true),
    332    DEFINE_PROP_BIT("edid",
    333                    PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_EDID, true),
    334    DEFINE_EDID_PROPERTIES(PCIVGAState, edid_info),
    335    DEFINE_PROP_BOOL("global-vmstate", PCIVGAState, vga.global_vmstate, false),
    336    DEFINE_PROP_END_OF_LIST(),
    337};
    338
    339static Property secondary_pci_properties[] = {
    340    DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16),
    341    DEFINE_PROP_BIT("qemu-extended-regs",
    342                    PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_QEXT, true),
    343    DEFINE_PROP_BIT("edid",
    344                    PCIVGAState, flags, PCI_VGA_FLAG_ENABLE_EDID, true),
    345    DEFINE_EDID_PROPERTIES(PCIVGAState, edid_info),
    346    DEFINE_PROP_END_OF_LIST(),
    347};
    348
    349static void vga_pci_class_init(ObjectClass *klass, void *data)
    350{
    351    DeviceClass *dc = DEVICE_CLASS(klass);
    352    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    353
    354    k->vendor_id = PCI_VENDOR_ID_QEMU;
    355    k->device_id = PCI_DEVICE_ID_QEMU_VGA;
    356    dc->vmsd = &vmstate_vga_pci;
    357    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
    358}
    359
    360static const TypeInfo vga_pci_type_info = {
    361    .name = TYPE_PCI_VGA,
    362    .parent = TYPE_PCI_DEVICE,
    363    .instance_size = sizeof(PCIVGAState),
    364    .abstract = true,
    365    .class_init = vga_pci_class_init,
    366    .interfaces = (InterfaceInfo[]) {
    367        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
    368        { },
    369    },
    370};
    371
    372static void vga_class_init(ObjectClass *klass, void *data)
    373{
    374    DeviceClass *dc = DEVICE_CLASS(klass);
    375    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    376
    377    k->realize = pci_std_vga_realize;
    378    k->romfile = "vgabios-stdvga.bin";
    379    k->class_id = PCI_CLASS_DISPLAY_VGA;
    380    device_class_set_props(dc, vga_pci_properties);
    381    dc->hotpluggable = false;
    382
    383    /* Expose framebuffer byteorder via QOM */
    384    object_class_property_add_bool(klass, "big-endian-framebuffer",
    385                                   vga_get_big_endian_fb, vga_set_big_endian_fb);
    386}
    387
    388static void secondary_class_init(ObjectClass *klass, void *data)
    389{
    390    DeviceClass *dc = DEVICE_CLASS(klass);
    391    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    392
    393    k->realize = pci_secondary_vga_realize;
    394    k->exit = pci_secondary_vga_exit;
    395    k->class_id = PCI_CLASS_DISPLAY_OTHER;
    396    device_class_set_props(dc, secondary_pci_properties);
    397    dc->reset = pci_secondary_vga_reset;
    398}
    399
    400static const TypeInfo vga_info = {
    401    .name          = "VGA",
    402    .parent        = TYPE_PCI_VGA,
    403    .class_init    = vga_class_init,
    404};
    405
    406static const TypeInfo secondary_info = {
    407    .name          = "secondary-vga",
    408    .parent        = TYPE_PCI_VGA,
    409    .instance_init = pci_secondary_vga_init,
    410    .class_init    = secondary_class_init,
    411};
    412
    413static void vga_register_types(void)
    414{
    415    type_register_static(&vga_pci_type_info);
    416    type_register_static(&vga_info);
    417    type_register_static(&secondary_info);
    418}
    419
    420type_init(vga_register_types)