diff options
43 files changed, 815 insertions, 247 deletions
diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml index 7e685c6a65..c5fa4fce26 100644 --- a/.gitlab-ci.d/static_checks.yml +++ b/.gitlab-ci.d/static_checks.yml @@ -4,9 +4,6 @@ check-patch: needs: job: amd64-centos8-container script: - - git config --local diff.renamelimit 0 - - git config --local diff.renames True - - git config --local diff.algorithm histogram - .gitlab-ci.d/check-patch.py variables: GIT_DEPTH: 1000 diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md new file mode 100644 index 0000000000..e910f7b1c2 --- /dev/null +++ b/.gitlab/issue_templates/bug.md @@ -0,0 +1,64 @@ +<!-- +This is the upstream QEMU issue tracker. + +If you are able to, it will greatly facilitate bug triage if you attempt +to reproduce the problem with the latest qemu.git master built from +source. See https://www.qemu.org/download/#source for instructions on +how to do this. + +QEMU generally supports the last two releases advertised on +https://www.qemu.org/. Problems with distro-packaged versions of QEMU +older than this should be reported to the distribution instead. + +See https://www.qemu.org/contribute/report-a-bug/ for additional +guidance. + +If this is a security issue, please consult +https://www.qemu.org/contribute/security-process/ +--> + +## Host environment + - Operating system: (Windows 10 21H1, Fedora 34, etc.) + - OS/kernel version: (For POSIX hosts, use `uname -a`) + - Architecture: (x86, ARM, s390x, etc.) + - QEMU flavor: (qemu-system-x86_64, qemu-aarch64, qemu-img, etc.) + - QEMU version: (e.g. `qemu-system-x86_64 --version`) + - QEMU command line: + <!-- + Give the smallest, complete command line that exhibits the problem. + + If you are using libvirt, virsh, or vmm, you can likely find the QEMU + command line arguments in /var/log/libvirt/qemu/$GUEST.log. + --> + ``` + ./qemu-system-x86_64 -M q35 -m 4096 -enable-kvm -hda fedora32.qcow2 + ``` + +## Emulated/Virtualized environment + - Operating system: (Windows 10 21H1, Fedora 34, etc.) + - OS/kernel version: (For POSIX guests, use `uname -a`.) + - Architecture: (x86, ARM, s390x, etc.) + + +## Description of problem +<!-- Describe the problem, including any error/crash messages seen. --> + + +## Steps to reproduce +1. +2. +3. + + +## Additional information + +<!-- +Attach logs, stack traces, screenshots, etc. Compress the files if necessary. +If using libvirt, libvirt logs and XML domain information may be relevant. +--> + +<!-- +The line below ensures that proper tags are added to the issue. +Please do not remove it. +--> +/label ~"kind::Bug" diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md new file mode 100644 index 0000000000..7de02dcc2c --- /dev/null +++ b/.gitlab/issue_templates/feature_request.md @@ -0,0 +1,32 @@ +<!-- +This is the upstream QEMU issue tracker. + +Please note that QEMU, like most open source projects, relies on +contributors who have motivation, skills and available time to work on +implementing particular features. + +Feature requests can be helpful for determining demand and interest, but +they are not a guarantee that a contributor will volunteer to implement +it. We welcome and encourage even draft patches to implement a feature +be sent to the mailing list where it can be discussed and developed +further by the community. + +Thank you for your interest in helping us to make QEMU better! +--> + +## Goal +<!-- Describe the final result you want to achieve. Avoid design specifics. --> + + +## Technical details +<!-- Describe technical details, design specifics, suggestions, versions, etc. --> + + +## Additional information +<!-- Patch or branch references, any other useful information --> + +<!-- +The line below ensures that proper tags are added to the issue. +Please do not remove it. +--> +/label ~"kind::Feature Request" diff --git a/.patchew.yml b/.patchew.yml index 2638b7f564..1b78262ce5 100644 --- a/.patchew.yml +++ b/.patchew.yml @@ -138,9 +138,6 @@ testing: script: | #!/bin/bash git rev-parse base > /dev/null || exit 0 - git config --local diff.renamelimit 0 - git config --local diff.renames True - git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. docker-mingw@fedora: enabled: true diff --git a/MAINTAINERS b/MAINTAINERS index 7ab02764b2..cfbf7ef79b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1365,11 +1365,9 @@ M: Alistair Francis <Alistair.Francis@wdc.com> L: qemu-riscv@nongnu.org S: Supported F: hw/riscv/opentitan.c -F: hw/char/ibex_uart.c -F: hw/intc/ibex_plic.c +F: hw/*/ibex_*.c F: include/hw/riscv/opentitan.h -F: include/hw/char/ibex_uart.h -F: include/hw/intc/ibex_plic.h +F: include/hw/*/ibex_*.h Microchip PolarFire SoC Icicle Kit M: Bin Meng <bin.meng@windriver.com> diff --git a/audio/coreaudio.c b/audio/coreaudio.c index f570e1ee60..d8a21d3e50 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -26,6 +26,7 @@ #include <CoreAudio/CoreAudio.h> #include <pthread.h> /* pthread_X */ +#include "qemu/main-loop.h" #include "qemu/module.h" #include "audio.h" @@ -34,7 +35,7 @@ typedef struct coreaudioVoiceOut { HWVoiceOut hw; - pthread_mutex_t mutex; + pthread_mutex_t buf_mutex; AudioDeviceID outputDeviceID; int frameSizeSetting; uint32_t bufferCount; @@ -241,11 +242,11 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 ( #define coreaudio_playback_logerr(status, ...) \ coreaudio_logerr2(status, "playback", __VA_ARGS__) -static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) +static int coreaudio_buf_lock (coreaudioVoiceOut *core, const char *fn_name) { int err; - err = pthread_mutex_lock (&core->mutex); + err = pthread_mutex_lock (&core->buf_mutex); if (err) { dolog ("Could not lock voice for %s\nReason: %s\n", fn_name, strerror (err)); @@ -254,11 +255,11 @@ static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) +static int coreaudio_buf_unlock (coreaudioVoiceOut *core, const char *fn_name) { int err; - err = pthread_mutex_unlock (&core->mutex); + err = pthread_mutex_unlock (&core->buf_mutex); if (err) { dolog ("Could not unlock voice for %s\nReason: %s\n", fn_name, strerror (err)); @@ -273,13 +274,13 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \ ret_type ret; \ \ - if (coreaudio_lock(core, "coreaudio_" #name)) { \ + if (coreaudio_buf_lock(core, "coreaudio_" #name)) { \ return 0; \ } \ \ ret = glue(audio_generic_, name)args; \ \ - coreaudio_unlock(core, "coreaudio_" #name); \ + coreaudio_buf_unlock(core, "coreaudio_" #name); \ return ret; \ } COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size), @@ -291,7 +292,10 @@ COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size)) #undef COREAUDIO_WRAPPER_FUNC -/* callback to feed audiooutput buffer */ +/* + * callback to feed audiooutput buffer. called without iothread lock. + * allowed to lock "buf_mutex", but disallowed to have any other locks. + */ static OSStatus audioDeviceIOProc( AudioDeviceID inDevice, const AudioTimeStamp *inNow, @@ -307,13 +311,13 @@ static OSStatus audioDeviceIOProc( coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; size_t len; - if (coreaudio_lock (core, "audioDeviceIOProc")) { + if (coreaudio_buf_lock (core, "audioDeviceIOProc")) { inInputTime = 0; return 0; } if (inDevice != core->outputDeviceID) { - coreaudio_unlock (core, "audioDeviceIOProc(old device)"); + coreaudio_buf_unlock (core, "audioDeviceIOProc(old device)"); return 0; } @@ -323,7 +327,7 @@ static OSStatus audioDeviceIOProc( /* if there are not enough samples, set signal and return */ if (pending_frames < frameCount) { inInputTime = 0; - coreaudio_unlock (core, "audioDeviceIOProc(empty)"); + coreaudio_buf_unlock (core, "audioDeviceIOProc(empty)"); return 0; } @@ -345,7 +349,7 @@ static OSStatus audioDeviceIOProc( out += write_len; } - coreaudio_unlock (core, "audioDeviceIOProc"); + coreaudio_buf_unlock (core, "audioDeviceIOProc"); return 0; } @@ -438,7 +442,16 @@ static OSStatus init_out_device(coreaudioVoiceOut *core) return status; } - /* set Callback */ + /* + * set Callback. + * + * On macOS 11.3.1, Core Audio calls AudioDeviceIOProc after calling an + * internal function named HALB_Mutex::Lock(), which locks a mutex in + * HALB_IOThread::Entry(void*). HALB_Mutex::Lock() is also called in + * AudioObjectGetPropertyData, which is called by coreaudio driver. + * Therefore, the specified callback must be designed to avoid a deadlock + * with the callers of AudioObjectGetPropertyData. + */ core->ioprocid = NULL; status = AudioDeviceCreateIOProcID(core->outputDeviceID, audioDeviceIOProc, @@ -521,6 +534,7 @@ static void update_device_playback_state(coreaudioVoiceOut *core) } } +/* called without iothread lock. */ static OSStatus handle_voice_change( AudioObjectID in_object_id, UInt32 in_number_addresses, @@ -530,9 +544,7 @@ static OSStatus handle_voice_change( OSStatus status; coreaudioVoiceOut *core = in_client_data; - if (coreaudio_lock(core, __func__)) { - abort(); - } + qemu_mutex_lock_iothread(); if (core->outputDeviceID) { fini_out_device(core); @@ -543,7 +555,7 @@ static OSStatus handle_voice_change( update_device_playback_state(core); } - coreaudio_unlock (core, __func__); + qemu_mutex_unlock_iothread(); return status; } @@ -558,14 +570,10 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, struct audsettings obt_as; /* create mutex */ - err = pthread_mutex_init(&core->mutex, NULL); + err = pthread_mutex_init(&core->buf_mutex, NULL); if (err) { dolog("Could not create mutex\nReason: %s\n", strerror (err)); - goto mutex_error; - } - - if (coreaudio_lock(core, __func__)) { - goto lock_error; + return -1; } obt_as = *as; @@ -584,37 +592,21 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, if (status != kAudioHardwareNoError) { coreaudio_playback_logerr (status, "Could not listen to voice property change\n"); - goto listener_error; + return -1; } if (init_out_device(core)) { - goto device_error; + status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, + &voice_addr, + handle_voice_change, + core); + if (status != kAudioHardwareNoError) { + coreaudio_playback_logerr(status, + "Could not remove voice property change listener\n"); + } } - coreaudio_unlock(core, __func__); return 0; - -device_error: - status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, - &voice_addr, - handle_voice_change, - core); - if (status != kAudioHardwareNoError) { - coreaudio_playback_logerr(status, - "Could not remove voice property change listener\n"); - } - -listener_error: - coreaudio_unlock(core, __func__); - -lock_error: - err = pthread_mutex_destroy(&core->mutex); - if (err) { - dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); - } - -mutex_error: - return -1; } static void coreaudio_fini_out (HWVoiceOut *hw) @@ -623,10 +615,6 @@ static void coreaudio_fini_out (HWVoiceOut *hw) int err; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - if (coreaudio_lock(core, __func__)) { - abort(); - } - status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &voice_addr, handle_voice_change, @@ -637,10 +625,8 @@ static void coreaudio_fini_out (HWVoiceOut *hw) fini_out_device(core); - coreaudio_unlock(core, __func__); - /* destroy mutex */ - err = pthread_mutex_destroy(&core->mutex); + err = pthread_mutex_destroy(&core->buf_mutex); if (err) { dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); } @@ -650,14 +636,8 @@ static void coreaudio_enable_out(HWVoiceOut *hw, bool enable) { coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - if (coreaudio_lock(core, __func__)) { - abort(); - } - core->enabled = enable; update_device_playback_state(core); - - coreaudio_unlock(core, __func__); } static void *coreaudio_audio_init(Audiodev *dev) diff --git a/block/snapshot.c b/block/snapshot.c index 6702c75e42..ccacda8bd5 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -275,13 +275,16 @@ int bdrv_snapshot_goto(BlockDriverState *bs, qobject_unref(file_options); g_free(subqdict_prefix); + /* Force .bdrv_open() below to re-attach fallback_bs on *fallback_ptr */ qdict_put_str(options, (*fallback_ptr)->name, bdrv_get_node_name(fallback_bs)); + /* Now close bs, apply the snapshot on fallback_bs, and re-open bs */ if (drv->bdrv_close) { drv->bdrv_close(bs); } + /* .bdrv_open() will re-attach it */ bdrv_unref_child(bs, *fallback_ptr); *fallback_ptr = NULL; @@ -296,7 +299,16 @@ int bdrv_snapshot_goto(BlockDriverState *bs, return ret < 0 ? ret : open_ret; } - assert(fallback_bs == (*fallback_ptr)->bs); + /* + * fallback_ptr is &bs->file or &bs->backing. *fallback_ptr + * was closed above and set to NULL, but the .bdrv_open() call + * has opened it again, because we set the respective option + * (with the qdict_put_str() call above). + * Assert that .bdrv_open() has attached some child on + * *fallback_ptr, and that it has attached the one we wanted + * it to (i.e., fallback_bs). + */ + assert(*fallback_ptr && fallback_bs == (*fallback_ptr)->bs); bdrv_unref(fallback_bs); return ret; } diff --git a/docs/devel/multi-thread-tcg.rst b/docs/devel/multi-thread-tcg.rst index 92a9eba13c..5b446ee08b 100644 --- a/docs/devel/multi-thread-tcg.rst +++ b/docs/devel/multi-thread-tcg.rst @@ -4,8 +4,9 @@ This work is licensed under the terms of the GNU GPL, version 2 or later. See the COPYING file in the top-level directory. -Introduction -============ +================== +Multi-threaded TCG +================== This document outlines the design for multi-threaded TCG (a.k.a MTTCG) system-mode emulation. user-mode emulation has always mirrored the diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 5cf121fe36..60f1f75e3a 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -229,6 +229,23 @@ static void continue_dma8 (SB16State *s) control (s, 1); } +static inline int restrict_sampling_rate(int freq) +{ + if (freq < SAMPLE_RATE_MIN) { + qemu_log_mask(LOG_GUEST_ERROR, + "sampling range too low: %d, increasing to %u\n", + freq, SAMPLE_RATE_MIN); + return SAMPLE_RATE_MIN; + } else if (freq > SAMPLE_RATE_MAX) { + qemu_log_mask(LOG_GUEST_ERROR, + "sampling range too high: %d, decreasing to %u\n", + freq, SAMPLE_RATE_MAX); + return SAMPLE_RATE_MAX; + } else { + return freq; + } +} + static void dma_cmd8 (SB16State *s, int mask, int dma_len) { s->fmt = AUDIO_FORMAT_U8; @@ -244,17 +261,7 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) int tmp = (256 - s->time_const); s->freq = (1000000 + (tmp / 2)) / tmp; } - if (s->freq < SAMPLE_RATE_MIN) { - qemu_log_mask(LOG_GUEST_ERROR, - "sampling range too low: %d, increasing to %u\n", - s->freq, SAMPLE_RATE_MIN); - s->freq = SAMPLE_RATE_MIN; - } else if (s->freq > SAMPLE_RATE_MAX) { - qemu_log_mask(LOG_GUEST_ERROR, - "sampling range too high: %d, decreasing to %u\n", - s->freq, SAMPLE_RATE_MAX); - s->freq = SAMPLE_RATE_MAX; - } + s->freq = restrict_sampling_rate(s->freq); if (dma_len != -1) { s->block_size = dma_len << s->fmt_stereo; @@ -768,7 +775,7 @@ static void complete (SB16State *s) * and FT2 sets output freq with this (go figure). Compare: * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate */ - s->freq = dsp_get_hilo (s); + s->freq = restrict_sampling_rate(dsp_get_hilo(s)); ldebug ("set freq %d\n", s->freq); break; diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c index 73b8f2e45b..fe4b6c3c9e 100644 --- a/hw/char/ibex_uart.c +++ b/hw/char/ibex_uart.c @@ -35,6 +35,43 @@ #include "qemu/log.h" #include "qemu/module.h" +REG32(INTR_STATE, 0x00) + FIELD(INTR_STATE, TX_WATERMARK, 0, 1) + FIELD(INTR_STATE, RX_WATERMARK, 1, 1) + FIELD(INTR_STATE, TX_EMPTY, 2, 1) + FIELD(INTR_STATE, RX_OVERFLOW, 3, 1) +REG32(INTR_ENABLE, 0x04) +REG32(INTR_TEST, 0x08) +REG32(CTRL, 0x0C) + FIELD(CTRL, TX_ENABLE, 0, 1) + FIELD(CTRL, RX_ENABLE, 1, 1) + FIELD(CTRL, NF, 2, 1) + FIELD(CTRL, SLPBK, 4, 1) + FIELD(CTRL, LLPBK, 5, 1) + FIELD(CTRL, PARITY_EN, 6, 1) + FIELD(CTRL, PARITY_ODD, 7, 1) + FIELD(CTRL, RXBLVL, 8, 2) + FIELD(CTRL, NCO, 16, 16) +REG32(STATUS, 0x10) + FIELD(STATUS, TXFULL, 0, 1) + FIELD(STATUS, RXFULL, 1, 1) + FIELD(STATUS, TXEMPTY, 2, 1) + FIELD(STATUS, RXIDLE, 4, 1) + FIELD(STATUS, RXEMPTY, 5, 1) +REG32(RDATA, 0x14) +REG32(WDATA, 0x18) +REG32(FIFO_CTRL, 0x1c) + FIELD(FIFO_CTRL, RXRST, 0, 1) + FIELD(FIFO_CTRL, TXRST, 1, 1) + FIELD(FIFO_CTRL, RXILVL, 2, 3) + FIELD(FIFO_CTRL, TXILVL, 5, 2) +REG32(FIFO_STATUS, 0x20) + FIELD(FIFO_STATUS, TXLVL, 0, 5) + FIELD(FIFO_STATUS, RXLVL, 16, 5) +REG32(OVRD, 0x24) +REG32(VAL, 0x28) +REG32(TIMEOUT_CTRL, 0x2c) + static void ibex_uart_update_irqs(IbexUartState *s) { if (s->uart_intr_state & s->uart_intr_enable & R_INTR_STATE_TX_WATERMARK_MASK) { diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c index fe12666789..278e21c434 100644 --- a/hw/char/sifive_uart.c +++ b/hw/char/sifive_uart.c @@ -19,10 +19,12 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/log.h" +#include "migration/vmstate.h" #include "chardev/char.h" #include "chardev/char-fe.h" #include "hw/irq.h" #include "hw/char/sifive_uart.h" +#include "hw/qdev-properties-system.h" /* * Not yet implemented: @@ -31,7 +33,7 @@ */ /* Returns the state of the IP (interrupt pending) register */ -static uint64_t uart_ip(SiFiveUARTState *s) +static uint64_t sifive_uart_ip(SiFiveUARTState *s) { uint64_t ret = 0; @@ -48,7 +50,7 @@ static uint64_t uart_ip(SiFiveUARTState *s) return ret; } -static void update_irq(SiFiveUARTState *s) +static void sifive_uart_update_irq(SiFiveUARTState *s) { int cond = 0; if ((s->ie & SIFIVE_UART_IE_TXWM) || @@ -63,7 +65,7 @@ static void update_irq(SiFiveUARTState *s) } static uint64_t -uart_read(void *opaque, hwaddr addr, unsigned int size) +sifive_uart_read(void *opaque, hwaddr addr, unsigned int size) { SiFiveUARTState *s = opaque; unsigned char r; @@ -74,7 +76,7 @@ uart_read(void *opaque, hwaddr addr, unsigned int size) memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1); s->rx_fifo_len--; qemu_chr_fe_accept_input(&s->chr); - update_irq(s); + sifive_uart_update_irq(s); return r; } return 0x80000000; @@ -84,7 +86,7 @@ uart_read(void *opaque, hwaddr addr, unsigned int size) case SIFIVE_UART_IE: return s->ie; case SIFIVE_UART_IP: - return uart_ip(s); + return sifive_uart_ip(s); case SIFIVE_UART_TXCTRL: return s->txctrl; case SIFIVE_UART_RXCTRL: @@ -99,8 +101,8 @@ uart_read(void *opaque, hwaddr addr, unsigned int size) } static void -uart_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) +sifive_uart_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) { SiFiveUARTState *s = opaque; uint32_t value = val64; @@ -109,11 +111,11 @@ uart_write(void *opaque, hwaddr addr, switch (addr) { case SIFIVE_UART_TXFIFO: qemu_chr_fe_write(&s->chr, &ch, 1); - update_irq(s); + sifive_uart_update_irq(s); return; case SIFIVE_UART_IE: s->ie = val64; - update_irq(s); + sifive_uart_update_irq(s); return; case SIFIVE_UART_TXCTRL: s->txctrl = val64; @@ -129,9 +131,9 @@ uart_write(void *opaque, hwaddr addr, __func__, (int)addr, (int)value); } -static const MemoryRegionOps uart_ops = { - .read = uart_read, - .write = uart_write, +static const MemoryRegionOps sifive_uart_ops = { + .read = sifive_uart_read, + .write = sifive_uart_write, .endianness = DEVICE_NATIVE_ENDIAN, .valid = { .min_access_size = 4, @@ -139,7 +141,7 @@ static const MemoryRegionOps uart_ops = { } }; -static void uart_rx(void *opaque, const uint8_t *buf, int size) +static void sifive_uart_rx(void *opaque, const uint8_t *buf, int size) { SiFiveUARTState *s = opaque; @@ -150,43 +152,137 @@ static void uart_rx(void *opaque, const uint8_t *buf, int size) } s->rx_fifo[s->rx_fifo_len++] = *buf; - update_irq(s); + sifive_uart_update_irq(s); } -static int uart_can_rx(void *opaque) +static int sifive_uart_can_rx(void *opaque) { SiFiveUARTState *s = opaque; return s->rx_fifo_len < sizeof(s->rx_fifo); } -static void uart_event(void *opaque, QEMUChrEvent event) +static void sifive_uart_event(void *opaque, QEMUChrEvent event) { } -static int uart_be_change(void *opaque) +static int sifive_uart_be_change(void *opaque) { SiFiveUARTState *s = opaque; - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, - uart_be_change, s, NULL, true); + qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, + sifive_uart_event, sifive_uart_be_change, s, + NULL, true); return 0; } +static Property sifive_uart_properties[] = { + DEFINE_PROP_CHR("chardev", SiFiveUARTState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_uart_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + SiFiveUARTState *s = SIFIVE_UART(obj); + + memory_region_init_io(&s->mmio, OBJECT(s), &sifive_uart_ops, s, + TYPE_SIFIVE_UART, SIFIVE_UART_MAX); + sysbus_init_mmio(sbd, &s->mmio); + sysbus_init_irq(sbd, &s->irq); +} + +static void sifive_uart_realize(DeviceState *dev, Error **errp) +{ + SiFiveUARTState *s = SIFIVE_UART(dev); + + qemu_chr_fe_set_handlers(&s->chr, sifive_uart_can_rx, sifive_uart_rx, + sifive_uart_event, sifive_uart_be_change, s, + NULL, true); + +} + +static void sifive_uart_reset_enter(Object *obj, ResetType type) +{ + SiFiveUARTState *s = SIFIVE_UART(obj); + s->ie = 0; + s->ip = 0; + s->txctrl = 0; + s->rxctrl = 0; + s->div = 0; + s->rx_fifo_len = 0; +} + +static void sifive_uart_reset_hold(Object *obj) +{ + SiFiveUARTState *s = SIFIVE_UART(obj); + qemu_irq_lower(s->irq); +} + +static const VMStateDescription vmstate_sifive_uart = { + .name = TYPE_SIFIVE_UART, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(rx_fifo, SiFiveUARTState, + SIFIVE_UART_RX_FIFO_SIZE), + VMSTATE_UINT8(rx_fifo_len, SiFiveUARTState), + VMSTATE_UINT32(ie, SiFiveUARTState), + VMSTATE_UINT32(ip, SiFiveUARTState), + VMSTATE_UINT32(txctrl, SiFiveUARTState), + VMSTATE_UINT32(rxctrl, SiFiveUARTState), + VMSTATE_UINT32(div, SiFiveUARTState), + VMSTATE_END_OF_LIST() + }, +}; + + +static void sifive_uart_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + ResettableClass *rc = RESETTABLE_CLASS(oc); + + dc->realize = sifive_uart_realize; + dc->vmsd = &vmstate_sifive_uart; + rc->phases.enter = sifive_uart_reset_enter; + rc->phases.hold = sifive_uart_reset_hold; + device_class_set_props(dc, sifive_uart_properties); +} + +static const TypeInfo sifive_uart_info = { + .name = TYPE_SIFIVE_UART, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveUARTState), + .instance_init = sifive_uart_init, + .class_init = sifive_uart_class_init, +}; + +static void sifive_uart_register_types(void) +{ + type_register_static(&sifive_uart_info); +} + +type_init(sifive_uart_register_types) + /* * Create UART device. */ SiFiveUARTState *sifive_uart_create(MemoryRegion *address_space, hwaddr base, Chardev *chr, qemu_irq irq) { - SiFiveUARTState *s = g_malloc0(sizeof(SiFiveUARTState)); - s->irq = irq; - qemu_chr_fe_init(&s->chr, chr, &error_abort); - qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx, uart_event, - uart_be_change, s, NULL, true); - memory_region_init_io(&s->mmio, NULL, &uart_ops, s, - TYPE_SIFIVE_UART, SIFIVE_UART_MAX); - memory_region_add_subregion(address_space, base, &s->mmio); - return s; + DeviceState *dev; + SysBusDevice *s; + SiFiveUARTState *r; + + dev = qdev_new("riscv.sifive.uart"); + s = SYS_BUS_DEVICE(dev); + qdev_prop_set_chr(dev, "chardev", chr); + sysbus_realize_and_unref(s, &error_fatal); + memory_region_add_subregion(address_space, base, + sysbus_mmio_get_region(s, 0)); + sysbus_connect_irq(s, 0, irq); + + r = SIFIVE_UART(dev); + return r; } diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 7545dcda9c..c5a7e3bacb 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -36,7 +36,7 @@ static const MemMapEntry ibex_memmap[] = { [IBEX_DEV_SPI] = { 0x40050000, 0x1000 }, [IBEX_DEV_I2C] = { 0x40080000, 0x1000 }, [IBEX_DEV_PATTGEN] = { 0x400e0000, 0x1000 }, - [IBEX_DEV_RV_TIMER] = { 0x40100000, 0x1000 }, + [IBEX_DEV_TIMER] = { 0x40100000, 0x1000 }, [IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 }, [IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 }, [IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 }, @@ -106,6 +106,8 @@ static void lowrisc_ibex_soc_init(Object *obj) object_initialize_child(obj, "plic", &s->plic, TYPE_IBEX_PLIC); object_initialize_child(obj, "uart", &s->uart, TYPE_IBEX_UART); + + object_initialize_child(obj, "timer", &s->timer, TYPE_IBEX_TIMER); } static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) @@ -159,6 +161,14 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) 3, qdev_get_gpio_in(DEVICE(&s->plic), IBEX_UART0_RX_OVERFLOW_IRQ)); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer), 0, memmap[IBEX_DEV_TIMER].base); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), + 0, qdev_get_gpio_in(DEVICE(&s->plic), + IBEX_TIMER_TIMEREXPIRED0_0)); + create_unimplemented_device("riscv.lowrisc.ibex.gpio", memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size); create_unimplemented_device("riscv.lowrisc.ibex.spi", @@ -167,8 +177,6 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) memmap[IBEX_DEV_I2C].base, memmap[IBEX_DEV_I2C].size); create_unimplemented_device("riscv.lowrisc.ibex.pattgen", memmap[IBEX_DEV_PATTGEN].base, memmap[IBEX_DEV_PATTGEN].size); - create_unimplemented_device("riscv.lowrisc.ibex.rv_timer", - memmap[IBEX_DEV_RV_TIMER].base, memmap[IBEX_DEV_RV_TIMER].size); create_unimplemented_device("riscv.lowrisc.ibex.sensor_ctrl", memmap[IBEX_DEV_SENSOR_CTRL].base, memmap[IBEX_DEV_SENSOR_CTRL].size); create_unimplemented_device("riscv.lowrisc.ibex.otp_ctrl", diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c new file mode 100644 index 0000000000..5befb53506 --- /dev/null +++ b/hw/timer/ibex_timer.c @@ -0,0 +1,305 @@ +/* + * QEMU lowRISC Ibex Timer device + * + * Copyright (c) 2021 Western Digital + * + * For details check the documentation here: + * https://docs.opentitan.org/hw/ip/rv_timer/doc/ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "hw/timer/ibex_timer.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "target/riscv/cpu.h" +#include "migration/vmstate.h" + +REG32(CTRL, 0x00) + FIELD(CTRL, ACTIVE, 0, 1) +REG32(CFG0, 0x100) + FIELD(CFG0, PRESCALE, 0, 12) + FIELD(CFG0, STEP, 16, 8) +REG32(LOWER0, 0x104) +REG32(UPPER0, 0x108) +REG32(COMPARE_LOWER0, 0x10C) +REG32(COMPARE_UPPER0, 0x110) +REG32(INTR_ENABLE, 0x114) + FIELD(INTR_ENABLE, IE_0, 0, 1) +REG32(INTR_STATE, 0x118) + FIELD(INTR_STATE, IS_0, 0, 1) +REG32(INTR_TEST, 0x11C) + FIELD(INTR_TEST, T_0, 0, 1) + +static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + timebase_freq, NANOSECONDS_PER_SECOND); +} + +static void ibex_timer_update_irqs(IbexTimerState *s) +{ + CPUState *cs = qemu_get_cpu(0); + RISCVCPU *cpu = RISCV_CPU(cs); + uint64_t value = s->timer_compare_lower0 | + ((uint64_t)s->timer_compare_upper0 << 32); + uint64_t next, diff; + uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); + + if (!(s->timer_ctrl & R_CTRL_ACTIVE_MASK)) { + /* Timer isn't active */ + return; + } + + /* Update the CPUs mtimecmp */ + cpu->env.timecmp = value; + + if (cpu->env.timecmp <= now) { + /* + * If the mtimecmp was in the past raise the interrupt now. + */ + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1)); + if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; + qemu_set_irq(s->irq, true); + } + return; + } + + /* Setup a timer to trigger the interrupt in the future */ + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0)); + qemu_set_irq(s->irq, false); + + diff = cpu->env.timecmp - now; + next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + muldiv64(diff, + NANOSECONDS_PER_SECOND, + s->timebase_freq); + + if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { + /* We overflowed the timer, just set it as large as we can */ + timer_mod(cpu->env.timer, 0x7FFFFFFFFFFFFFFF); + } else { + timer_mod(cpu->env.timer, next); + } +} + +static void ibex_timer_cb(void *opaque) +{ + IbexTimerState *s = opaque; + CPUState *cs = qemu_get_cpu(0); + RISCVCPU *cpu = RISCV_CPU(cs); + + riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1)); + if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) { + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; + qemu_set_irq(s->irq, true); + } +} + +static void ibex_timer_reset(DeviceState *dev) +{ + IbexTimerState *s = IBEX_TIMER(dev); + + CPUState *cpu = qemu_get_cpu(0); + CPURISCVState *env = cpu->env_ptr; + env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + &ibex_timer_cb, s); + env->timecmp = 0; + + s->timer_ctrl = 0x00000000; + s->timer_cfg0 = 0x00010000; + s->timer_compare_lower0 = 0xFFFFFFFF; + s->timer_compare_upper0 = 0xFFFFFFFF; + s->timer_intr_enable = 0x00000000; + s->timer_intr_state = 0x00000000; + s->timer_intr_test = 0x00000000; + + ibex_timer_update_irqs(s); +} + +static uint64_t ibex_timer_read(void *opaque, hwaddr addr, + unsigned int size) +{ + IbexTimerState *s = opaque; + uint64_t now = cpu_riscv_read_rtc(s->timebase_freq); + uint64_t retvalue = 0; + + switch (addr >> 2) { + case R_CTRL: + retvalue = s->timer_ctrl; + break; + case R_CFG0: + retvalue = s->timer_cfg0; + break; + case R_LOWER0: + retvalue = now; + break; + case R_UPPER0: + retvalue = now >> 32; + break; + case R_COMPARE_LOWER0: + retvalue = s->timer_compare_lower0; + break; + case R_COMPARE_UPPER0: + retvalue = s->timer_compare_upper0; + break; + case R_INTR_ENABLE: + retvalue = s->timer_intr_enable; + break; + case R_INTR_STATE: + retvalue = s->timer_intr_state; + break; + case R_INTR_TEST: + retvalue = s->timer_intr_test; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + return 0; + } + + return retvalue; +} + +static void ibex_timer_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + IbexTimerState *s = opaque; + uint32_t val = val64; + + switch (addr >> 2) { + case R_CTRL: + s->timer_ctrl = val; + break; + case R_CFG0: + qemu_log_mask(LOG_UNIMP, "Changing prescale or step not supported"); + s->timer_cfg0 = val; + break; + case R_LOWER0: + qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); + break; + case R_UPPER0: + qemu_log_mask(LOG_UNIMP, "Changing timer value is not supported"); + break; + case R_COMPARE_LOWER0: + s->timer_compare_lower0 = val; + ibex_timer_update_irqs(s); + break; + case R_COMPARE_UPPER0: + s->timer_compare_upper0 = val; + ibex_timer_update_irqs(s); + break; + case R_INTR_ENABLE: + s->timer_intr_enable = val; + break; + case R_INTR_STATE: + /* Write 1 to clear */ + s->timer_intr_state &= ~val; + break; + case R_INTR_TEST: + s->timer_intr_test = val; + if (s->timer_intr_enable & + s->timer_intr_test & + R_INTR_ENABLE_IE_0_MASK) { + s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; + qemu_set_irq(s->irq, true); + } + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + } +} + +static const MemoryRegionOps ibex_timer_ops = { + .read = ibex_timer_read, + .write = ibex_timer_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl.min_access_size = 4, + .impl.max_access_size = 4, +}; + +static int ibex_timer_post_load(void *opaque, int version_id) +{ + IbexTimerState *s = opaque; + + ibex_timer_update_irqs(s); + return 0; +} + +static const VMStateDescription vmstate_ibex_timer = { + .name = TYPE_IBEX_TIMER, + .version_id = 1, + .minimum_version_id = 1, + .post_load = ibex_timer_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(timer_ctrl, IbexTimerState), + VMSTATE_UINT32(timer_cfg0, IbexTimerState), + VMSTATE_UINT32(timer_compare_lower0, IbexTimerState), + VMSTATE_UINT32(timer_compare_upper0, IbexTimerState), + VMSTATE_UINT32(timer_intr_enable, IbexTimerState), + VMSTATE_UINT32(timer_intr_state, IbexTimerState), + VMSTATE_UINT32(timer_intr_test, IbexTimerState), + VMSTATE_END_OF_LIST() + } +}; + +static Property ibex_timer_properties[] = { + DEFINE_PROP_UINT32("timebase-freq", IbexTimerState, timebase_freq, 10000), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ibex_timer_init(Object *obj) +{ + IbexTimerState *s = IBEX_TIMER(obj); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + memory_region_init_io(&s->mmio, obj, &ibex_timer_ops, s, + TYPE_IBEX_TIMER, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); +} + +static void ibex_timer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = ibex_timer_reset; + dc->vmsd = &vmstate_ibex_timer; + device_class_set_props(dc, ibex_timer_properties); +} + +static const TypeInfo ibex_timer_info = { + .name = TYPE_IBEX_TIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IbexTimerState), + .instance_init = ibex_timer_init, + .class_init = ibex_timer_class_init, +}; + +static void ibex_timer_register_types(void) +{ + type_register_static(&ibex_timer_info); +} + +type_init(ibex_timer_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 157f540ecd..1aa3cd2284 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -33,5 +33,6 @@ softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c')) softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) +specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h index 546f958eb8..a39985516a 100644 --- a/include/hw/char/ibex_uart.h +++ b/include/hw/char/ibex_uart.h @@ -31,43 +31,6 @@ #include "qemu/timer.h" #include "qom/object.h" -REG32(INTR_STATE, 0x00) - FIELD(INTR_STATE, TX_WATERMARK, 0, 1) - FIELD(INTR_STATE, RX_WATERMARK, 1, 1) - FIELD(INTR_STATE, TX_EMPTY, 2, 1) - FIELD(INTR_STATE, RX_OVERFLOW, 3, 1) -REG32(INTR_ENABLE, 0x04) -REG32(INTR_TEST, 0x08) -REG32(CTRL, 0x0C) - FIELD(CTRL, TX_ENABLE, 0, 1) - FIELD(CTRL, RX_ENABLE, 1, 1) - FIELD(CTRL, NF, 2, 1) - FIELD(CTRL, SLPBK, 4, 1) - FIELD(CTRL, LLPBK, 5, 1) - FIELD(CTRL, PARITY_EN, 6, 1) - FIELD(CTRL, PARITY_ODD, 7, 1) - FIELD(CTRL, RXBLVL, 8, 2) - FIELD(CTRL, NCO, 16, 16) -REG32(STATUS, 0x10) - FIELD(STATUS, TXFULL, 0, 1) - FIELD(STATUS, RXFULL, 1, 1) - FIELD(STATUS, TXEMPTY, 2, 1) - FIELD(STATUS, RXIDLE, 4, 1) - FIELD(STATUS, RXEMPTY, 5, 1) -REG32(RDATA, 0x14) -REG32(WDATA, 0x18) -REG32(FIFO_CTRL, 0x1c) - FIELD(FIFO_CTRL, RXRST, 0, 1) - FIELD(FIFO_CTRL, TXRST, 1, 1) - FIELD(FIFO_CTRL, RXILVL, 2, 3) - FIELD(FIFO_CTRL, TXILVL, 5, 2) -REG32(FIFO_STATUS, 0x20) - FIELD(FIFO_STATUS, TXLVL, 0, 5) - FIELD(FIFO_STATUS, RXLVL, 16, 5) -REG32(OVRD, 0x24) -REG32(VAL, 0x28) -REG32(TIMEOUT_CTRL, 0x2c) - #define IBEX_UART_TX_FIFO_SIZE 16 #define IBEX_UART_CLOCK 50000000 /* 50MHz clock */ diff --git a/include/hw/char/sifive_uart.h b/include/hw/char/sifive_uart.h index 3e962be659..7f6c79f8bd 100644 --- a/include/hw/char/sifive_uart.h +++ b/include/hw/char/sifive_uart.h @@ -21,6 +21,7 @@ #define HW_SIFIVE_UART_H #include "chardev/char-fe.h" +#include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "qom/object.h" @@ -49,12 +50,10 @@ enum { #define SIFIVE_UART_GET_TXCNT(txctrl) ((txctrl >> 16) & 0x7) #define SIFIVE_UART_GET_RXCNT(rxctrl) ((rxctrl >> 16) & 0x7) +#define SIFIVE_UART_RX_FIFO_SIZE 8 #define TYPE_SIFIVE_UART "riscv.sifive.uart" - -typedef struct SiFiveUARTState SiFiveUARTState; -DECLARE_INSTANCE_CHECKER(SiFiveUARTState, SIFIVE_UART, - TYPE_SIFIVE_UART) +OBJECT_DECLARE_SIMPLE_TYPE(SiFiveUARTState, SIFIVE_UART) struct SiFiveUARTState { /*< private >*/ @@ -64,8 +63,8 @@ struct SiFiveUARTState { qemu_irq irq; MemoryRegion mmio; CharBackend chr; - uint8_t rx_fifo[8]; - unsigned int rx_fifo_len; + uint8_t rx_fifo[SIFIVE_UART_RX_FIFO_SIZE]; + uint8_t rx_fifo_len; uint32_t ie; uint32_t ip; uint32_t txctrl; diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index aab9bc9245..86cceef698 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -22,6 +22,7 @@ #include "hw/riscv/riscv_hart.h" #include "hw/intc/ibex_plic.h" #include "hw/char/ibex_uart.h" +#include "hw/timer/ibex_timer.h" #include "qom/object.h" #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc" @@ -35,6 +36,7 @@ struct LowRISCIbexSoCState { RISCVHartArrayState cpus; IbexPlicState plic; IbexUartState uart; + IbexTimerState timer; MemoryRegion flash_mem; MemoryRegion rom; @@ -57,7 +59,7 @@ enum { IBEX_DEV_SPI, IBEX_DEV_I2C, IBEX_DEV_PATTGEN, - IBEX_DEV_RV_TIMER, + IBEX_DEV_TIMER, IBEX_DEV_SENSOR_CTRL, IBEX_DEV_OTP_CTRL, IBEX_DEV_PWRMGR, @@ -82,6 +84,7 @@ enum { }; enum { + IBEX_TIMER_TIMEREXPIRED0_0 = 125, IBEX_UART0_RX_PARITY_ERR_IRQ = 8, IBEX_UART0_RX_TIMEOUT_IRQ = 7, IBEX_UART0_RX_BREAK_ERR_IRQ = 6, diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h new file mode 100644 index 0000000000..6a43537003 --- /dev/null +++ b/include/hw/timer/ibex_timer.h @@ -0,0 +1,52 @@ +/* + * QEMU lowRISC Ibex Timer device + * + * Copyright (c) 2021 Western Digital + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_IBEX_TIMER_H +#define HW_IBEX_TIMER_H + +#include "hw/sysbus.h" + +#define TYPE_IBEX_TIMER "ibex-timer" +OBJECT_DECLARE_SIMPLE_TYPE(IbexTimerState, IBEX_TIMER) + +struct IbexTimerState { + /* <private> */ + SysBusDevice parent_obj; + + /* <public> */ + MemoryRegion mmio; + + uint32_t timer_ctrl; + uint32_t timer_cfg0; + uint32_t timer_compare_lower0; + uint32_t timer_compare_upper0; + uint32_t timer_intr_enable; + uint32_t timer_intr_state; + uint32_t timer_intr_test; + + uint32_t timebase_freq; + + qemu_irq irq; +}; +#endif /* HW_IBEX_TIMER_H */ diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 97cdfd7761..dc3496f36c 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -526,6 +526,15 @@ qemu_plugin_register_vcpu_syscall_ret_cb(qemu_plugin_id_t id, char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn); /** + * qemu_plugin_insn_symbol() - best effort symbol lookup + * @insn: instruction reference + * + * Return a static string referring to the symbol. This is dependent + * on the binary QEMU is running having provided a symbol table. + */ +const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn); + +/** * qemu_plugin_vcpu_for_each() - iterate over the existing vCPU * @id: plugin ID * @cb: callback function diff --git a/meson.build b/meson.build index d8a92666fb..a91b39465c 100644 --- a/meson.build +++ b/meson.build @@ -1882,7 +1882,7 @@ if have_system or have_user 'target/hppa', 'target/i386', 'target/i386/kvm', - 'target/mips', + 'target/mips/tcg', 'target/ppc', 'target/riscv', 'target/s390x', diff --git a/plugins/api.c b/plugins/api.c index 817c9b6b69..332e2c60e2 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -233,6 +233,12 @@ char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) return plugin_disas(cpu, insn->vaddr, insn->data->len); } +const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn) +{ + const char *sym = lookup_symbol(insn->vaddr); + return sym[0] != 0 ? sym : NULL; +} + /* * The memory queries allow the plugin to query information about a * memory access. diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index bbcd25ae05..cb8eff233e 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -399,7 +399,12 @@ if ($chk_branch) { my $num_patches = @patches; for my $hash (@patches) { my $FILE; - open($FILE, '-|', "git", "show", "--patch-with-stat", $hash) || + open($FILE, '-|', "git", + "-c", "diff.renamelimit=0", + "-c", "diff.renames=True", + "-c", "diff.algorithm=histogram", + "show", + "--patch-with-stat", $hash) || die "$P: git show $hash - $!\n"; while (<$FILE>) { chomp; diff --git a/target/mips/cpu.c b/target/mips/cpu.c index 96236abc00..d426918291 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -35,7 +35,7 @@ #include "qapi/qapi-commands-machine-target.h" #include "fpu_helper.h" -const char regnames[32][4] = { +const char regnames[32][3] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 075c24abda..1dfe69c6c0 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1152,13 +1152,13 @@ struct CPUMIPSState { CPUMIPSMVPContext *mvp; #if !defined(CONFIG_USER_ONLY) CPUMIPSTLBContext *tlb; + void *irq[8]; + struct MIPSITUState *itu; + MemoryRegion *itc_tag; /* ITC Configuration Tags */ #endif const mips_def_t *cpu_model; - void *irq[8]; QEMUTimer *timer; /* Internal timer */ - struct MIPSITUState *itu; - MemoryRegion *itc_tag; /* ITC Configuration Tags */ target_ulong exception_base; /* ExceptionBase input to the core */ uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */ }; @@ -1316,12 +1316,16 @@ uint64_t cpu_mips_phys_to_kseg1(void *opaque, uint64_t addr); bool mips_um_ksegs_enabled(void); void mips_um_ksegs_enable(void); +#if !defined(CONFIG_USER_ONLY) + /* mips_int.c */ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); /* mips_itu.c */ void itc_reconfigure(struct MIPSITUState *tag); +#endif /* !CONFIG_USER_ONLY */ + /* helper.c */ target_ulong exception_resume_pc(CPUMIPSState *env); diff --git a/target/mips/internal.h b/target/mips/internal.h index 18d5da64a5..eecdd10116 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -74,7 +74,7 @@ struct mips_def_t { int32_t SAARP; }; -extern const char regnames[32][4]; +extern const char regnames[32][3]; extern const char fregnames[32][4]; extern const struct mips_def_t mips_defs[]; diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build index 5d8acbaf0d..bf4001e574 100644 --- a/target/mips/tcg/meson.build +++ b/target/mips/tcg/meson.build @@ -1,8 +1,7 @@ gen = [ decodetree.process('mips32r6.decode', extra_args: '--static-decode=decode_mips32r6'), decodetree.process('mips64r6.decode', extra_args: '--static-decode=decode_mips64r6'), - decodetree.process('msa32.decode', extra_args: '--static-decode=decode_msa32'), - decodetree.process('msa64.decode', extra_args: '--static-decode=decode_msa64'), + decodetree.process('msa.decode', extra_args: '--decode=decode_ase_msa'), decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'), ] diff --git a/target/mips/tcg/msa32.decode b/target/mips/tcg/msa.decode index ca200e373b..bf132e36b9 100644 --- a/target/mips/tcg/msa32.decode +++ b/target/mips/tcg/msa.decode @@ -6,9 +6,10 @@ # # Reference: # MIPS Architecture for Programmers Volume IV-j -# The MIPS32 SIMD Architecture Module, Revision 1.12 -# (Document Number: MD00866-2B-MSA32-AFP-01.12) -# +# - The MIPS32 SIMD Architecture Module, Revision 1.12 +# (Document Number: MD00866-2B-MSA32-AFP-01.12) +# - The MIPS64 SIMD Architecture Module, Revision 1.12 +# (Document Number: MD00868-1D-MSA64-AFP-01.12) &rtype rs rt rd sa @@ -19,6 +20,7 @@ @bz_df ...... ... df:2 wt:5 s16:16 &msa_bz LSA 000000 ..... ..... ..... 000 .. 000101 @lsa +DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa BZ_V 010001 01011 ..... ................ @bz BNZ_V 010001 01111 ..... ................ @bz diff --git a/target/mips/tcg/msa64.decode b/target/mips/tcg/msa64.decode deleted file mode 100644 index d2442474d0..0000000000 --- a/target/mips/tcg/msa64.decode +++ /dev/null @@ -1,17 +0,0 @@ -# MIPS SIMD Architecture Module instruction set -# -# Copyright (C) 2020 Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# Reference: -# MIPS Architecture for Programmers Volume IV-j -# The MIPS64 SIMD Architecture Module, Revision 1.12 -# (Document Number: MD00868-1D-MSA64-AFP-01.12) -# - -&rtype rs rt rd sa !extern - -@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &rtype - -DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index ae6587edf6..eed2eca6c9 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -18,8 +18,7 @@ #include "internal.h" /* Include the auto-generated decoder. */ -#include "decode-msa32.c.inc" -#include "decode-msa64.c.inc" +#include "decode-msa.c.inc" #define OPC_MSA (0x1E << 26) @@ -255,7 +254,7 @@ enum { OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09, }; -static const char * const msaregnames[] = { +static const char msaregnames[][6] = { "w0.d0", "w0.d1", "w1.d0", "w1.d1", "w2.d0", "w2.d1", "w3.d0", "w3.d1", "w4.d0", "w4.d1", "w5.d0", "w5.d1", @@ -2162,7 +2161,7 @@ static void gen_msa_vec(DisasContext *ctx) } } -static void gen_msa(DisasContext *ctx) +static bool trans_MSA(DisasContext *ctx, arg_MSA *a) { uint32_t opcode = ctx->opcode; @@ -2258,11 +2257,6 @@ static void gen_msa(DisasContext *ctx) gen_reserved_instruction(ctx); break; } -} - -static bool trans_MSA(DisasContext *ctx, arg_MSA *a) -{ - gen_msa(ctx); return true; } @@ -2274,13 +2268,8 @@ static bool trans_LSA(DisasContext *ctx, arg_rtype *a) static bool trans_DLSA(DisasContext *ctx, arg_rtype *a) { - return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa); -} - -bool decode_ase_msa(DisasContext *ctx, uint32_t insn) -{ - if (TARGET_LONG_BITS == 64 && decode_msa64(ctx, insn)) { - return true; + if (TARGET_LONG_BITS != 64) { + return false; } - return decode_msa32(ctx, insn); + return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa); } diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c index fb0a811af6..963d4ba8b1 100644 --- a/target/mips/tcg/mxu_translate.c +++ b/target/mips/tcg/mxu_translate.c @@ -447,9 +447,9 @@ enum { static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; static TCGv mxu_CR; -static const char * const mxuregnames[] = { +static const char mxuregnames[][4] = { "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", - "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR", + "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "XCR", }; void mxu_translate_init(void) diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c index 6de60fa6dd..77108b0b1a 100644 --- a/target/mips/tcg/sysemu/mips-semi.c +++ b/target/mips/tcg/sysemu/mips-semi.c @@ -75,7 +75,7 @@ enum UHIOpenFlags { }; /* Errno values taken from asm-mips/errno.h */ -static uint16_t host_to_mips_errno[] = { +static const uint16_t host_to_mips_errno[] = { [ENAMETOOLONG] = 78, #ifdef EOVERFLOW [EOVERFLOW] = 79, diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index 259f780d19..a150a014ec 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -17,6 +17,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "cpu.h" #include "internal.h" @@ -659,7 +660,7 @@ static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, w = directory_index - 1; if (directory_index & 0x1) { /* Generate adjacent page from same PTE for odd TLB page */ - lsb = (1 << w) >> 6; + lsb = BIT_ULL(w) >> 6; *pw_entrylo0 = entry & ~lsb; /* even page */ *pw_entrylo1 = entry | lsb; /* odd page */ } else if (dph) { diff --git a/target/mips/trace-events b/target/mips/tcg/trace-events index 0c55e0bbad..0c55e0bbad 100644 --- a/target/mips/trace-events +++ b/target/mips/tcg/trace-events diff --git a/target/mips/tcg/trace.h b/target/mips/tcg/trace.h new file mode 100644 index 0000000000..b8c6c4568e --- /dev/null +++ b/target/mips/tcg/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_mips_tcg.h" diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 797eba4434..b4a454ec09 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -31,7 +31,7 @@ #include "exec/helper-gen.h" #include "semihosting/semihost.h" -#include "target/mips/trace.h" +#include "trace.h" #include "trace-tcg.h" #include "exec/translator.h" #include "exec/log.h" @@ -1280,11 +1280,11 @@ TCGv_i64 fpu_f64[32]; #define DISAS_STOP DISAS_TARGET_0 #define DISAS_EXIT DISAS_TARGET_1 -static const char * const regnames_HI[] = { +static const char regnames_HI[][4] = { "HI0", "HI1", "HI2", "HI3", }; -static const char * const regnames_LO[] = { +static const char regnames_LO[][4] = { "LO0", "LO1", "LO2", "LO3", }; @@ -12151,8 +12151,8 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) tcg_gen_lookup_and_goto_ptr(); break; default: - fprintf(stderr, "unknown branch 0x%x\n", proc_hflags); - abort(); + LOG_DISAS("unknown branch 0x%x\n", proc_hflags); + gen_reserved_instruction(ctx); } } } @@ -14076,8 +14076,6 @@ enum { BGEZALS = 0x13, BC2F = 0x14, BC2T = 0x15, - BPOSGE64 = 0x1a, - BPOSGE32 = 0x1b, /* These overlap and are distinguished by bit16 of the instruction */ BC1F = 0x1c, BC1T = 0x1d, @@ -16121,10 +16119,6 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) generate_exception_err(ctx, EXCP_CpU, 1); } break; - case BPOSGE64: - case BPOSGE32: - /* MIPS DSP: not implemented */ - /* Fall through */ default: MIPS_INVAL("pool32i"); gen_reserved_instruction(ctx); @@ -20182,6 +20176,8 @@ static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, tcg_gen_movi_tl(tv0, rd >> 3); tcg_gen_movi_tl(tv1, imm); gen_helper_shilo(tv0, tv1, cpu_env); + tcg_temp_free(tv1); + tcg_temp_free(tv0); } break; case NM_MULEQ_S_W_PHL: @@ -20296,6 +20292,10 @@ static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, gen_reserved_instruction(ctx); break; } + + tcg_temp_free(v2_t); + tcg_temp_free(v1_t); + tcg_temp_free(t0); } static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) @@ -21137,7 +21137,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) extract32(ctx->opcode, 0, 1) << 13; gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, - imm); + imm << 1); } break; default: @@ -21572,14 +21572,6 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) } -/* SmartMIPS extension to MIPS32 */ - -#if defined(TARGET_MIPS64) - -/* MDMX extension to MIPS64 */ - -#endif - /* MIPSDSP functions. */ static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, int rd, int base, int offset) @@ -24373,10 +24365,11 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx) { TCGv t0, t1; + check_dsp(ctx); + if (rt == 0) { break; } - check_dsp(ctx); t0 = tcg_temp_new(); t1 = tcg_temp_new(); diff --git a/target/mips/translate.h b/target/mips/tcg/translate.h index 6144259034..6144259034 100644 --- a/target/mips/translate.h +++ b/target/mips/tcg/translate.h diff --git a/target/mips/trace.h b/target/mips/trace.h deleted file mode 100644 index f25b88ca6f..0000000000 --- a/target/mips/trace.h +++ /dev/null @@ -1 +0,0 @@ -#include "trace/trace-target_mips.h" diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index ca78682cf4..a7a9c0b1fe 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -170,7 +170,7 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) for (i = 0; i < CSR_TABLE_SIZE; i++) { predicate = csr_ops[i].predicate; - if (predicate && !predicate(env, i)) { + if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) { if (csr_ops[i].name) { g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name); } else { diff --git a/target/riscv/translate.c b/target/riscv/translate.c index c6e8739614..62a7d7e4c7 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -47,7 +47,7 @@ typedef struct DisasContext { bool virt_enabled; uint32_t opcode; uint32_t mstatus_fs; - uint32_t misa; + target_ulong misa; uint32_t mem_idx; /* Remember the rounding mode encoded in the previous fp instruction, which we have already installed into env->fp_status. Or -1 for diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index 314370fd1f..4c8a5994b2 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -75,10 +75,11 @@ class BootLinuxAarch64(LinuxTest): self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') - def test_virt_tcg(self): + def test_virt_tcg_gicv2(self): """ :avocado: tags=accel:tcg :avocado: tags=cpu:max + :avocado: tags=device:gicv2 """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") @@ -87,29 +88,28 @@ class BootLinuxAarch64(LinuxTest): self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) - def test_virt_kvm_gicv2(self): + def test_virt_tcg_gicv3(self): """ - :avocado: tags=accel:kvm - :avocado: tags=cpu:host - :avocado: tags=device:gicv2 + :avocado: tags=accel:tcg + :avocado: tags=cpu:max + :avocado: tags=device:gicv3 """ - self.require_accelerator("kvm") - self.vm.add_args("-accel", "kvm") - self.vm.add_args("-cpu", "host") - self.vm.add_args("-machine", "virt,gic-version=2") + self.require_accelerator("tcg") + self.vm.add_args("-accel", "tcg") + self.vm.add_args("-cpu", "max") + self.vm.add_args("-machine", "virt,gic-version=3") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) - def test_virt_kvm_gicv3(self): + def test_virt_kvm(self): """ :avocado: tags=accel:kvm :avocado: tags=cpu:host - :avocado: tags=device:gicv3 """ self.require_accelerator("kvm") self.vm.add_args("-accel", "kvm") self.vm.add_args("-cpu", "host") - self.vm.add_args("-machine", "virt,gic-version=3") + self.vm.add_args("-machine", "virt,gic-version=host") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) diff --git a/tests/qtest/fuzz-sb16-test.c b/tests/qtest/fuzz-sb16-test.c index 51030cd7dc..f47a8bcdbd 100644 --- a/tests/qtest/fuzz-sb16-test.c +++ b/tests/qtest/fuzz-sb16-test.c @@ -37,6 +37,22 @@ static void test_fuzz_sb16_0x91(void) qtest_quit(s); } +/* + * This used to trigger the assert in audio_calloc + * through command 0xd4 + */ +static void test_fuzz_sb16_0xd4(void) +{ + QTestState *s = qtest_init("-M pc -display none " + "-device sb16,audiodev=none " + "-audiodev id=none,driver=none"); + qtest_outb(s, 0x22c, 0x41); + qtest_outb(s, 0x22c, 0x00); + qtest_outb(s, 0x22c, 0x14); + qtest_outb(s, 0x22c, 0xd4); + qtest_quit(s); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -46,6 +62,7 @@ int main(int argc, char **argv) if (strcmp(arch, "i386") == 0) { qtest_add_func("fuzz/test_fuzz_sb16/1c", test_fuzz_sb16_0x1c); qtest_add_func("fuzz/test_fuzz_sb16/91", test_fuzz_sb16_0x91); + qtest_add_func("fuzz/test_fuzz_sb16/d4", test_fuzz_sb16_0xd4); } return g_test_run(); diff --git a/tests/tcg/hppa/Makefile.target b/tests/tcg/hppa/Makefile.target index 8bf01966bd..71791235f6 100644 --- a/tests/tcg/hppa/Makefile.target +++ b/tests/tcg/hppa/Makefile.target @@ -4,3 +4,7 @@ # On parisc Linux supports 4K/16K/64K (but currently only 4k works) EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-16384 run-test-mmap-65536 + +# There is a race that causes this to fail about 1% of the time +run-signals: signals + $(call skip-test, $<, "BROKEN awaiting vdso support") diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 241ef28f61..0036b8a505 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -8,3 +8,7 @@ TESTS+=exrl-trtr TESTS+=pack TESTS+=mvo TESTS+=mvc + +# This triggers failures on s390x hosts about 4% of the time +run-signals: signals + $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups") |