mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
HW core patch queue
. Deprecate unmaintained SH-4 models (Samuel) . HPET: Convert DPRINTF calls to trace events (Daniel) . Implement buffered block writes in Intel PFlash (Gerd) . Ignore ELF loadable segments with zero size (Bin) . ESP/NCR53C9x: PCI DMA fixes (Mark) . PIIX: Simplify Xen PCI IRQ routing (Bernhard) . Restrict CPU 'start-powered-off' property to sysemu (Phil) . target/alpha: Only build sys_helper.c on system emulation (Phil) . target/xtensa: Use generic instruction breakpoint API & add test (Max) . Restrict icount to system emulation (Phil) . Do not set CPUState TCG-specific flags in non-TCG accels (Phil) . Cleanup TCG tb_invalidate API (Phil) . Correct LoongArch/KVM include path (Bibo) . Do not ignore throttle errors in crypto backends (Phil) . MAINTAINERS updates (Raphael, Zhao) -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmWqXbkACgkQ4+MsLN6t wN6VVBAAkP/Bs2JfQYobPZVV868wceM97KeUJMXP2YWf6dSLpHRCQN5KtuJcACM9 y3k3R7nMeVJSGmzl/1gF1G9JhjoCLoVLX/ejeBppv4Wq//9sEdggaQfdCwkhWw2o IK/gPjTZpimE7Er4hPlxmuhSRuM1MX4duKFRRfuZpE7XY14Y7/Hk12VIG7LooO0x 2Sl8CaU0DN7CWmRVDoUkwVx7JBy28UVarRDsgpBim7oKmjjBFnCJkH6B6NJXEiYr z1BmIcHa87S09kG1ek+y8aZpG9iPC7nUWjPIQyJGhnfrnBuO7hQHwCLIjHHp5QBR BoMr8YQNTI34/M/D8pBfg96LrGDjkQOfwRyRddkMP/jJcNPMAPMNGbfVaIrfij1e T+jFF4gQenOvy1XKCY3Uk/a11P3tIRFBEeOlzzQg4Aje9W2MhUNwK2HTlRfBbrRr V30R764FDmHlsyOu6/E3jqp4GVCgryF1bglPOBjVEU5uytbQTP8jshIpGVnxBbF+ OpFwtsoDbsousNKVcO5+B0mlHcB9Ru9h11M5/YD/jfLMk95Ga90JGdgYpqQ5tO5Y aqQhKfCKbfgKuKhysxpsdWAwHZzVrlSf+UrObF0rl2lMXXfcppjCqNaw4QJ0oedc DNBxTPcCE2vWhUzP3A60VH7jLh4nLaqSTrxxQKkbx+Je1ERGrxs= =KmQh -----END PGP SIGNATURE----- Merge tag 'hw-cpus-20240119' of https://github.com/philmd/qemu into staging HW core patch queue . Deprecate unmaintained SH-4 models (Samuel) . HPET: Convert DPRINTF calls to trace events (Daniel) . Implement buffered block writes in Intel PFlash (Gerd) . Ignore ELF loadable segments with zero size (Bin) . ESP/NCR53C9x: PCI DMA fixes (Mark) . PIIX: Simplify Xen PCI IRQ routing (Bernhard) . Restrict CPU 'start-powered-off' property to sysemu (Phil) . target/alpha: Only build sys_helper.c on system emulation (Phil) . target/xtensa: Use generic instruction breakpoint API & add test (Max) . Restrict icount to system emulation (Phil) . Do not set CPUState TCG-specific flags in non-TCG accels (Phil) . Cleanup TCG tb_invalidate API (Phil) . Correct LoongArch/KVM include path (Bibo) . Do not ignore throttle errors in crypto backends (Phil) . MAINTAINERS updates (Raphael, Zhao) # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmWqXbkACgkQ4+MsLN6t # wN6VVBAAkP/Bs2JfQYobPZVV868wceM97KeUJMXP2YWf6dSLpHRCQN5KtuJcACM9 # y3k3R7nMeVJSGmzl/1gF1G9JhjoCLoVLX/ejeBppv4Wq//9sEdggaQfdCwkhWw2o # IK/gPjTZpimE7Er4hPlxmuhSRuM1MX4duKFRRfuZpE7XY14Y7/Hk12VIG7LooO0x # 2Sl8CaU0DN7CWmRVDoUkwVx7JBy28UVarRDsgpBim7oKmjjBFnCJkH6B6NJXEiYr # z1BmIcHa87S09kG1ek+y8aZpG9iPC7nUWjPIQyJGhnfrnBuO7hQHwCLIjHHp5QBR # BoMr8YQNTI34/M/D8pBfg96LrGDjkQOfwRyRddkMP/jJcNPMAPMNGbfVaIrfij1e # T+jFF4gQenOvy1XKCY3Uk/a11P3tIRFBEeOlzzQg4Aje9W2MhUNwK2HTlRfBbrRr # V30R764FDmHlsyOu6/E3jqp4GVCgryF1bglPOBjVEU5uytbQTP8jshIpGVnxBbF+ # OpFwtsoDbsousNKVcO5+B0mlHcB9Ru9h11M5/YD/jfLMk95Ga90JGdgYpqQ5tO5Y # aqQhKfCKbfgKuKhysxpsdWAwHZzVrlSf+UrObF0rl2lMXXfcppjCqNaw4QJ0oedc # DNBxTPcCE2vWhUzP3A60VH7jLh4nLaqSTrxxQKkbx+Je1ERGrxs= # =KmQh # -----END PGP SIGNATURE----- # gpg: Signature made Fri 19 Jan 2024 11:32:09 GMT # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-cpus-20240119' of https://github.com/philmd/qemu: (36 commits) configure: Add linux header compile support for LoongArch MAINTAINERS: Update hw/core/cpu.c entry MAINTAINERS: Update Raphael Norwitz email hw/elf_ops: Ignore loadable segments with zero size hw/scsi/esp-pci: set DMA_STAT_BCMBLT when BLAST command issued hw/scsi/esp-pci: synchronise setting of DMA_STAT_DONE with ESP completion interrupt hw/scsi/esp-pci: generate PCI interrupt from separate ESP and PCI sources hw/scsi/esp-pci: use correct address register for PCI DMA transfers target/riscv: Rename tcg_cpu_FOO() to include 'riscv' target/i386: Rename tcg_cpu_FOO() to include 'x86' hw/s390x: Rename cpu_class_init() to include 'sclp' hw/core/cpu: Rename cpu_class_init() to include 'common' accel: Rename accel_init_ops_interfaces() to include 'system' cpus: Restrict 'start-powered-off' property to system emulation system/watchpoint: Move TCG specific code to accel/tcg/ system/replay: Restrict icount to system emulation hw/pflash: implement update buffer for block writes hw/pflash: use ldn_{be,le}_p and stn_{be,le}_p hw/pflash: refactor pflash_data_write() hw/i386/pc_piix: Make piix_intx_routing_notifier_xen() more device independent ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3f2a357b95
50 changed files with 603 additions and 520 deletions
|
@ -80,16 +80,39 @@ struct PFlashCFI01 {
|
|||
uint16_t ident3;
|
||||
uint8_t cfi_table[0x52];
|
||||
uint64_t counter;
|
||||
unsigned int writeblock_size;
|
||||
uint32_t writeblock_size;
|
||||
MemoryRegion mem;
|
||||
char *name;
|
||||
void *storage;
|
||||
VMChangeStateEntry *vmstate;
|
||||
bool old_multiple_chip_handling;
|
||||
|
||||
/* block update buffer */
|
||||
unsigned char *blk_bytes;
|
||||
uint32_t blk_offset;
|
||||
};
|
||||
|
||||
static int pflash_post_load(void *opaque, int version_id);
|
||||
|
||||
static bool pflash_blk_write_state_needed(void *opaque)
|
||||
{
|
||||
PFlashCFI01 *pfl = opaque;
|
||||
|
||||
return (pfl->blk_offset != -1);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pflash_blk_write = {
|
||||
.name = "pflash_cfi01_blk_write",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pflash_blk_write_state_needed,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
|
||||
VMSTATE_UINT32(blk_offset, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pflash = {
|
||||
.name = "pflash_cfi01",
|
||||
.version_id = 1,
|
||||
|
@ -101,6 +124,10 @@ static const VMStateDescription vmstate_pflash = {
|
|||
VMSTATE_UINT8(status, PFlashCFI01),
|
||||
VMSTATE_UINT64(counter, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription * const []) {
|
||||
&vmstate_pflash_blk_write,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -225,34 +252,10 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
|
|||
uint32_t ret;
|
||||
|
||||
p = pfl->storage;
|
||||
switch (width) {
|
||||
case 1:
|
||||
ret = p[offset];
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
ret = p[offset] << 8;
|
||||
ret |= p[offset + 1];
|
||||
} else {
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
ret = p[offset] << 24;
|
||||
ret |= p[offset + 1] << 16;
|
||||
ret |= p[offset + 2] << 8;
|
||||
ret |= p[offset + 3];
|
||||
} else {
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
ret |= p[offset + 2] << 16;
|
||||
ret |= p[offset + 3] << 24;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
if (be) {
|
||||
ret = ldn_be_p(p + offset, width);
|
||||
} else {
|
||||
ret = ldn_le_p(p + offset, width);
|
||||
}
|
||||
trace_pflash_data_read(pfl->name, offset, width, ret);
|
||||
return ret;
|
||||
|
@ -400,40 +403,61 @@ static void pflash_update(PFlashCFI01 *pfl, int offset,
|
|||
}
|
||||
}
|
||||
|
||||
/* copy current flash content to block update buffer */
|
||||
static void pflash_blk_write_start(PFlashCFI01 *pfl, hwaddr offset)
|
||||
{
|
||||
hwaddr mask = ~(pfl->writeblock_size - 1);
|
||||
|
||||
trace_pflash_write_block_start(pfl->name, pfl->counter);
|
||||
pfl->blk_offset = offset & mask;
|
||||
memcpy(pfl->blk_bytes, pfl->storage + pfl->blk_offset,
|
||||
pfl->writeblock_size);
|
||||
}
|
||||
|
||||
/* commit block update buffer changes */
|
||||
static void pflash_blk_write_flush(PFlashCFI01 *pfl)
|
||||
{
|
||||
g_assert(pfl->blk_offset != -1);
|
||||
trace_pflash_write_block_flush(pfl->name);
|
||||
memcpy(pfl->storage + pfl->blk_offset, pfl->blk_bytes,
|
||||
pfl->writeblock_size);
|
||||
pflash_update(pfl, pfl->blk_offset, pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
/* discard block update buffer changes */
|
||||
static void pflash_blk_write_abort(PFlashCFI01 *pfl)
|
||||
{
|
||||
trace_pflash_write_block_abort(pfl->name);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
uint32_t value, int width, int be)
|
||||
{
|
||||
uint8_t *p = pfl->storage;
|
||||
uint8_t *p;
|
||||
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
|
||||
switch (width) {
|
||||
case 1:
|
||||
p[offset] = value;
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
p[offset] = value >> 8;
|
||||
p[offset + 1] = value;
|
||||
} else {
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
if (pfl->blk_offset != -1) {
|
||||
/* block write: redirect writes to block update buffer */
|
||||
if ((offset < pfl->blk_offset) ||
|
||||
(offset + width > pfl->blk_offset + pfl->writeblock_size)) {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
p[offset] = value >> 24;
|
||||
p[offset + 1] = value >> 16;
|
||||
p[offset + 2] = value >> 8;
|
||||
p[offset + 3] = value;
|
||||
} else {
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
p[offset + 2] = value >> 16;
|
||||
p[offset + 3] = value >> 24;
|
||||
}
|
||||
break;
|
||||
trace_pflash_data_write_block(pfl->name, offset, width, value,
|
||||
pfl->counter);
|
||||
p = pfl->blk_bytes + (offset - pfl->blk_offset);
|
||||
} else {
|
||||
/* write directly to storage */
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
p = pfl->storage + offset;
|
||||
}
|
||||
|
||||
if (be) {
|
||||
stn_be_p(p, width, value);
|
||||
} else {
|
||||
stn_le_p(p, width, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
|
@ -548,9 +572,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||
} else {
|
||||
value = extract32(value, 0, pfl->bank_width * 8);
|
||||
}
|
||||
trace_pflash_write_block(pfl->name, value);
|
||||
pfl->counter = value;
|
||||
pfl->wcycle++;
|
||||
pflash_blk_write_start(pfl, offset);
|
||||
break;
|
||||
case 0x60:
|
||||
if (cmd == 0xd0) {
|
||||
|
@ -581,12 +605,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
/* FIXME check @offset, @width */
|
||||
if (!pfl->ro) {
|
||||
/*
|
||||
* FIXME writing straight to memory is *wrong*. We
|
||||
* should write to a buffer, and flush it to memory
|
||||
* only on confirm command (see below).
|
||||
*/
|
||||
if (!pfl->ro && (pfl->blk_offset != -1)) {
|
||||
pflash_data_write(pfl, offset, value, width, be);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
|
@ -595,18 +614,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||
pfl->status |= 0x80;
|
||||
|
||||
if (!pfl->counter) {
|
||||
hwaddr mask = pfl->writeblock_size - 1;
|
||||
mask = ~mask;
|
||||
|
||||
trace_pflash_write(pfl->name, "block write finished");
|
||||
pfl->wcycle++;
|
||||
if (!pfl->ro) {
|
||||
/* Flush the entire write buffer onto backing storage. */
|
||||
/* FIXME premature! */
|
||||
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
}
|
||||
}
|
||||
|
||||
pfl->counter--;
|
||||
|
@ -618,20 +627,17 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||
case 3: /* Confirm mode */
|
||||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
if (cmd == 0xd0) {
|
||||
/* FIXME this is where we should write out the buffer */
|
||||
if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
|
||||
pflash_blk_write_flush(pfl);
|
||||
pfl->wcycle = 0;
|
||||
pfl->status |= 0x80;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: Aborting write to buffer not implemented,"
|
||||
" the data is already written to storage!\n"
|
||||
"Flash device reset into READ mode.\n",
|
||||
__func__);
|
||||
pflash_blk_write_abort(pfl);
|
||||
goto mode_read_array;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pflash_blk_write_abort(pfl);
|
||||
goto error_flash;
|
||||
}
|
||||
break;
|
||||
|
@ -865,6 +871,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
|||
pfl->cmd = 0x00;
|
||||
pfl->status = 0x80; /* WSM ready */
|
||||
pflash_cfi01_fill_cfi_table(pfl);
|
||||
|
||||
pfl->blk_bytes = g_malloc(pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||
|
@ -884,6 +893,8 @@ static void pflash_cfi01_system_reset(DeviceState *dev)
|
|||
* This model deliberately ignores this delay.
|
||||
*/
|
||||
pfl->status = 0x80;
|
||||
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static Property pflash_cfi01_properties[] = {
|
||||
|
|
|
@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
}
|
||||
goto reset_flash;
|
||||
}
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, 0);
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
if (!pfl->ro) {
|
||||
p = (uint8_t *)pfl->storage + offset;
|
||||
if (pfl->be) {
|
||||
|
|
|
@ -202,6 +202,7 @@ static sh7750_io_device tc58128 = {
|
|||
|
||||
int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
|
||||
{
|
||||
warn_report_once("The TC58128 flash device is deprecated");
|
||||
init_dev(&tc58128_devs[0], zone1);
|
||||
init_dev(&tc58128_devs[1], zone2);
|
||||
return sh7750_register_io_device(s, &tc58128);
|
||||
|
|
|
@ -12,7 +12,8 @@ fdctrl_tc_pulse(int level) "TC pulse: %u"
|
|||
pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64
|
||||
pflash_chip_erase_start(const char *name) "%s: start chip erase"
|
||||
pflash_data_read(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x"
|
||||
pflash_device_info(const char *name, uint64_t offset) "%s: read device information offset:0x%04" PRIx64
|
||||
pflash_erase_complete(const char *name) "%s: sector erase complete"
|
||||
|
@ -32,7 +33,9 @@ pflash_unlock0_failed(const char *name, uint64_t offset, uint8_t cmd, uint16_t a
|
|||
pflash_unlock1_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: unlock0 failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_unsupported_device_configuration(const char *name, uint8_t width, uint8_t max) "%s: unsupported device configuration: device_width:%d max_device_width:%d"
|
||||
pflash_write(const char *name, const char *str) "%s: %s"
|
||||
pflash_write_block(const char *name, uint32_t value) "%s: block write: bytes:0x%x"
|
||||
pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x"
|
||||
pflash_write_block_flush(const char *name) "%s: block write flush"
|
||||
pflash_write_block_abort(const char *name) "%s: block write abort"
|
||||
pflash_write_block_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64
|
||||
pflash_write_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: command failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_write_invalid(const char *name, uint8_t cmd) "%s: invalid write for command 0x%02x"
|
||||
|
|
|
@ -273,7 +273,7 @@ static int64_t cpu_common_get_arch_id(CPUState *cpu)
|
|||
return cpu->cpu_index;
|
||||
}
|
||||
|
||||
static void cpu_class_init(ObjectClass *klass, void *data)
|
||||
static void cpu_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
@ -304,7 +304,7 @@ static const TypeInfo cpu_type_info = {
|
|||
.instance_finalize = cpu_common_finalize,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(CPUClass),
|
||||
.class_init = cpu_class_init,
|
||||
.class_init = cpu_common_class_init,
|
||||
};
|
||||
|
||||
static void cpu_register_types(void)
|
||||
|
|
|
@ -92,13 +92,10 @@ static void piix_intx_routing_notifier_xen(PCIDevice *dev)
|
|||
{
|
||||
int i;
|
||||
|
||||
/* Scan for updates to PCI link routes (0x60-0x63). */
|
||||
/* Scan for updates to PCI link routes. */
|
||||
for (i = 0; i < PIIX_NUM_PIRQS; i++) {
|
||||
uint8_t v = dev->config_read(dev, PIIX_PIRQCA + i, 1);
|
||||
if (v & 0x80) {
|
||||
v = 0;
|
||||
}
|
||||
v &= 0xf;
|
||||
const PCIINTxRoute route = pci_device_route_intx_to_irq(dev, i);
|
||||
const uint8_t v = route.mode == PCI_INTX_ENABLED ? route.irq : 0;
|
||||
xen_set_pci_link_route(i, v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void cpu_class_init(ObjectClass *oc, void *data)
|
||||
static void sclp_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SCLPEventClass *k = SCLP_EVENT_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
@ -94,7 +94,7 @@ static const TypeInfo sclp_cpu_info = {
|
|||
.name = TYPE_SCLP_CPU_HOTPLUG,
|
||||
.parent = TYPE_SCLP_EVENT,
|
||||
.instance_size = sizeof(SCLPEvent),
|
||||
.class_init = cpu_class_init,
|
||||
.class_init = sclp_cpu_class_init,
|
||||
.class_size = sizeof(SCLPEventClass),
|
||||
};
|
||||
|
||||
|
|
|
@ -77,6 +77,41 @@ struct PCIESPState {
|
|||
ESPState esp;
|
||||
};
|
||||
|
||||
static void esp_pci_update_irq(PCIESPState *pci)
|
||||
{
|
||||
int scsi_level = !!(pci->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT);
|
||||
int dma_level = (pci->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ?
|
||||
!!(pci->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0;
|
||||
int level = scsi_level || dma_level;
|
||||
|
||||
pci_set_irq(PCI_DEVICE(pci), level);
|
||||
}
|
||||
|
||||
static void esp_irq_handler(void *opaque, int irq_num, int level)
|
||||
{
|
||||
PCIESPState *pci = PCI_ESP(opaque);
|
||||
|
||||
if (level) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT;
|
||||
|
||||
/*
|
||||
* If raising the ESP IRQ to indicate end of DMA transfer, set
|
||||
* DMA_STAT_DONE at the same time. In theory this should be done in
|
||||
* esp_pci_dma_memory_rw(), however there is a delay between setting
|
||||
* DMA_STAT_DONE and the ESP IRQ arriving which is visible to the
|
||||
* guest that can cause confusion e.g. Linux
|
||||
*/
|
||||
if ((pci->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 &&
|
||||
pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
} else {
|
||||
pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT;
|
||||
}
|
||||
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
|
||||
static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val)
|
||||
{
|
||||
ESPState *s = &pci->esp;
|
||||
|
@ -89,6 +124,7 @@ static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val)
|
|||
{
|
||||
trace_esp_pci_dma_blast(val);
|
||||
qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n");
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT;
|
||||
}
|
||||
|
||||
static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val)
|
||||
|
@ -151,6 +187,7 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
|
|||
/* clear some bits on write */
|
||||
uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE;
|
||||
pci->dma_regs[DMA_STAT] &= ~(val & mask);
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -161,17 +198,14 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val)
|
|||
|
||||
static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr)
|
||||
{
|
||||
ESPState *s = &pci->esp;
|
||||
uint32_t val;
|
||||
|
||||
val = pci->dma_regs[saddr];
|
||||
if (saddr == DMA_STAT) {
|
||||
if (s->rregs[ESP_RSTAT] & STAT_INT) {
|
||||
val |= DMA_STAT_SCSIINT;
|
||||
}
|
||||
if (!(pci->sbac & SBAC_STATUS)) {
|
||||
pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT |
|
||||
DMA_STAT_DONE);
|
||||
esp_pci_update_irq(pci);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +309,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
|||
qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n");
|
||||
}
|
||||
|
||||
addr = pci->dma_regs[DMA_SPA];
|
||||
addr = pci->dma_regs[DMA_WAC];
|
||||
if (pci->dma_regs[DMA_WBC] < len) {
|
||||
len = pci->dma_regs[DMA_WBC];
|
||||
}
|
||||
|
@ -285,9 +319,6 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len,
|
|||
/* update status registers */
|
||||
pci->dma_regs[DMA_WBC] -= len;
|
||||
pci->dma_regs[DMA_WAC] += len;
|
||||
if (pci->dma_regs[DMA_WBC] == 0) {
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len)
|
||||
|
@ -342,23 +373,13 @@ static const VMStateDescription vmstate_esp_pci_scsi = {
|
|||
}
|
||||
};
|
||||
|
||||
static void esp_pci_command_complete(SCSIRequest *req, size_t resid)
|
||||
{
|
||||
ESPState *s = req->hba_private;
|
||||
PCIESPState *pci = container_of(s, PCIESPState, esp);
|
||||
|
||||
esp_command_complete(req, resid);
|
||||
pci->dma_regs[DMA_WBC] = 0;
|
||||
pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE;
|
||||
}
|
||||
|
||||
static const struct SCSIBusInfo esp_pci_scsi_info = {
|
||||
.tcq = false,
|
||||
.max_target = ESP_MAX_DEVS,
|
||||
.max_lun = 7,
|
||||
|
||||
.transfer_data = esp_transfer_data,
|
||||
.complete = esp_pci_command_complete,
|
||||
.complete = esp_command_complete,
|
||||
.cancel = esp_request_cancelled,
|
||||
};
|
||||
|
||||
|
@ -386,7 +407,7 @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
|
|||
"esp-io", 0x80);
|
||||
|
||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
|
||||
s->irq = pci_allocate_irq(dev);
|
||||
s->irq = qemu_allocate_irq(esp_irq_handler, pci, 0);
|
||||
|
||||
scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ static void shix_machine_init(MachineClass *mc)
|
|||
mc->init = shix_init;
|
||||
mc->is_default = true;
|
||||
mc->default_cpu_type = TYPE_SH7750R_CPU;
|
||||
mc->deprecation_reason = "old and unmaintained";
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("shix", shix_machine_init)
|
||||
|
|
|
@ -39,13 +39,7 @@
|
|||
#include "hw/timer/i8254.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
//#define HPET_DEBUG
|
||||
#ifdef HPET_DEBUG
|
||||
#define DPRINTF printf
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
#include "trace.h"
|
||||
|
||||
#define HPET_MSI_SUPPORT 0
|
||||
|
||||
|
@ -431,7 +425,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
HPETState *s = opaque;
|
||||
uint64_t cur_tick, index;
|
||||
|
||||
DPRINTF("qemu: Enter hpet_ram_readl at %" PRIx64 "\n", addr);
|
||||
trace_hpet_ram_read(addr);
|
||||
index = addr;
|
||||
/*address range of all TN regs*/
|
||||
if (index >= 0x100 && index <= 0x3ff) {
|
||||
|
@ -439,7 +433,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
HPETTimer *timer = &s->timer[timer_id];
|
||||
|
||||
if (timer_id > s->num_timers) {
|
||||
DPRINTF("qemu: timer id out of range\n");
|
||||
trace_hpet_timer_id_out_of_range(timer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -457,7 +451,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
case HPET_TN_ROUTE + 4:
|
||||
return timer->fsb >> 32;
|
||||
default:
|
||||
DPRINTF("qemu: invalid hpet_ram_readl\n");
|
||||
trace_hpet_ram_read_invalid();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -469,7 +463,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
case HPET_CFG:
|
||||
return s->config;
|
||||
case HPET_CFG + 4:
|
||||
DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl\n");
|
||||
trace_hpet_invalid_hpet_cfg(4);
|
||||
return 0;
|
||||
case HPET_COUNTER:
|
||||
if (hpet_enabled(s)) {
|
||||
|
@ -477,7 +471,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
} else {
|
||||
cur_tick = s->hpet_counter;
|
||||
}
|
||||
DPRINTF("qemu: reading counter = %" PRIx64 "\n", cur_tick);
|
||||
trace_hpet_ram_read_reading_counter(0, cur_tick);
|
||||
return cur_tick;
|
||||
case HPET_COUNTER + 4:
|
||||
if (hpet_enabled(s)) {
|
||||
|
@ -485,12 +479,12 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
|
|||
} else {
|
||||
cur_tick = s->hpet_counter;
|
||||
}
|
||||
DPRINTF("qemu: reading counter + 4 = %" PRIx64 "\n", cur_tick);
|
||||
trace_hpet_ram_read_reading_counter(4, cur_tick);
|
||||
return cur_tick >> 32;
|
||||
case HPET_STATUS:
|
||||
return s->isr;
|
||||
default:
|
||||
DPRINTF("qemu: invalid hpet_ram_readl\n");
|
||||
trace_hpet_ram_read_invalid();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -504,8 +498,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
HPETState *s = opaque;
|
||||
uint64_t old_val, new_val, val, index;
|
||||
|
||||
DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = 0x%" PRIx64 "\n",
|
||||
addr, value);
|
||||
trace_hpet_ram_write(addr, value);
|
||||
index = addr;
|
||||
old_val = hpet_ram_read(opaque, addr, 4);
|
||||
new_val = value;
|
||||
|
@ -515,14 +508,14 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
uint8_t timer_id = (addr - 0x100) / 0x20;
|
||||
HPETTimer *timer = &s->timer[timer_id];
|
||||
|
||||
DPRINTF("qemu: hpet_ram_writel timer_id = 0x%x\n", timer_id);
|
||||
trace_hpet_ram_write_timer_id(timer_id);
|
||||
if (timer_id > s->num_timers) {
|
||||
DPRINTF("qemu: timer id out of range\n");
|
||||
trace_hpet_timer_id_out_of_range(timer_id);
|
||||
return;
|
||||
}
|
||||
switch ((addr - 0x100) % 0x20) {
|
||||
case HPET_TN_CFG:
|
||||
DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
|
||||
trace_hpet_ram_write_tn_cfg();
|
||||
if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
|
||||
update_irq(timer, 0);
|
||||
}
|
||||
|
@ -540,10 +533,10 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
break;
|
||||
case HPET_TN_CFG + 4: // Interrupt capabilities
|
||||
DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
|
||||
trace_hpet_ram_write_invalid_tn_cfg(4);
|
||||
break;
|
||||
case HPET_TN_CMP: // comparator register
|
||||
DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP\n");
|
||||
trace_hpet_ram_write_tn_cmp(0);
|
||||
if (timer->config & HPET_TN_32BIT) {
|
||||
new_val = (uint32_t)new_val;
|
||||
}
|
||||
|
@ -566,7 +559,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
break;
|
||||
case HPET_TN_CMP + 4: // comparator register high order
|
||||
DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
|
||||
trace_hpet_ram_write_tn_cmp(4);
|
||||
if (!timer_is_periodic(timer)
|
||||
|| (timer->config & HPET_TN_SETVAL)) {
|
||||
timer->cmp = (timer->cmp & 0xffffffffULL) | new_val << 32;
|
||||
|
@ -591,7 +584,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
|
||||
break;
|
||||
default:
|
||||
DPRINTF("qemu: invalid hpet_ram_writel\n");
|
||||
trace_hpet_ram_write_invalid();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
@ -631,7 +624,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
break;
|
||||
case HPET_CFG + 4:
|
||||
DPRINTF("qemu: invalid HPET_CFG+4 write\n");
|
||||
trace_hpet_invalid_hpet_cfg(4);
|
||||
break;
|
||||
case HPET_STATUS:
|
||||
val = new_val & s->isr;
|
||||
|
@ -643,24 +636,20 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
|
|||
break;
|
||||
case HPET_COUNTER:
|
||||
if (hpet_enabled(s)) {
|
||||
DPRINTF("qemu: Writing counter while HPET enabled!\n");
|
||||
trace_hpet_ram_write_counter_write_while_enabled();
|
||||
}
|
||||
s->hpet_counter =
|
||||
(s->hpet_counter & 0xffffffff00000000ULL) | value;
|
||||
DPRINTF("qemu: HPET counter written. ctr = 0x%" PRIx64 " -> "
|
||||
"%" PRIx64 "\n", value, s->hpet_counter);
|
||||
trace_hpet_ram_write_counter_written(0, value, s->hpet_counter);
|
||||
break;
|
||||
case HPET_COUNTER + 4:
|
||||
if (hpet_enabled(s)) {
|
||||
DPRINTF("qemu: Writing counter while HPET enabled!\n");
|
||||
}
|
||||
trace_hpet_ram_write_counter_write_while_enabled();
|
||||
s->hpet_counter =
|
||||
(s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
|
||||
DPRINTF("qemu: HPET counter + 4 written. ctr = 0x%" PRIx64 " -> "
|
||||
"%" PRIx64 "\n", value, s->hpet_counter);
|
||||
trace_hpet_ram_write_counter_written(4, value, s->hpet_counter);
|
||||
break;
|
||||
default:
|
||||
DPRINTF("qemu: invalid hpet_ram_writel\n");
|
||||
trace_hpet_ram_write_invalid();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,3 +99,18 @@ sifive_pwm_write(uint64_t data, uint64_t offset) "Write 0x%" PRIx64 " at address
|
|||
sh_timer_start_stop(int enable, int current) "%d (%d)"
|
||||
sh_timer_read(uint64_t offset) "tmu012_read 0x%" PRIx64
|
||||
sh_timer_write(uint64_t offset, uint64_t value) "tmu012_write 0x%" PRIx64 " 0x%08" PRIx64
|
||||
|
||||
# hpet.c
|
||||
hpet_timer_id_out_of_range(uint8_t timer_id) "timer id out of range: 0x%" PRIx8
|
||||
hpet_invalid_hpet_cfg(uint8_t reg_off) "invalid HPET_CFG + %u" PRIx8
|
||||
hpet_ram_read(uint64_t addr) "enter hpet_ram_readl at 0x%" PRIx64
|
||||
hpet_ram_read_reading_counter(uint8_t reg_off, uint64_t cur_tick) "reading counter + %" PRIu8 " = 0x%" PRIx64
|
||||
hpet_ram_read_invalid(void) "invalid hpet_ram_readl"
|
||||
hpet_ram_write(uint64_t addr, uint64_t value) "enter hpet_ram_writel at 0x%" PRIx64 " = 0x%" PRIx64
|
||||
hpet_ram_write_timer_id(uint64_t timer_id) "hpet_ram_writel timer_id = 0x%" PRIx64
|
||||
hpet_ram_write_tn_cfg(void) "hpet_ram_writel HPET_TN_CFG"
|
||||
hpet_ram_write_invalid_tn_cfg(uint8_t reg_off) "invalid HPET_TN_CFG + %" PRIu8 " write"
|
||||
hpet_ram_write_tn_cmp(uint8_t reg_off) "hpet_ram_writel HPET_TN_CMP + %" PRIu8
|
||||
hpet_ram_write_invalid(void) "invalid hpet_ram_writel"
|
||||
hpet_ram_write_counter_write_while_enabled(void) "Writing counter while HPET enabled!"
|
||||
hpet_ram_write_counter_written(uint8_t reg_off, uint64_t value, uint64_t counter) "HPET counter + %" PRIu8 "written. crt = 0x%" PRIx64 " -> 0x%" PRIx64
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue