qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

q800: add a block backend to the PRAM

This allows to save and restore the content of the PRAM.
It may be useful if we want to check the configuration or to change it.

The backend is added using mtd interface, for instance:

... -drive file=pram.img,format=raw,if=mtd ...

where pram.img is the file where the data will be stored, its size must
be 256 bytes.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20191219201439.84804-3-laurent@vivier.eu>

+74
+6
hw/m68k/q800.c
··· 158 158 NubusBus *nubus; 159 159 GLUEState *irq; 160 160 qemu_irq *pic; 161 + DriveInfo *dinfo; 161 162 162 163 linux_boot = (kernel_filename != NULL); 163 164 ··· 200 201 /* VIA */ 201 202 202 203 via_dev = qdev_create(NULL, TYPE_MAC_VIA); 204 + dinfo = drive_get(IF_MTD, 0, 0); 205 + if (dinfo) { 206 + qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo), 207 + &error_abort); 208 + } 203 209 qdev_init_nofail(via_dev); 204 210 sysbus = SYS_BUS_DEVICE(via_dev); 205 211 sysbus_mmio_map(sysbus, 0, VIA_BASE);
+65
hw/misc/mac_via.c
··· 27 27 #include "sysemu/runstate.h" 28 28 #include "qapi/error.h" 29 29 #include "qemu/cutils.h" 30 + #include "hw/qdev-properties.h" 31 + #include "sysemu/block-backend.h" 30 32 #include "trace.h" 31 33 32 34 /* ··· 375 377 mdc->update_irq(s); 376 378 } 377 379 380 + 381 + static void pram_update(MacVIAState *m) 382 + { 383 + if (m->blk) { 384 + blk_pwrite(m->blk, 0, m->mos6522_via1.PRAM, 385 + sizeof(m->mos6522_via1.PRAM), 0); 386 + } 387 + } 388 + 378 389 /* 379 390 * RTC Commands 380 391 * ··· 547 558 /* PRAM address 0x00 -> 0x13 */ 548 559 trace_via1_rtc_cmd_pram_write(m->cmd - REG_PRAM_ADDR, m->data_out); 549 560 v1s->PRAM[m->cmd - REG_PRAM_ADDR] = m->data_out; 561 + pram_update(m); 550 562 m->cmd = REG_EMPTY; 551 563 break; 552 564 case REG_PRAM_SECT...REG_PRAM_SECT_LAST: ··· 577 589 g_assert(REG_PRAM_SECT <= m->cmd && m->cmd <= REG_PRAM_SECT_LAST); 578 590 sector = m->cmd - REG_PRAM_SECT; 579 591 v1s->PRAM[sector * 32 + m->alt] = m->data_out; 592 + pram_update(m); 580 593 trace_via1_rtc_cmd_pram_sect_write(sector, m->alt, sector * 32 + m->alt, 581 594 m->data_out); 582 595 m->alt = REG_EMPTY; ··· 857 870 MacVIAState *m = MAC_VIA(dev); 858 871 MOS6522State *ms; 859 872 struct tm tm; 873 + int ret; 860 874 861 875 /* Init VIAs 1 and 2 */ 862 876 sysbus_init_child_obj(OBJECT(dev), "via1", &m->mos6522_via1, ··· 890 904 m->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via_adb_poll, m); 891 905 m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq", 892 906 VIA1_IRQ_ADB_READY_BIT); 907 + 908 + if (m->blk) { 909 + int64_t len = blk_getlength(m->blk); 910 + if (len < 0) { 911 + error_setg_errno(errp, -len, 912 + "could not get length of backing image"); 913 + return; 914 + } 915 + ret = blk_set_perm(m->blk, 916 + BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE, 917 + BLK_PERM_ALL, errp); 918 + if (ret < 0) { 919 + return; 920 + } 921 + 922 + len = blk_pread(m->blk, 0, m->mos6522_via1.PRAM, 923 + sizeof(m->mos6522_via1.PRAM)); 924 + if (len != sizeof(m->mos6522_via1.PRAM)) { 925 + error_setg(errp, "can't read PRAM contents"); 926 + return; 927 + } 928 + } 893 929 } 894 930 895 931 static void mac_via_init(Object *obj) ··· 914 950 TYPE_ADB_BUS, DEVICE(obj), "adb.0"); 915 951 } 916 952 953 + static void postload_update_cb(void *opaque, int running, RunState state) 954 + { 955 + MacVIAState *m = MAC_VIA(opaque); 956 + 957 + qemu_del_vm_change_state_handler(m->vmstate); 958 + m->vmstate = NULL; 959 + 960 + pram_update(m); 961 + } 962 + 963 + static int mac_via_post_load(void *opaque, int version_id) 964 + { 965 + MacVIAState *m = MAC_VIA(opaque); 966 + 967 + if (m->blk) { 968 + m->vmstate = qemu_add_vm_change_state_handler(postload_update_cb, 969 + m); 970 + } 971 + 972 + return 0; 973 + } 974 + 917 975 static const VMStateDescription vmstate_mac_via = { 918 976 .name = "mac-via", 919 977 .version_id = 1, 920 978 .minimum_version_id = 1, 979 + .post_load = mac_via_post_load, 921 980 .fields = (VMStateField[]) { 922 981 /* VIAs */ 923 982 VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mos6522, ··· 950 1009 } 951 1010 }; 952 1011 1012 + static Property mac_via_properties[] = { 1013 + DEFINE_PROP_DRIVE("drive", MacVIAState, blk), 1014 + DEFINE_PROP_END_OF_LIST(), 1015 + }; 1016 + 953 1017 static void mac_via_class_init(ObjectClass *oc, void *data) 954 1018 { 955 1019 DeviceClass *dc = DEVICE_CLASS(oc); ··· 957 1021 dc->realize = mac_via_realize; 958 1022 dc->reset = mac_via_reset; 959 1023 dc->vmsd = &vmstate_mac_via; 1024 + dc->props = mac_via_properties; 960 1025 } 961 1026 962 1027 static TypeInfo mac_via_info = {
+3
include/hw/misc/mac_via.h
··· 81 81 typedef struct MacVIAState { 82 82 SysBusDevice busdev; 83 83 84 + VMChangeStateEntry *vmstate; 85 + 84 86 /* MMIO */ 85 87 MemoryRegion mmio; 86 88 MemoryRegion via1mem; ··· 100 102 uint8_t cmd; 101 103 int wprotect; 102 104 int alt; 105 + BlockBackend *blk; 103 106 104 107 /* ADB */ 105 108 ADBBusState adb_bus;