[PATCH v3 3/3] Implement audio capture in virtio-snd device
Signed-off-by: Emmanouil Pitsidianakis --- hw/virtio/trace-events | 3 +- hw/virtio/virtio-snd.c | 238 +++-- 2 files changed, 205 insertions(+), 36 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 8f3953dc28..3e7b259aef 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -165,7 +165,8 @@ virtio_snd_handle_pcm_set_params(int stream) "VIRTIO_SND_PCM_SET_PARAMS called f virtio_snd_handle_pcm_start_stop(const char *code, int stream) "%s called for stream %d" virtio_snd_handle_pcm_release(int stream) "VIRTIO_SND_PCM_RELEASE called for stream %d" virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" -virtio_snd_handle_xfer(void) "tx/rx queue callback called" +virtio_snd_handle_tx_xfer(void) "tx queue callback called" +virtio_snd_handle_rx_xfer(void) "rx queue callback called" virtio_snd_handle_event(void) "event queue callback called" virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_unrealize(void *snd) "snd %p: unrealize" diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c index dbf8d8162f..a6ac9d8ce0 100644 --- a/hw/virtio/virtio-snd.c +++ b/hw/virtio/virtio-snd.c @@ -27,7 +27,7 @@ #define VIRTIO_SOUND_VM_VERSION 1 #define VIRTIO_SOUND_JACK_DEFAULT 0 -#define VIRTIO_SOUND_STREAM_DEFAULT 1 +#define VIRTIO_SOUND_STREAM_DEFAULT 2 #define VIRTIO_SOUND_CHMAP_DEFAULT 0 #define VIRTIO_SOUND_HDA_FN_NID 0 @@ -114,12 +114,16 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config) } static void virtio_snd_process_cmdq(VirtIOSound *s); -static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream); +static void virtio_snd_pcm_out_flush(VirtIOSoundPCMStream *stream); +static void virtio_snd_pcm_in_flush(VirtIOSoundPCMStream *stream); static void virtio_snd_pcm_out_cb(void *data, int available); -static uint32_t virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream, +static void virtio_snd_pcm_in_cb(void *data, int available); +static uint32_t virtio_snd_pcm_write(VirtIOSoundPCMStream *stream, VirtQueue *vq, - VirtQueueElement *element, - bool read); + VirtQueueElement *element); +static uint32_t virtio_snd_pcm_read(VirtIOSoundPCMStream *stream, + VirtQueue *vq, + VirtQueueElement *element); /* * Get a specific stream from the virtio sound card device. @@ -421,15 +425,12 @@ static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) &as); } else { -qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented."); -/* - * stream->voice.in = AUD_open_in(&s->card, - *stream->voice.in, - *"virtio_snd_card", - *stream, - *virtio_snd_input_cb, - *&as); - */ +stream->voice.in = AUD_open_in(&s->card, +stream->voice.in, +"virtio_snd_card", +stream, +virtio_snd_pcm_in_cb, +&as); } stream->as = as; @@ -502,6 +503,8 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, if (stream) { if (stream->direction == VIRTIO_SND_D_OUTPUT) { AUD_set_active_out(stream->voice.out, start); +} else { +AUD_set_active_in(stream->voice.in, start); } } else { error_report("Invalid stream id: %d", req.stream_id); @@ -552,7 +555,11 @@ static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream *stream, */ virtio_snd_process_cmdq(stream->s); trace_virtio_snd_pcm_stream_flush(stream_id); -virtio_snd_pcm_flush(stream); +if (stream->direction == VIRTIO_SND_D_OUTPUT) { +virtio_snd_pcm_out_flush(stream); +} else { +virtio_snd_pcm_in_flush(stream); +} } return VIRTIO_SND_S_OK; @@ -738,7 +745,7 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq) * @vdev: VirtIOSound device * @vq: tx virtqueue */ -static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) +static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq) { VirtIOSound *s = VIRTIO_SND(vdev); VirtIOSoundPCMStream *stream = NULL; @@ -747,7 +754,7 @@ static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) virtio_snd_pcm_xfer hdr; virtio_snd_pcm_status resp = { 0 }; -trace_virtio_snd_handle_xfer(); +trace_virti
[PATCH v3 1/3] Add virtio-sound device
This patch adds an audio device implementing the recent virtio sound spec (1.2). PCM functionality is implemented, and jack[0], chmaps[1] messages are at the moment left unimplemented. PS2: This patch was based on a draft patch posted by OpenSynergy in 2019. [2] [0]: https://www.kernel.org/doc/html/latest/sound/designs/jack-controls.html [1]: https://www.kernel.org/doc/html/latest/sound/designs/channel-mapping-api.html [2]: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471#diff-fa5c10be8476fb5385a280885d527b0b40dfc11ddcc74369fce085d8b5b17bbd Signed-off-by: Emmanouil Pitsidianakis Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev base-commit: 361d539735 --- MAINTAINERS|6 + hw/virtio/Kconfig |5 + hw/virtio/meson.build |1 + hw/virtio/trace-events | 21 + hw/virtio/virtio-snd.c | 1121 include/hw/virtio/virtio-snd.h | 194 ++ 6 files changed, 1348 insertions(+) create mode 100644 hw/virtio/virtio-snd.c create mode 100644 include/hw/virtio/virtio-snd.h diff --git a/MAINTAINERS b/MAINTAINERS index 12e59b6b27..2bed60f9c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2245,6 +2245,12 @@ F: hw/virtio/virtio-mem-pci.h F: hw/virtio/virtio-mem-pci.c F: include/hw/virtio/virtio-mem.h +virtio-snd +M: Manos Pitsidianakis +S: Supported +F: hw/virtio/virtio-snd*.c +F: include/hw/virtio/virtio-snd.h + nvme M: Keith Busch M: Klaus Jensen diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index 92c9cf6c96..d6f20657b3 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -17,6 +17,11 @@ config VIRTIO_PCI depends on PCI select VIRTIO +config VIRTIO_SND +bool +default y +depends on VIRTIO + config VIRTIO_MMIO bool select VIRTIO diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index 13e7c6c272..120d4bfa0a 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -31,6 +31,7 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c')) specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c')) specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_SND', if_true: files('virtio-snd.c')) specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c')) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 7109cf1a3b..8f3953dc28 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -154,3 +154,24 @@ virtio_pmem_flush_done(int type) "fsync return=%d" virtio_gpio_start(void) "start" virtio_gpio_stop(void) "stop" virtio_gpio_set_status(uint8_t status) "0x%x" + +#virtio-snd.c +virtio_snd_pcm_stream_flush(int stream) "flushing stream %d" +virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" +#virtio_snd_handle_jack_info(int jack) "VIRTIO_SND_JACK_INFO called for jack %d" +#virtio_snd_handle_jack_remap(void) "VIRTIO_SND_PCM_JACK_REMAP called" +virtio_snd_handle_pcm_info(int stream) "VIRTIO_SND_R_PCM_INFO called for stream %d" +virtio_snd_handle_pcm_set_params(int stream) "VIRTIO_SND_PCM_SET_PARAMS called for stream %d" +virtio_snd_handle_pcm_start_stop(const char *code, int stream) "%s called for stream %d" +virtio_snd_handle_pcm_release(int stream) "VIRTIO_SND_PCM_RELEASE called for stream %d" +virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" +virtio_snd_handle_xfer(void) "tx/rx queue callback called" +virtio_snd_handle_event(void) "event queue callback called" +virtio_snd_realize(void *snd) "snd %p: realize" +virtio_snd_unrealize(void *snd) "snd %p: unrealize" +virtio_snd_get_features(void *vdev, uint64_t features) "snd %p: get_features 0x%"PRIx64 +virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams, uint32_t chmaps) "snd %p: get_config jacks=%d streams=%d chmaps=%d" +virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks, uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t new_chmaps) "snd %p: set_config jacks from %d->%d, streams from %d->%d, chmaps from %d->%d" +virtio_snd_vm_state_running(void) "vm state running" +virtio_snd_vm_state_stopped(void) "vm state stopped" +virtio_snd_handle_code(int val, const char *code) "ctrl code msg val = %d == %s" diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c new file mode 100644 index 00..dbf8d8162f --- /dev/null +++ b/hw/virtio/virtio-snd.c @@ -0,0 +1,1121 @@ +/* + * VIRTIO Sound Device conforming to + * + * "Virtual I/O Device (VIRTIO) Version 1.2 + * Committee Specification Draft 01 + * 09
Re: [PATCH 4/6] linux-user: Fix signed math overflow in brk() syscall
On 7/18/23 00:02, Philippe Mathieu-Daudé wrote: On 17/7/23 23:35, Helge Deller wrote: Fix the math overflow when calculating the new_malloc_size. new_host_brk_page and brk_page are unsigned integers. If userspace reduces the heap, new_host_brk_page is lower than brk_page which results in a huge positive number (but should actually be negative). Fix it by adding a proper check and as such make the code more readable. Signed-off-by: Helge Deller Tested-by: Markus F.X.J. Oberhumer Tested-by: Markus F.X.J. Oberhumer Ok. Fixes: 86f04735ac ("linux-user: Fix brk() to release pages") Hmm isn't it: Fixes: ef4330c23b ("linux-user: Handle brk() attempts with very large sizes") It's really 86f04735ac because this one introduced freeing of memory which can lead to new_host_brk_page becoming smaller than brk_page. Buglink: https://github.com/upx/upx/issues/683 Also: Cc: qemu-sta...@nongnu.org Yep. --- linux-user/syscall.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 92d146f8fb..aa906bedcc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -860,12 +860,13 @@ abi_long do_brk(abi_ulong brk_val) * itself); instead we treat "mapped but at wrong address" as * a failure and unmap again. */ - new_alloc_size = new_host_brk_page - brk_page; - if (new_alloc_size) { + if (new_host_brk_page > brk_page) { + new_alloc_size = new_host_brk_page - brk_page; mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0)); } else { + new_alloc_size = 0; mapped_addr = brk_page; } -- 2.41.0 Alternatively: -- >8 -- diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1464151826..aafb13f3b4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -814,7 +814,7 @@ void target_set_brk(abi_ulong new_brk) abi_long do_brk(abi_ulong brk_val) { abi_long mapped_addr; - abi_ulong new_alloc_size; + abi_long new_alloc_size; abi_ulong new_brk, new_host_brk_page; /* brk pointers are always untagged */ @@ -857,8 +857,8 @@ abi_long do_brk(abi_ulong brk_val) * a failure and unmap again. */ new_alloc_size = new_host_brk_page - brk_page; - if (new_alloc_size) { - mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, + if (new_alloc_size > 0) { + mapped_addr = get_errno(target_mmap(brk_page, (abi_ulong)new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0)); } else { possible, but I like my patch more. Anyhow, Reviewed-by: Philippe Mathieu-Daudé Thanks! Helge
[PATCH for-8.1] virtio-iommu: Standardize granule extraction and formatting
At several locations we compute the granule from the config page_size_mask using ctz() and then format it in traces using BIT(). As the page_size_mask is 64b we should use ctz64 and BIT_ULL() for formatting. We failed to be consistent. Note the page_size_mask is garanteed to be non null. The spec mandates the device to set at least one bit, so ctz64 cannot return 64. This is garanteed by the fact the device initializes the page_size_mask to qemu_target_page_mask() and then the page_size_mask is further constrained by virtio_iommu_set_page_size_mask() callback which can't result in a new mask being null. So if Coverity complains round those ctz64/BIT_ULL with CID 1517772 this is a false positive Signed-off-by: Eric Auger Fixes: 94df5b2180 ("virtio-iommu: Fix 64kB host page size VFIO device assignment") --- hw/virtio/virtio-iommu.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 201127c488..c6ee4d7a3c 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -852,17 +852,19 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr, VirtIOIOMMUEndpoint *ep; uint32_t sid, flags; bool bypass_allowed; +int granule; bool found; int i; interval.low = addr; interval.high = addr + 1; +granule = ctz64(s->config.page_size_mask); IOMMUTLBEntry entry = { .target_as = &address_space_memory, .iova = addr, .translated_addr = addr, -.addr_mask = (1 << ctz32(s->config.page_size_mask)) - 1, +.addr_mask = BIT_ULL(granule) - 1, .perm = IOMMU_NONE, }; @@ -1115,7 +1117,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr, if (s->granule_frozen) { int cur_granule = ctz64(cur_mask); -if (!(BIT(cur_granule) & new_mask)) { +if (!(BIT_ULL(cur_granule) & new_mask)) { error_setg(errp, "virtio-iommu %s does not support frozen granule 0x%llx", mr->parent_obj.name, BIT_ULL(cur_granule)); return -1; @@ -1161,7 +1163,7 @@ static void virtio_iommu_freeze_granule(Notifier *notifier, void *data) } s->granule_frozen = true; granule = ctz64(s->config.page_size_mask); -trace_virtio_iommu_freeze_granule(BIT(granule)); +trace_virtio_iommu_freeze_granule(BIT_ULL(granule)); } static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) -- 2.38.1
Re: [PATCH v2 2/4] vhost-user: Interface for migration state transfer
On Wed, Jul 12, 2023 at 01:17:00PM +0200, Hanna Czenczek wrote: > Add the interface for transferring the back-end's state during migration > as defined previously in vhost-user.rst. > > Signed-off-by: Hanna Czenczek > --- > include/hw/virtio/vhost-backend.h | 24 + > include/hw/virtio/vhost.h | 79 > hw/virtio/vhost-user.c| 147 ++ > hw/virtio/vhost.c | 37 > 4 files changed, 287 insertions(+) Reviewed-by: Stefan Hajnoczi signature.asc Description: PGP signature
Re: [PATCH v2 3/4] vhost: Add high-level state save/load functions
On Wed, Jul 12, 2023 at 01:17:01PM +0200, Hanna Czenczek wrote: > vhost_save_backend_state() and vhost_load_backend_state() can be used by > vhost front-ends to easily save and load the back-end's state to/from > the migration stream. > > Because we do not know the full state size ahead of time, > vhost_save_backend_state() simply reads the data in 1 MB chunks, and > writes each chunk consecutively into the migration stream, prefixed by > its length. EOF is indicated by a 0-length chunk. > > Signed-off-by: Hanna Czenczek > --- > include/hw/virtio/vhost.h | 35 +++ > hw/virtio/vhost.c | 204 ++ > 2 files changed, 239 insertions(+) > > diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h > index d8877496e5..0c282abd4e 100644 > --- a/include/hw/virtio/vhost.h > +++ b/include/hw/virtio/vhost.h > @@ -425,4 +425,39 @@ int vhost_set_device_state_fd(struct vhost_dev *dev, > */ > int vhost_check_device_state(struct vhost_dev *dev, Error **errp); > > +/** > + * vhost_save_backend_state(): High-level function to receive a vhost > + * back-end's state, and save it in `f`. Uses I think the GtkDoc syntax is @f instead of `f`. > + * `vhost_set_device_state_fd()` to get the data from the back-end, and > + * stores it in consecutive chunks that are each prefixed by their > + * respective length (be32). The end is marked by a 0-length chunk. > + * > + * Must only be called while the device and all its vrings are stopped > + * (`VHOST_TRANSFER_STATE_PHASE_STOPPED`). > + * > + * @dev: The vhost device from which to save the state > + * @f: Migration stream in which to save the state > + * @errp: Potential error message > + * > + * Returns 0 on success, and -errno otherwise. > + */ > +int vhost_save_backend_state(struct vhost_dev *dev, QEMUFile *f, Error > **errp); > + > +/** > + * vhost_load_backend_state(): High-level function to load a vhost > + * back-end's state from `f`, and send it over to the back-end. Reads > + * the data from `f` in the format used by `vhost_save_state()`, and > + * uses `vhost_set_device_state_fd()` to transfer it to the back-end. > + * > + * Must only be called while the device and all its vrings are stopped > + * (`VHOST_TRANSFER_STATE_PHASE_STOPPED`). > + * > + * @dev: The vhost device to which to send the sate > + * @f: Migration stream from which to load the state > + * @errp: Potential error message > + * > + * Returns 0 on success, and -errno otherwise. > + */ > +int vhost_load_backend_state(struct vhost_dev *dev, QEMUFile *f, Error > **errp); > + > #endif > diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c > index 756b6d55a8..332d49a310 100644 > --- a/hw/virtio/vhost.c > +++ b/hw/virtio/vhost.c > @@ -2128,3 +2128,207 @@ int vhost_check_device_state(struct vhost_dev *dev, > Error **errp) > "vhost transport does not support migration state transfer"); > return -ENOSYS; > } > + > +int vhost_save_backend_state(struct vhost_dev *dev, QEMUFile *f, Error > **errp) > +{ > +/* Maximum chunk size in which to transfer the state */ > +const size_t chunk_size = 1 * 1024 * 1024; > +void *transfer_buf = NULL; > +g_autoptr(GError) g_err = NULL; > +int pipe_fds[2], read_fd = -1, write_fd = -1, reply_fd = -1; > +int ret; > + > +/* [0] for reading (our end), [1] for writing (back-end's end) */ > +if (!g_unix_open_pipe(pipe_fds, FD_CLOEXEC, &g_err)) { > +error_setg(errp, "Failed to set up state transfer pipe: %s", > + g_err->message); > +ret = -EINVAL; > +goto fail; > +} > + > +read_fd = pipe_fds[0]; > +write_fd = pipe_fds[1]; > + > +/* > + * VHOST_TRANSFER_STATE_PHASE_STOPPED means the device must be stopped. > + * We cannot check dev->suspended, because the back-end may not support > + * suspending. > + */ > +assert(!dev->started); > + > +/* Transfer ownership of write_fd to the back-end */ > +ret = vhost_set_device_state_fd(dev, > +VHOST_TRANSFER_STATE_DIRECTION_SAVE, > +VHOST_TRANSFER_STATE_PHASE_STOPPED, > +write_fd, > +&reply_fd, > +errp); > +if (ret < 0) { > +error_prepend(errp, "Failed to initiate state transfer: "); > +goto fail; > +} > + > +/* If the back-end wishes to use a different pipe, switch over */ > +if (reply_fd >= 0) { > +close(read_fd); > +read_fd = reply_fd; > +} > + > +transfer_buf = g_malloc(chunk_size); > + > +while (true) { > +ssize_t read_ret; > + > +read_ret = read(read_fd, transfer_buf, chunk_size); > +if (read_ret < 0) { Is it necessary to handle -EINTR? > +ret = -errno; > +error_setg_errno(errp, -ret, "Failed to receive state"); > +goto fail; > +} > + > +
Re: [PATCH v2 4/4] vhost-user-fs: Implement internal migration
On Wed, Jul 12, 2023 at 01:17:02PM +0200, Hanna Czenczek wrote: > A virtio-fs device's VM state consists of: > - the virtio device (vring) state (VMSTATE_VIRTIO_DEVICE) > - the back-end's (virtiofsd's) internal state > > We get/set the latter via the new vhost operations to transfer migratory > state. It is its own dedicated subsection, so that for external > migration, it can be disabled. > > Signed-off-by: Hanna Czenczek > --- > hw/virtio/vhost-user-fs.c | 101 +- > 1 file changed, 100 insertions(+), 1 deletion(-) Reviewed-by: Stefan Hajnoczi signature.asc Description: PGP signature
Re: [PATCH for-8.2 v3 0/8] target/riscv: add 'max' CPU, deprecate
Alistair, I'm doing some overly complicated stuff here w.r.t to KVM specific code that are biting me back in further cleanups I'm working on. I'll do some changes in this series and re-send. Thanks, Daniel On 7/14/23 14:43, Daniel Henrique Barboza wrote: Hi, This version has changes suggested in v2. The most significant change is the deprecation of the 'any' CPU in patch 8. The reasoning behind it is that Alistair mentioned that the 'any' CPU intended to work like the newly added 'max' CPU, so we're better of removing the 'any' CPU since it'll be out of place. We can't just remove the CPU out of the gate so we'll have to make it do with deprecation first. Patches missing review: 5,6,7,8 Changes from v2: - patches 1, 3, 4: - remove "DEFINE_PROP_END_OF_LIST()" at the end of each prop array; - use ARRAY_SIZE() in the for loop - patch 5: - remove the trailing '/' in the last line of the macro - wrap the macro in "do {} while (0)" - patch 8 (new): - deprecate the 'any' CPU - v2 link: https://lore.kernel.org/qemu-riscv/20230712205748.446931-1-dbarb...@ventanamicro.com/ Daniel Henrique Barboza (8): target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[] target/riscv/cpu.c: skip 'bool' check when filtering KVM props target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[] target/riscv/cpu.c: add a ADD_CPU_PROPERTIES_ARRAY() macro target/riscv: add 'max' CPU type avocado, risc-v: add opensbi tests for 'max' CPU target/riscv: deprecate the 'any' CPU type docs/about/deprecated.rst | 12 target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 114 ++--- tests/avocado/riscv_opensbi.py | 16 + 4 files changed, 121 insertions(+), 22 deletions(-)
[PATCH v2 5/5] linux-user: Fix qemu-arm to run static armhf binaries
qemu-user crashes immediately when running static binaries on the armhf architecture. The problem is the memory layout where the executable is loaded before the interpreter library, in which case the reserved brk region clashes with the interpreter code and is released before qemu tries to start the program. At load time qemu calculates a brk value for interpreter and executable each. The fix is to choose the higher one of both. Signed-off-by: Helge Deller Cc: Andreas Schwab Cc: qemu-sta...@nongnu.org Reported-by: venkata.p...@toshiba-tsip.com Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1040981 --- linux-user/elfload.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index a26200d9f3..94951630b1 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3615,6 +3615,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) if (elf_interpreter) { load_elf_interp(elf_interpreter, &interp_info, bprm->buf); +/* + * adjust brk address if the interpreter was loaded above the main + * executable, e.g. happens with static binaries on armhf + */ +if (interp_info.brk > info->brk) { +info->brk = interp_info.brk; +} /* If the program interpreter is one of these two, then assume an iBCS2 image. Otherwise assume a native linux image. */ -- 2.41.0
[PATCH v2 1/5] linux-user: Fix qemu brk() to not zero bytes on current page
The qemu brk() implementation is too aggressive and cleans remaining bytes on the current page above the last brk address. But some existing applications are buggy and read/write bytes above their current heap address. On a phyiscal machine this does not trigger a runtime error as long as the access happens on the same page. Additionally the Linux kernel allocates only full pages and does no zeroing on already allocated pages, even if the brk address is lowered. Fix qemu to behave the same way as the kernel does. Do not touch already allocated pages, and - when running with different page sizes of guest and host - zero out only those memory areas where the host page size is bigger than the guest page size. Signed-off-by: Helge Deller Tested-by: "Markus F.X.J. Oberhumer" Fixes: 86f04735ac ("linux-user: Fix brk() to release pages") Cc: qemu-sta...@nongnu.org Buglink: https://github.com/upx/upx/issues/683 --- linux-user/syscall.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c99ef9c01e..ee54eed33b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -829,10 +829,8 @@ abi_long do_brk(abi_ulong brk_val) /* brk_val and old target_brk might be on the same page */ if (new_brk == TARGET_PAGE_ALIGN(target_brk)) { -if (brk_val > target_brk) { -/* empty remaining bytes in (possibly larger) host page */ -memset(g2h_untagged(target_brk), 0, new_host_brk_page - target_brk); -} +/* empty remaining bytes in (possibly larger) host page */ +memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk); target_brk = brk_val; return target_brk; } @@ -840,7 +838,7 @@ abi_long do_brk(abi_ulong brk_val) /* Release heap if necesary */ if (new_brk < target_brk) { /* empty remaining bytes in (possibly larger) host page */ -memset(g2h_untagged(brk_val), 0, new_host_brk_page - brk_val); +memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk); /* free unused host pages and set new brk_page */ target_munmap(new_host_brk_page, brk_page - new_host_brk_page); @@ -873,7 +871,7 @@ abi_long do_brk(abi_ulong brk_val) * come from the remaining part of the previous page: it may * contains garbage data due to a previous heap usage (grown * then shrunken). */ -memset(g2h_untagged(target_brk), 0, brk_page - target_brk); +memset(g2h_untagged(brk_page), 0, HOST_PAGE_ALIGN(brk_page) - brk_page); target_brk = brk_val; brk_page = new_host_brk_page; -- 2.41.0
[PATCH v2 0/5] linux-user: brk() syscall fixes and armhf static binary fix
Commit 86f04735ac ("linux-user: Fix brk() to release pages") introduced the possibility for userspace applications to reduce memory footprint by calling brk() with a lower address and as such free up memory, the same way as the Linux kernel allows on physical machines. This change introduced some failures for applications with errors like - accesing bytes above the brk heap address on the same page, - freeing memory below the initial brk address, and introduced a behaviour which isn't done by the kernel (e.g. zeroing memory above brk). This patch series fixes those issues and has been tested with existing programs (e.g. upx). Additionally one patch fixes running static armhf executables (e.g. fstype) which was broken since qemu-8.0. Changes in v2: - dropped patch to revert d28b3c90cfad ("linux-user: Make sure initial brk(0) is page-aligned") - rephrased some commit messages - fixed Cc email addresses, added new ones - added R-b tags Helge Helge Deller (5): linux-user: Fix qemu brk() to not zero bytes on current page linux-user: Prohibit brk() to to shrink below initial heap address linux-user: Fix signed math overflow in brk() syscall linux-user: Fix strace output for old_mmap linux-user: Fix qemu-arm to run static armhf binaries linux-user/elfload.c | 7 +++ linux-user/strace.c | 49 linux-user/syscall.c | 23 + 3 files changed, 66 insertions(+), 13 deletions(-) -- 2.41.0
[PATCH v2 2/5] linux-user: Prohibit brk() to to shrink below initial heap address
Since commit 86f04735ac ("linux-user: Fix brk() to release pages") it's possible for userspace applications to reduce their memory footprint by calling brk() with a lower address and free up memory. Before that commit guest heap memory was never unmapped. But the Linux kernel prohibits to reduce brk() below the initial memory address which is set at startup by the set_brk() function in binfmt_elf.c. Such a range check was missed in commit 86f04735ac. This patch adds the missing check by storing the initial brk value in initial_target_brk and verify any new brk addresses against that value. Tested with the i386 upx binary from https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-i386_linux.tar.xz Signed-off-by: Helge Deller Tested-by: "Markus F.X.J. Oberhumer" Fixes: 86f04735ac ("linux-user: Fix brk() to release pages") Cc: qemu-sta...@nongnu.org Buglink: https://github.com/upx/upx/issues/683 --- linux-user/syscall.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ee54eed33b..125fcbe423 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -801,12 +801,13 @@ static inline int host_to_target_sock_type(int host_type) return target_type; } -static abi_ulong target_brk; +static abi_ulong target_brk, initial_target_brk; static abi_ulong brk_page; void target_set_brk(abi_ulong new_brk) { target_brk = TARGET_PAGE_ALIGN(new_brk); +initial_target_brk = target_brk; brk_page = HOST_PAGE_ALIGN(target_brk); } @@ -824,6 +825,11 @@ abi_long do_brk(abi_ulong brk_val) return target_brk; } +/* do not allow to shrink below initial brk value */ +if (brk_val < initial_target_brk) { +brk_val = initial_target_brk; +} + new_brk = TARGET_PAGE_ALIGN(brk_val); new_host_brk_page = HOST_PAGE_ALIGN(brk_val); -- 2.41.0
[PATCH v2 3/5] linux-user: Fix signed math overflow in brk() syscall
Fix the math overflow when calculating the new_malloc_size. new_host_brk_page and brk_page are unsigned integers. If userspace reduces the heap, new_host_brk_page is lower than brk_page which results in a huge positive number (but should actually be negative). Fix it by adding a proper check and as such make the code more readable. Signed-off-by: Helge Deller Tested-by: "Markus F.X.J. Oberhumer" Reviewed-by: Philippe Mathieu-Daudé Fixes: 86f04735ac ("linux-user: Fix brk() to release pages") Cc: qemu-sta...@nongnu.org Buglink: https://github.com/upx/upx/issues/683 --- linux-user/syscall.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 125fcbe423..95727a816a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -860,12 +860,13 @@ abi_long do_brk(abi_ulong brk_val) * itself); instead we treat "mapped but at wrong address" as * a failure and unmap again. */ -new_alloc_size = new_host_brk_page - brk_page; -if (new_alloc_size) { +if (new_host_brk_page > brk_page) { +new_alloc_size = new_host_brk_page - brk_page; mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0)); } else { +new_alloc_size = 0; mapped_addr = brk_page; } -- 2.41.0
[PATCH v2 4/5] linux-user: Fix strace output for old_mmap
The old_mmap syscall (e.g. on i386) hands over the parameters in a struct. Adjust the strace output to print the correct values. Signed-off-by: Helge Deller Reported-by: John Reiser Closes: https://gitlab.com/qemu-project/qemu/-/issues/1760 --- linux-user/strace.c | 49 + 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index bbd29148d4..e0ab8046ec 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3767,10 +3767,24 @@ print_utimensat(CPUArchState *cpu_env, const struct syscallname *name, #if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2) static void -print_mmap(CPUArchState *cpu_env, const struct syscallname *name, +print_mmap_both(CPUArchState *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5) -{ + abi_long arg3, abi_long arg4, abi_long arg5, + bool is_old_mmap) +{ +if (is_old_mmap) { +abi_ulong *v; +abi_ulong argp = arg0; +if (!(v = lock_user(VERIFY_READ, argp, 6 * sizeof(abi_ulong), 1))) +return; +arg0 = tswapal(v[0]); +arg1 = tswapal(v[1]); +arg2 = tswapal(v[2]); +arg3 = tswapal(v[3]); +arg4 = tswapal(v[4]); +arg5 = tswapal(v[5]); +unlock_user(v, argp, 0); +} print_syscall_prologue(name); print_pointer(arg0, 0); print_raw_param("%d", arg1, 0); @@ -3780,7 +3794,34 @@ print_mmap(CPUArchState *cpu_env, const struct syscallname *name, print_raw_param("%#x", arg5, 1); print_syscall_epilogue(name); } -#define print_mmap2 print_mmap +#endif + +#if defined(TARGET_NR_mmap) +static void +print_mmap(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ +return print_mmap_both(cpu_env, name, arg0, arg1, arg2, arg3, + arg4, arg5, +#if defined(TARGET_NR_mmap2) +true +#else +false +#endif +); +} +#endif + +#if defined(TARGET_NR_mmap2) +static void +print_mmap2(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ +return print_mmap_both(cpu_env, name, arg0, arg1, arg2, arg3, + arg4, arg5, false); +} #endif #ifdef TARGET_NR_mprotect -- 2.41.0
Re: PING: [PATCH v4 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
On Tue, Jul 11, 2023 at 07:31:02PM +0900, Jeuk Kim wrote: > Hi, > Any more reviews...? > > Dear Stefan > If you don't mind, Could you give it "reviewed-by"? > And is there anything else I should do...? Sorry for the late reply. I was on vacation and am working my way through pending code review and bug reports. I have started reviewing this series and should be finish on Wednesday or Thursday. Stefan signature.asc Description: PGP signature
Re: [PATCH 04/10] hw/riscv: virt: Add PCIe HIGHMEM in memmap
On 7/12/23 13:39, Sunil V L wrote: PCIe High MMIO base is actually dynamic and fixed at run time based on the RAM configured. Currently, this is not part of the memmap and kept in separate static variable in virt.c. However, ACPI code also needs this information to populate DSDT. So, once the base is discovered, merge this into the final memmap which can be used to create ACPI tables later. Signed-off-by: Sunil V L --- hw/riscv/virt.c | 31 ++- include/hw/riscv/virt.h | 9 +++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index f6067db8ec..7aee06f021 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -84,6 +84,22 @@ static const MemMapEntry virt_memmap[] = { static MemMapEntry virt_high_pcie_memmap; +/* + * virt_memmap doesn't include floating High Mem IO address entry. To enable + * code organization in multiple files (ex: ACPI), it is better to have single + * memmap which has complete information. + * + * VIRT_HIGH_PCIE_MMIO is always greater than the last memmap entry and hence + * full_virt_memmap is capable of holding both virt_memmap and + * VIRT_HIGH_PCIE_MMIO entry. + * + * The values for these floating entries will be updated when top of RAM is + * discovered. + */ +static MemMapEntry full_virt_memmap[] = { +[VIRT_HIGH_PCIE_MMIO] = { 0x0, 0 }, +}; + #define VIRT_FLASH_SECTOR_SIZE (256 * KiB) static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s, @@ -1444,7 +1460,20 @@ static void virt_machine_init(MachineState *machine) ROUND_UP(virt_high_pcie_memmap.base, virt_high_pcie_memmap.size); } -s->memmap = virt_memmap; +/* + * Initialize the floating values in full memory map + */ +full_virt_memmap[VIRT_HIGH_PCIE_MMIO].base = virt_high_pcie_memmap.base; +full_virt_memmap[VIRT_HIGH_PCIE_MMIO].size = virt_high_pcie_memmap.size; + +s->memmap = full_virt_memmap; +/* + * Copy the base virt_memmap entries to full memmap + */ +for (i = 0; i < ARRAY_SIZE(virt_memmap); i++) { +s->memmap[i] = virt_memmap[i]; +} + This change here kind of convinces me of the point I made earlier in patch 2: we can simplify gpex_pcie_init() to use just the RISCVVirtState as a parameter and get everything else from it. It's also something for a follow-up. As for this patch: Reviewed-by: Daniel Henrique Barboza /* register system main memory (actual RAM) */ memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base, diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 00c22492a7..1d7ddf5df0 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -60,7 +60,7 @@ struct RISCVVirtState { char *oem_id; char *oem_table_id; OnOffAuto acpi; -const MemMapEntry *memmap; +MemMapEntry *memmap; PCIBus *bus; }; @@ -84,7 +84,12 @@ enum { VIRT_PCIE_MMIO, VIRT_PCIE_PIO, VIRT_PLATFORM_BUS, -VIRT_PCIE_ECAM +VIRT_PCIE_ECAM, +VIRT_LAST_MEMMAP /* Keep this entry always last */ +}; + +enum { +VIRT_HIGH_PCIE_MMIO = VIRT_LAST_MEMMAP, }; enum {
Re: [PATCH 05/10] hw/riscv/virt-acpi-build.c: Add AIA support in RINTC
On 7/12/23 13:39, Sunil V L wrote: Update the RINTC structure in MADT with AIA related fields. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/virt-acpi-build.c | 66 +++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 01843e4509..12b8ef0352 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -37,6 +37,7 @@ #include "hw/intc/riscv_aclint.h" #define ACPI_BUILD_TABLE_SIZE 0x2 +#define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) typedef struct AcpiBuildState { /* Copy of table in RAM (for patching) */ @@ -57,18 +58,42 @@ static void acpi_align_size(GArray *blob, unsigned align) } static void riscv_acpi_madt_add_rintc(uint32_t uid, + uint32_t local_cpu_id, const CPUArchIdList *arch_ids, - GArray *entry) + GArray *entry, + RISCVVirtAIAType aia_type, + uint64_t imsic_addr, + uint32_t imsic_size) { uint64_t hart_id = arch_ids->cpus[uid].arch_id; build_append_int_noprefix(entry, 0x18, 1); /* Type */ -build_append_int_noprefix(entry, 20, 1); /* Length */ +build_append_int_noprefix(entry, 36, 1); /* Length */ build_append_int_noprefix(entry, 1, 1); /* Version */ build_append_int_noprefix(entry, 0, 1); /* Reserved */ build_append_int_noprefix(entry, 0x1, 4);/* Flags*/ build_append_int_noprefix(entry, hart_id, 8);/* Hart ID */ build_append_int_noprefix(entry, uid, 4);/* ACPI Processor UID */ +/* External Interrupt Controller ID */ +if (aia_type == VIRT_AIA_TYPE_APLIC) { +build_append_int_noprefix(entry, + ACPI_BUILD_INTC_ID( + arch_ids->cpus[uid].props.node_id, + local_cpu_id), + 4); +} else { +build_append_int_noprefix(entry, 0, 4); +} + +if (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) { +/* IMSIC Base address */ +build_append_int_noprefix(entry, imsic_addr, 8); +/* IMSIC Size */ +build_append_int_noprefix(entry, imsic_size, 4); +} else { +build_append_int_noprefix(entry, 0, 8); +build_append_int_noprefix(entry, 0, 4); +} } static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) @@ -76,6 +101,11 @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) MachineClass *mc = MACHINE_GET_CLASS(s); MachineState *ms = MACHINE(s); const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms); +uint64_t imsic_socket_addr, imsic_addr; +uint8_t guest_index_bits; +uint32_t imsic_size, local_cpu_id, socket_id; + +guest_index_bits = imsic_num_bits(s->aia_guests + 1); for (int i = 0; i < arch_ids->len; i++) { Aml *dev; @@ -86,8 +116,19 @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) aml_append(dev, aml_name_decl("_UID", aml_int(arch_ids->cpus[i].arch_id))); +socket_id = arch_ids->cpus[i].props.node_id; +local_cpu_id = (arch_ids->cpus[i].arch_id - +riscv_socket_first_hartid(ms, socket_id)) % +riscv_socket_hart_count(ms, socket_id); /* build _MAT object */ -riscv_acpi_madt_add_rintc(i, arch_ids, madt_buf); +imsic_socket_addr = s->memmap[VIRT_IMSIC_S].base + +(socket_id * VIRT_IMSIC_GROUP_MAX_SIZE); +imsic_addr = imsic_socket_addr + + local_cpu_id * IMSIC_HART_SIZE(guest_index_bits); +imsic_size = IMSIC_HART_SIZE(guest_index_bits); + +riscv_acpi_madt_add_rintc(i, local_cpu_id, arch_ids, madt_buf, + s->aia_type, imsic_addr, imsic_size); aml_append(dev, aml_name_decl("_MAT", aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data))); @@ -226,6 +267,7 @@ static void build_dsdt(GArray *table_data, * 5.2.12 Multiple APIC Description Table (MADT) * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/15 * https://drive.google.com/file/d/1R6k4MshhN3WTT-hwqAquu5nX6xSEqK2l/view + * https://drive.google.com/file/d/1oMGPyOD58JaPgMl1pKasT-VKsIKia7zR/view */ static void build_madt(GArray *table_data, BIOSLinker *linker, @@ -234,6 +276,12 @@ static void build_madt(GArray *table_
Re: [PATCH 06/10] hw/riscv/virt-acpi-build.c: Add IMSIC in the MADT
On 7/12/23 13:39, Sunil V L wrote: Add IMSIC structure in MADT when IMSIC is configured. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/virt-acpi-build.c | 34 ++ 1 file changed, 34 insertions(+) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 12b8ef0352..ebdc3bffea 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -280,8 +280,20 @@ static void build_madt(GArray *table_data, uint8_t guest_index_bits; uint32_t imsic_size; uint32_t local_cpu_id, socket_id; +uint8_t hart_index_bits, group_index_bits, group_index_shift; +uint16_t imsic_max_hart_per_socket = 0; +uint8_t socket; + +for (socket = 0; socket < riscv_socket_count(ms); socket++) { +if (imsic_max_hart_per_socket < s->soc[socket].num_harts) { +imsic_max_hart_per_socket = s->soc[socket].num_harts; +} +} guest_index_bits = imsic_num_bits(s->aia_guests + 1); +hart_index_bits = imsic_num_bits(imsic_max_hart_per_socket); +group_index_bits = imsic_num_bits(riscv_socket_count(ms)); +group_index_shift = IMSIC_MMIO_GROUP_MIN_SHIFT; AcpiTable table = { .sig = "APIC", .rev = 6, .oem_id = s->oem_id, .oem_table_id = s->oem_table_id }; @@ -306,6 +318,28 @@ static void build_madt(GArray *table_data, s->aia_type, imsic_addr, imsic_size); } +/* IMSIC */ +if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) { +/* IMSIC */ +build_append_int_noprefix(table_data, 0x19, 1); /* Type */ +build_append_int_noprefix(table_data, 16, 1); /* Length */ +build_append_int_noprefix(table_data, 1, 1);/* Version */ +build_append_int_noprefix(table_data, 0, 1);/* Reserved */ +build_append_int_noprefix(table_data, 0, 4);/* Flags */ +/* Number of supervisor mode Interrupt Identities */ +build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2); +/* Number of guest mode Interrupt Identities */ +build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2); +/* Guest Index Bits */ +build_append_int_noprefix(table_data, guest_index_bits, 1); +/* Hart Index Bits */ +build_append_int_noprefix(table_data, hart_index_bits, 1); +/* Group Index Bits */ +build_append_int_noprefix(table_data, group_index_bits, 1); +/* Group Index Shift */ +build_append_int_noprefix(table_data, group_index_shift, 1); +} + acpi_table_end(linker, &table); }
Re: [PATCH 07/10] hw/riscv/virt-acpi-build.c: Add APLIC in the MADT
On 7/12/23 13:39, Sunil V L wrote: Add APLIC structures for each socket in the MADT when system is configured with APLIC as the external wired interrupt controller. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/virt-acpi-build.c | 36 ++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index ebdc3bffea..9f2d0c92b0 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -276,9 +276,9 @@ static void build_madt(GArray *table_data, MachineClass *mc = MACHINE_GET_CLASS(s); MachineState *ms = MACHINE(s); const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms); -uint64_t imsic_socket_addr, imsic_addr; +uint64_t imsic_socket_addr, imsic_addr, aplic_addr; +uint32_t imsic_size, gsi_base; uint8_t guest_index_bits; -uint32_t imsic_size; uint32_t local_cpu_id, socket_id; uint8_t hart_index_bits, group_index_bits, group_index_shift; uint16_t imsic_max_hart_per_socket = 0; @@ -340,6 +340,38 @@ static void build_madt(GArray *table_data, build_append_int_noprefix(table_data, group_index_shift, 1); } +if (s->aia_type != VIRT_AIA_TYPE_NONE) { +/* APLICs */ +for (socket = 0; socket < riscv_socket_count(ms); socket++) { +aplic_addr = s->memmap[VIRT_APLIC_S].base + + s->memmap[VIRT_APLIC_S].size * socket; +gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket; +build_append_int_noprefix(table_data, 0x1A, 1);/* Type */ +build_append_int_noprefix(table_data, 36, 1); /* Length */ +build_append_int_noprefix(table_data, 1, 1); /* Version */ +build_append_int_noprefix(table_data, socket, 1); /* APLIC ID */ +build_append_int_noprefix(table_data, 0, 4); /* Flags */ +build_append_int_noprefix(table_data, 0, 8); /* Hardware ID */ +/* Number of IDCs */ +if (s->aia_type == VIRT_AIA_TYPE_APLIC) { +build_append_int_noprefix(table_data, + s->soc[socket].num_harts, + 2); +} else { +build_append_int_noprefix(table_data, 0, 2); +} +/* Total External Interrupt Sources Supported */ +build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_SOURCES, 2); +/* Global System Interrupt Base */ +build_append_int_noprefix(table_data, gsi_base, 4); +/* APLIC Address */ +build_append_int_noprefix(table_data, aplic_addr, 8); +/* APLIC size */ +build_append_int_noprefix(table_data, + s->memmap[VIRT_APLIC_S].size, 4); +} +} + acpi_table_end(linker, &table); }
Re: [PATCH 08/10] hw/riscv/virt-acpi-build.c: Add CMO information in RHCT
On 7/12/23 13:39, Sunil V L wrote: When CMO related extensions like Zicboz, Zicbom and Zicbop are enabled, the block size for those extensions need to be communicated via CMO node in RHCT. Add CMO node in RHCT if any of those CMO extensions are detected. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/virt-acpi-build.c | 64 +- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 9f2d0c92b0..2d2bd3b970 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -146,6 +146,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) * 5.2.36 RISC-V Hart Capabilities Table (RHCT) * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/16 * https://drive.google.com/file/d/1nP3nFiH4jkPMp6COOxP6123DCZKR-tia/view + * https://drive.google.com/file/d/1sKbOa8m1UZw1JkquZYe3F1zQBN1xXsaf/view */ static void build_rhct(GArray *table_data, BIOSLinker *linker, @@ -155,8 +156,8 @@ static void build_rhct(GArray *table_data, MachineState *ms = MACHINE(s); const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms); size_t len, aligned_len; -uint32_t isa_offset, num_rhct_nodes; -RISCVCPU *cpu; +uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0; +RISCVCPU *cpu = &s->soc[0].harts[0]; char *isa; AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id, @@ -172,6 +173,9 @@ static void build_rhct(GArray *table_data, /* ISA + N hart info */ num_rhct_nodes = 1 + ms->smp.cpus; +if (cpu->cfg.ext_icbom || cpu->cfg.ext_icboz) { +num_rhct_nodes++; +} /* Number of RHCT nodes*/ build_append_int_noprefix(table_data, num_rhct_nodes, 4); @@ -183,7 +187,6 @@ static void build_rhct(GArray *table_data, isa_offset = table_data->len - table.table_offset; build_append_int_noprefix(table_data, 0, 2); /* Type 0 */ -cpu = &s->soc[0].harts[0]; isa = riscv_isa_string(cpu); len = 8 + strlen(isa) + 1; aligned_len = (len % 2) ? (len + 1) : len; @@ -199,14 +202,59 @@ static void build_rhct(GArray *table_data, build_append_int_noprefix(table_data, 0x0, 1); /* Optional Padding */ } +/* CMO node */ +if (cpu->cfg.ext_icbom || cpu->cfg.ext_icboz) { +cmo_offset = table_data->len - table.table_offset; +build_append_int_noprefix(table_data, 1, 2);/* Type */ +build_append_int_noprefix(table_data, 10, 2); /* Total Length */ +build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ +build_append_int_noprefix(table_data, 0, 1);/* Reserved */ + +/* CBOM block size */ +if (cpu->cfg.cbom_blocksize) { +build_append_int_noprefix(table_data, + __builtin_ctz(cpu->cfg.cbom_blocksize), + 1); +} else { +build_append_int_noprefix(table_data, 0, 1); +} + +/* CBOP block size */ +build_append_int_noprefix(table_data, 0, 1); + +/* CBOZ block size */ +if (cpu->cfg.cboz_blocksize) { +build_append_int_noprefix(table_data, + __builtin_ctz(cpu->cfg.cboz_blocksize), + 1); +} else { +build_append_int_noprefix(table_data, 0, 1); +} +} + /* Hart Info Node */ for (int i = 0; i < arch_ids->len; i++) { +len = 16; +int num_offsets = 1; build_append_int_noprefix(table_data, 0x, 2); /* Type */ -build_append_int_noprefix(table_data, 16, 2); /* Length */ -build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ -build_append_int_noprefix(table_data, 1, 2);/* Number of offsets */ -build_append_int_noprefix(table_data, i, 4);/* ACPI Processor UID */ -build_append_int_noprefix(table_data, isa_offset, 4); /* Offsets[0] */ + +/* Length */ +if (cmo_offset) { +len += 4; +num_offsets++; +} + +build_append_int_noprefix(table_data, len, 2); +build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ +/* Number of offsets */ +build_append_int_noprefix(table_data, num_offsets, 2); +build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ + +/* Offsets */ +build_append_int_noprefix(table_data, isa_offset, 4); +if (cmo_offset) { +build_append_int_noprefix(table_data, cmo_offset, 4); +} } acpi_table_end(linker, &table);
Re: [PATCH 09/10] hw/riscv/virt-acpi-build.c: Add MMU node in RHCT
On 7/12/23 13:39, Sunil V L wrote: MMU type information is available via MMU node in RHCT. Add this node in RHCT. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/virt-acpi-build.c | 36 1 file changed, 36 insertions(+) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 2d2bd3b970..25745eee4c 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -158,6 +158,8 @@ static void build_rhct(GArray *table_data, size_t len, aligned_len; uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0; RISCVCPU *cpu = &s->soc[0].harts[0]; +uint32_t mmu_offset = 0; +uint8_t satp_mode_max; char *isa; AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id, @@ -177,6 +179,10 @@ static void build_rhct(GArray *table_data, num_rhct_nodes++; } +if (cpu->cfg.satp_mode.supported != 0) { +num_rhct_nodes++; +} + /* Number of RHCT nodes*/ build_append_int_noprefix(table_data, num_rhct_nodes, 4); @@ -202,6 +208,26 @@ static void build_rhct(GArray *table_data, build_append_int_noprefix(table_data, 0x0, 1); /* Optional Padding */ } +/* MMU node structure */ +if (cpu->cfg.satp_mode.supported != 0) { +satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); +mmu_offset = table_data->len - table.table_offset; +build_append_int_noprefix(table_data, 1, 2);/* Type */ +build_append_int_noprefix(table_data, 8, 2);/* Total Length */ +build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ +build_append_int_noprefix(table_data, 0, 1);/* Reserved */ +/* Virtual Address Scheme */ +if (satp_mode_max == VM_1_10_SV57) { +build_append_int_noprefix(table_data, 2, 1);/* Sv57 */ +} else if (satp_mode_max == VM_1_10_SV48) { +build_append_int_noprefix(table_data, 1, 1);/* Sv48 */ +} else if (satp_mode_max == VM_1_10_SV39) { +build_append_int_noprefix(table_data, 0, 1);/* Sv39 */ +} else { +assert(1); +} +} + /* CMO node */ if (cpu->cfg.ext_icbom || cpu->cfg.ext_icboz) { cmo_offset = table_data->len - table.table_offset; @@ -244,6 +270,11 @@ static void build_rhct(GArray *table_data, num_offsets++; } +if (mmu_offset) { +len += 4; +num_offsets++; +} + build_append_int_noprefix(table_data, len, 2); build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ /* Number of offsets */ @@ -252,9 +283,14 @@ static void build_rhct(GArray *table_data, /* Offsets */ build_append_int_noprefix(table_data, isa_offset, 4); + if (cmo_offset) { build_append_int_noprefix(table_data, cmo_offset, 4); } + +if (mmu_offset) { +build_append_int_noprefix(table_data, mmu_offset, 4); +} } acpi_table_end(linker, &table);
Re: [PATCH 10/10] hw/riscv/virt-acpi-build.c: Add IO controllers and devices
On 7/12/23 13:39, Sunil V L wrote: Add basic IO controllers and devices like PCI, VirtIO and UART in the ACPI namespace. Signed-off-by: Sunil V L --- Reviewed-by: Daniel Henrique Barboza hw/riscv/Kconfig | 1 + hw/riscv/virt-acpi-build.c | 87 ++ 2 files changed, 88 insertions(+) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index b6a5eb4452..a50717be87 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -45,6 +45,7 @@ config RISCV_VIRT select FW_CFG_DMA select PLATFORM_BUS select ACPI +select ACPI_PCI config SHAKTI_C bool diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index 25745eee4c..91f06fdc97 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -27,6 +27,7 @@ #include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" +#include "hw/acpi/pci.h" #include "hw/acpi/utils.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -35,6 +36,7 @@ #include "hw/riscv/virt.h" #include "hw/riscv/numa.h" #include "hw/intc/riscv_aclint.h" +#include "hw/pci-host/gpex.h" #define ACPI_BUILD_TABLE_SIZE 0x2 #define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) @@ -138,6 +140,55 @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) } } +static void +acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, +uint32_t uart_irq) +{ +Aml *dev = aml_device("COM0"); +aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); +aml_append(dev, aml_name_decl("_UID", aml_int(0))); + +Aml *crs = aml_resource_template(); +aml_append(crs, aml_memory32_fixed(uart_memmap->base, + uart_memmap->size, AML_READ_WRITE)); +aml_append(crs, +aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &uart_irq, 1)); +aml_append(dev, aml_name_decl("_CRS", crs)); + +Aml *pkg = aml_package(2); +aml_append(pkg, aml_string("clock-frequency")); +aml_append(pkg, aml_int(3686400)); + +Aml *UUID = aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"); + +Aml *pkg1 = aml_package(1); +aml_append(pkg1, pkg); + +Aml *package = aml_package(2); +aml_append(package, UUID); +aml_append(package, pkg1); + +aml_append(dev, aml_name_decl("_DSD", package)); +aml_append(scope, dev); +} + +static void +acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, + uint32_t irq, RISCVVirtState *s) +{ +struct GPEXConfig cfg = { +.mmio32 = memmap[VIRT_PCIE_MMIO], +.mmio64 = memmap[VIRT_HIGH_PCIE_MMIO], +.pio = memmap[VIRT_PCIE_PIO], +.ecam = memmap[VIRT_PCIE_ECAM], +.irq = irq, +.bus = s->bus, +}; + +acpi_dsdt_add_gpex(scope, &cfg); +} + /* RHCT Node[N] starts at offset 56 */ #define RHCT_NODE_ARRAY_OFFSET 56 @@ -318,6 +369,8 @@ static void build_dsdt(GArray *table_data, RISCVVirtState *s) { Aml *scope, *dsdt; +MachineState *ms = MACHINE(s); +uint8_t socket_count; const MemMapEntry *memmap = s->memmap; AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = s->oem_id, .oem_table_id = s->oem_table_id }; @@ -337,6 +390,30 @@ static void build_dsdt(GArray *table_data, acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); +socket_count = riscv_socket_count(ms); + +acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ); + +if (socket_count == 1) { +acpi_dsdt_add_virtio(scope, &memmap[VIRT_VIRTIO], + VIRTIO_IRQ, VIRTIO_COUNT); +acpi_dsdt_add_pci(scope, memmap, PCIE_IRQ, s); +} else if (socket_count == 2) { +acpi_dsdt_add_virtio(scope, &memmap[VIRT_VIRTIO], + VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, + VIRTIO_COUNT); +acpi_dsdt_add_pci(scope, memmap, + PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES, + s); +} else { +acpi_dsdt_add_virtio(scope, &memmap[VIRT_VIRTIO], + VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, + VIRTIO_COUNT); +acpi_dsdt_add_pci(scope, memmap, + PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES * 2, + s); +} + aml_append(dsdt, scope); /* copy AML table into ACPI tables blob and patch header there */ @@ -486,6 +563,16 @@ static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_rhct(tables_blob, tables->linker, s); +acpi_add_table(table_offsets, tables_blob); +{ +AcpiMcfgInfo mcfg = { + .base = s->memmap[VIRT_PCIE_MMIO].base, + .size = s
Re: [PATCH v4 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
On Tue, Jul 04, 2023 at 05:33:57PM +0900, Jeuk Kim wrote: > From: Jeuk Kim > > Universal Flash Storage (UFS) is a high-performance mass storage device > with a serial interface. It is primarily used as a high-performance > data storage device for embedded applications. > > This commit contains code for UFS device to be recognized > as a UFS PCI device. > Patches to handle UFS logical unit and Transfer Request will follow. > > Signed-off-by: Jeuk Kim > --- > MAINTAINERS |6 + > docs/specs/pci-ids.rst |2 + > hw/Kconfig |1 + > hw/meson.build |1 + > hw/ufs/Kconfig |4 + > hw/ufs/meson.build |1 + > hw/ufs/trace-events | 33 ++ > hw/ufs/trace.h |1 + > hw/ufs/ufs.c | 304 +++ > hw/ufs/ufs.h | 42 ++ > include/block/ufs.h | 1048 ++ > include/hw/pci/pci.h |1 + > include/hw/pci/pci_ids.h |1 + > meson.build |1 + > 14 files changed, 1446 insertions(+) > create mode 100644 hw/ufs/Kconfig > create mode 100644 hw/ufs/meson.build > create mode 100644 hw/ufs/trace-events > create mode 100644 hw/ufs/trace.h > create mode 100644 hw/ufs/ufs.c > create mode 100644 hw/ufs/ufs.h > create mode 100644 include/block/ufs.h > > diff --git a/MAINTAINERS b/MAINTAINERS > index 4feea49a6e..756aae8623 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -2237,6 +2237,12 @@ F: tests/qtest/nvme-test.c > F: docs/system/devices/nvme.rst > T: git git://git.infradead.org/qemu-nvme.git nvme-next > > +ufs > +M: Jeuk Kim > +S: Supported > +F: hw/ufs/* > +F: include/block/ufs.h > + > megasas > M: Hannes Reinecke > L: qemu-bl...@nongnu.org > diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst > index e302bea484..d6707fa069 100644 > --- a/docs/specs/pci-ids.rst > +++ b/docs/specs/pci-ids.rst > @@ -92,6 +92,8 @@ PCI devices (other than virtio): >PCI PVPanic device (``-device pvpanic-pci``) > 1b36:0012 >PCI ACPI ERST device (``-device acpi-erst``) > +1b36:0013 > + PCI UFS device (``-device ufs``) > > All these devices are documented in :doc:`index`. > > diff --git a/hw/Kconfig b/hw/Kconfig > index ba62ff6417..9ca7b38c31 100644 > --- a/hw/Kconfig > +++ b/hw/Kconfig > @@ -38,6 +38,7 @@ source smbios/Kconfig > source ssi/Kconfig > source timer/Kconfig > source tpm/Kconfig > +source ufs/Kconfig > source usb/Kconfig > source virtio/Kconfig > source vfio/Kconfig > diff --git a/hw/meson.build b/hw/meson.build > index c7ac7d3d75..f01fac4617 100644 > --- a/hw/meson.build > +++ b/hw/meson.build > @@ -37,6 +37,7 @@ subdir('smbios') > subdir('ssi') > subdir('timer') > subdir('tpm') > +subdir('ufs') > subdir('usb') > subdir('vfio') > subdir('virtio') > diff --git a/hw/ufs/Kconfig b/hw/ufs/Kconfig > new file mode 100644 > index 00..b7b3392e85 > --- /dev/null > +++ b/hw/ufs/Kconfig > @@ -0,0 +1,4 @@ > +config UFS_PCI > +bool > +default y if PCI_DEVICES > +depends on PCI > diff --git a/hw/ufs/meson.build b/hw/ufs/meson.build > new file mode 100644 > index 00..eb5164bde9 > --- /dev/null > +++ b/hw/ufs/meson.build > @@ -0,0 +1 @@ > +system_ss.add(when: 'CONFIG_UFS_PCI', if_true: files('ufs.c')) > diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events > new file mode 100644 > index 00..17793929b1 > --- /dev/null > +++ b/hw/ufs/trace-events > @@ -0,0 +1,33 @@ > +# ufs.c > +ufs_irq_raise(void) "INTx" > +ufs_irq_lower(void) "INTx" > +ufs_mmio_read(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" > data 0x%"PRIx64" size %d" > +ufs_mmio_write(uint64_t addr, uint64_t data, unsigned size) "addr > 0x%"PRIx64" data 0x%"PRIx64" size %d" > +ufs_process_db(uint32_t slot) "UTRLDBR slot %"PRIu32"" > +ufs_process_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" > +ufs_complete_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" > +ufs_sendback_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" > +ufs_exec_nop_cmd(uint32_t slot) "UTRLDBR slot %"PRIu32"" > +ufs_exec_scsi_cmd(uint32_t slot, uint8_t lun, uint8_t opcode) "slot > %"PRIu32", lun 0x%"PRIx8", opcode 0x%"PRIx8"" > +ufs_exec_query_cmd(uint32_t slot, uint8_t opcode) "slot %"PRIu32", opcode > 0x%"PRIx8"" > +ufs_process_uiccmd(uint32_t uiccmd, uint32_t ucmdarg1, uint32_t ucmdarg2, > uint32_t ucmdarg3) "uiccmd 0x%"PRIx32", ucmdarg1 0x%"PRIx32", ucmdarg2 > 0x%"PRIx32", ucmdarg3 0x%"PRIx32"" > + > +# error condition > +ufs_err_memory_allocation(void) "failed to allocate memory" > +ufs_err_dma_read_utrd(uint32_t slot, uint64_t addr) "failed to read utrd. > UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" > +ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req > upiu. UTRLDBR slot %"PRIu32", request upiu addr %"PRIu64"" > +ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. > UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" > +ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to wr
Re: [PATCH v4 2/3] hw/ufs: Support for Query Transfer Requests
On Tue, Jul 04, 2023 at 05:33:58PM +0900, Jeuk Kim wrote: > +static MemTxResult ufs_dma_read_prdt(UfsRequest *req) > +{ > +UfsHc *u = req->hc; > +uint16_t prdt_len = le16_to_cpu(req->utrd.prd_table_length); > +uint16_t prdt_byte_off = > +le16_to_cpu(req->utrd.prd_table_offset) * sizeof(uint32_t); > +uint32_t prdt_size = prdt_len * sizeof(UfshcdSgEntry); > +g_autofree UfshcdSgEntry *prd_entries = NULL; > +hwaddr req_upiu_base_addr, prdt_base_addr; > +int err; > + > +assert(!req->sg); > + > +if (prdt_len == 0) { > +return MEMTX_OK; > +} > + > +prd_entries = g_new(UfshcdSgEntry, prdt_size); > +if (!prd_entries) { g_new() never returns NULL. The process aborts if there is not enough memory available. Use g_try_new() if you want to handle memory allocation failure. > +trace_ufs_err_memory_allocation(); > +return MEMTX_ERROR; > +} > + > +req_upiu_base_addr = ufs_get_req_upiu_base_addr(&req->utrd); > +prdt_base_addr = req_upiu_base_addr + prdt_byte_off; > + > +err = ufs_addr_read(u, prdt_base_addr, prd_entries, prdt_size); > +if (err) { > +trace_ufs_err_dma_read_prdt(req->slot, prdt_base_addr); > +return err; > +} > + > +req->sg = g_malloc0(sizeof(QEMUSGList)); > +if (!req->sg) { g_malloc0() never returns NULL. The process aborts if there is not enough memory available. signature.asc Description: PGP signature
Re: [PATCH v4 3/3] hw/ufs: Support for UFS logical unit
On Tue, Jul 04, 2023 at 05:33:59PM +0900, Jeuk Kim wrote: > +static Property ufs_lu_props[] = { > +DEFINE_PROP_DRIVE_IOTHREAD("drive", UfsLu, qdev.conf.blk), This device is not aware of IOThreads, so I think DEFINE_PROP_DRIVE() should be used instead. signature.asc Description: PGP signature
[PATCH for-8.2 v4 00/11] riscv: add 'max' CPU, deprecate 'any'
Hi, This new version has some adjustments w.r.t the KVM code that got a bit neglected in the last 3 versions. The most notable change is in patch 3, a new patch where we're moving the KVM property handling into an exclusive helper. This helped to unclog riscv_cpu_add_user_properties() a lot, making it easier for future cleanups we're planning to do in this code. Patch 4 (new) helped to padronize the code even more, allowing for more macro usages to reduce repetition. Patch 8 (new) is basically patch 7 for KVM properties. Patches missing review: 3, 4, 8, 10, 11 Changes from v3: - patch 1: - skip existing riscv_cpu_options before calling qdev_prop_add_static() - patch 3 (new): - move kvm CPU property handling to riscv_cpu_add_kvm_properties() - patch 4 (new): - remove DEFINE_PROP_END_OF_LIST() for riscv_cpu_extensions[] - patch 7 (former 5): - rename macro to ADD_CPU_QDEV_PROPERTIES_ARRAY() - patch 8 (new): - add ADD_UNAVAIL_KVM_PROP_ARRAY macro - v3 link: https://lore.kernel.org/qemu-riscv/20230714174311.672359-1-dbarb...@ventanamicro.com/ Daniel Henrique Barboza (11): target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[] target/riscv/cpu.c: skip 'bool' check when filtering KVM props target/riscv/cpu.c: split kvm prop handling to its own helper target/riscv/cpu.c: del DEFINE_PROP_END_OF_LIST() from riscv_cpu_extensions target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[] target/riscv/cpu.c: add ADD_CPU_QDEV_PROPERTIES_ARRAY() macro target/riscv/cpu.c: add ADD_UNAVAIL_KVM_PROP_ARRAY() macro target/riscv: add 'max' CPU type avocado, risc-v: add opensbi tests for 'max' CPU target/riscv: deprecate the 'any' CPU type docs/about/deprecated.rst | 12 +++ target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 169 + tests/avocado/riscv_opensbi.py | 16 4 files changed, 160 insertions(+), 38 deletions(-) -- 2.41.0
[PATCH for-8.2 v4 01/11] target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[]
We'll add a new CPU type that will enable a considerable amount of extensions. To make it easier for us we'll do a few cleanups in our existing riscv_cpu_extensions[] array. Start by splitting all CPU non-boolean options from it. Create a new riscv_cpu_options[] array for them. Add all these properties in riscv_cpu_add_user_properties() as it is already being done today. No functional changes made. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 28 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9339c0241d..587a5a9548 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1751,7 +1751,6 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ -DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), @@ -1767,11 +1766,6 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true), -DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), -DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), -DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), -DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), - DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false), DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true), DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false), @@ -1802,9 +1796,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false), DEFINE_PROP_BOOL("zicbom", RISCVCPU, cfg.ext_icbom, true), -DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true), -DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false), @@ -1848,6 +1840,18 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_END_OF_LIST(), }; +static Property riscv_cpu_options[] = { +DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), + +DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), +DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), + +DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), +DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), + +DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), +DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), +}; #ifndef CONFIG_USER_ONLY static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, @@ -1916,6 +1920,14 @@ static void riscv_cpu_add_user_properties(Object *obj) #endif qdev_property_add_static(dev, prop); } + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { +/* Check if KVM created the property already */ +if (object_property_find(obj, riscv_cpu_options[i].name)) { +continue; +} +qdev_property_add_static(dev, &riscv_cpu_options[i]); +} } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH for-8.2 v4 10/11] avocado, risc-v: add opensbi tests for 'max' CPU
Add smoke tests to ensure that we'll not break the 'max' CPU type when adding new ratified extensions to be enabled. Signed-off-by: Daniel Henrique Barboza --- tests/avocado/riscv_opensbi.py | 16 1 file changed, 16 insertions(+) diff --git a/tests/avocado/riscv_opensbi.py b/tests/avocado/riscv_opensbi.py index bfff9cc3c3..15fd57fe51 100644 --- a/tests/avocado/riscv_opensbi.py +++ b/tests/avocado/riscv_opensbi.py @@ -61,3 +61,19 @@ def test_riscv64_virt(self): :avocado: tags=machine:virt """ self.boot_opensbi() + +def test_riscv32_virt_maxcpu(self): +""" +:avocado: tags=arch:riscv32 +:avocado: tags=machine:virt +:avocado: tags=cpu:max +""" +self.boot_opensbi() + +def test_riscv64_virt_maxcpu(self): +""" +:avocado: tags=arch:riscv64 +:avocado: tags=machine:virt +:avocado: tags=cpu:max +""" +self.boot_opensbi() -- 2.41.0
[PATCH for-8.2 v4 05/11] target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[]
Our goal is to make riscv_cpu_extensions[] hold only ratified, non-vendor extensions. Create a new riscv_cpu_vendor_exts[] array for them, changing riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties() accordingly. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 37 +++-- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 918acb9e6c..b59b06cddd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1808,20 +1808,6 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false), DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false), -/* Vendor-specific custom extensions */ -DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false), -DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false), -DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false), -DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false), -DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false), -DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false), -DEFINE_PROP_BOOL("xtheadfmv", RISCVCPU, cfg.ext_xtheadfmv, false), -DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false), -DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false), -DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false), -DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false), -DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), - /* These are experimental so mark with 'x-' */ DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false), @@ -1838,6 +1824,21 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false), }; +static Property riscv_cpu_vendor_exts[] = { +DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false), +DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false), +DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false), +DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false), +DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false), +DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false), +DEFINE_PROP_BOOL("xtheadfmv", RISCVCPU, cfg.ext_xtheadfmv, false), +DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false), +DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false), +DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false), +DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false), +DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), +}; + static Property riscv_cpu_options[] = { DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), @@ -1899,6 +1900,10 @@ static void riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_extensions[i].name); } +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_vendor_exts); i++) { +riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_vendor_exts[i].name); +} + for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { /* Check if KVM created the property already */ if (object_property_find(obj, riscv_cpu_options[i].name)) { @@ -1937,6 +1942,10 @@ static void riscv_cpu_add_user_properties(Object *obj) for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { qdev_property_add_static(dev, &riscv_cpu_options[i]); } + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_vendor_exts); i++) { +qdev_property_add_static(dev, &riscv_cpu_vendor_exts[i]); +} } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH for-8.2 v4 09/11] target/riscv: add 'max' CPU type
The 'max' CPU type is used by tooling to determine what's the most capable CPU a current QEMU version implements. Other archs such as ARM implements this type. Let's add it to RISC-V. What we consider "most capable CPU" in this context are related to ratified, non-vendor extensions. This means that we want the 'max' CPU to enable all (possible) ratified extensions by default. The reasoning behind this design is (1) vendor extensions can conflict with each other and we won't play favorities deciding which one is default or not and (2) non-ratified extensions are always prone to changes, not being stable enough to be enabled by default. All this said, we're still not able to enable all ratified extensions due to conflicts between them. Zfinx and all its dependencies aren't enabled because of a conflict with RVF. zce, zcmp and zcmt are also disabled due to RVD conflicts. When running with 64 bits we're also disabling zcf. MISA bits RVG, RVJ and RVV are also being set manually since they're default disabled. This is the resulting 'riscv,isa' DT for this new CPU: rv64imafdcvh_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_ zfh_zfhmin_zca_zcb_zcd_zba_zbb_zbc_zbkb_zbkc_zbkx_zbs_zk_zkn_zknd_ zkne_zknh_zkr_zks_zksed_zksh_zkt_zve32f_zve64f_zve64d_ smstateen_sscofpmf_sstc_svadu_svinval_svnapot_svpbmt Signed-off-by: Daniel Henrique Barboza Reviewed-by: Weiwei Li --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 53 ++ 2 files changed, 54 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 04af50983e..f3fbe37a2c 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -30,6 +30,7 @@ #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") +#define TYPE_RISCV_CPU_MAX RISCV_CPU_TYPE_NAME("max") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7f79585bd1..7fdde68dee 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -248,6 +248,7 @@ static const char * const riscv_intr_names[] = { }; static void riscv_cpu_add_user_properties(Object *obj); +static void riscv_init_max_cpu_extensions(Object *obj); const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) { @@ -374,6 +375,25 @@ static void riscv_any_cpu_init(Object *obj) cpu->cfg.pmp = true; } +static void riscv_max_cpu_init(Object *obj) +{ +RISCVCPU *cpu = RISCV_CPU(obj); +CPURISCVState *env = &cpu->env; +RISCVMXL mlx = MXL_RV64; + +#ifdef TARGET_RISCV32 +mlx = MXL_RV32; +#endif +set_misa(env, mlx, 0); +riscv_cpu_add_user_properties(obj); +riscv_init_max_cpu_extensions(obj); +env->priv_ver = PRIV_VERSION_LATEST; +#ifndef CONFIG_USER_ONLY +set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ? +VM_1_10_SV32 : VM_1_10_SV57); +#endif +} + #if defined(TARGET_RISCV64) static void rv64_base_cpu_init(Object *obj) { @@ -1953,6 +1973,38 @@ static void riscv_cpu_add_user_properties(Object *obj) ADD_CPU_QDEV_PROPERTIES_ARRAY(dev, riscv_cpu_experimental_exts); } +/* + * The 'max' type CPU will have all possible ratified + * non-vendor extensions enabled. + */ +static void riscv_init_max_cpu_extensions(Object *obj) +{ +RISCVCPU *cpu = RISCV_CPU(obj); +CPURISCVState *env = &cpu->env; +Property *prop; + +/* Enable RVG, RVJ and RVV that are disabled by default */ +set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV); + +for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { +object_property_set_bool(obj, prop->name, true, NULL); +} + +/* Zfinx is not compatible with F. Disable it */ +object_property_set_bool(obj, "zfinx", false, NULL); +object_property_set_bool(obj, "zdinx", false, NULL); +object_property_set_bool(obj, "zhinx", false, NULL); +object_property_set_bool(obj, "zhinxmin", false, NULL); + +object_property_set_bool(obj, "zce", false, NULL); +object_property_set_bool(obj, "zcmp", false, NULL); +object_property_set_bool(obj, "zcmt", false, NULL); + +if (env->misa_mxl != MXL_RV32) { +object_property_set_bool(obj, "zcf", false, NULL); +} +} + static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true), @@ -2291,6 +2343,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { .abstract = true, }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), +DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), #if defined(CONFIG_KVM) DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), #endif -- 2.41.0
[PATCH for-8.2 v4 04/11] target/riscv/cpu.c: del DEFINE_PROP_END_OF_LIST() from riscv_cpu_extensions
This last blank element is used by the 'for' loop to check if a property has a valid name. Remove it and use ARRAY_SIZE() instead like riscv_cpu_options is already using. All future arrays will also do the same and we'll able to encapsulate more repetitions in macros later on. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1b6d546522..918acb9e6c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1836,8 +1836,6 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("x-zfbfmin", RISCVCPU, cfg.ext_zfbfmin, false), DEFINE_PROP_BOOL("x-zvfbfmin", RISCVCPU, cfg.ext_zvfbfmin, false), DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false), - -DEFINE_PROP_END_OF_LIST(), }; static Property riscv_cpu_options[] = { @@ -1892,14 +1890,13 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) static void riscv_cpu_add_kvm_properties(Object *obj) { -Property *prop; DeviceState *dev = DEVICE(obj); kvm_riscv_init_user_properties(obj); riscv_cpu_add_misa_properties(obj); -for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_extensions); i++) { +riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_extensions[i].name); } for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { @@ -1920,7 +1917,6 @@ static void riscv_cpu_add_kvm_properties(Object *obj) */ static void riscv_cpu_add_user_properties(Object *obj) { -Property *prop; DeviceState *dev = DEVICE(obj); #ifndef CONFIG_USER_ONLY @@ -1934,8 +1930,8 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_misa_properties(obj); -for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -qdev_property_add_static(dev, prop); +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_extensions); i++) { +qdev_property_add_static(dev, &riscv_cpu_extensions[i]); } for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { -- 2.41.0
[PATCH for-8.2 v4 07/11] target/riscv/cpu.c: add ADD_CPU_QDEV_PROPERTIES_ARRAY() macro
The code inside riscv_cpu_add_user_properties() became quite repetitive after recent changes. Add a macro to hide the repetition away. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Weiwei Li --- target/riscv/cpu.c | 26 +++--- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 4d78276058..58cbe410e2 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1873,6 +1873,13 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, } #endif +#define ADD_CPU_QDEV_PROPERTIES_ARRAY(_dev, _array) \ +do { \ +for (int i = 0; i < ARRAY_SIZE(_array); i++) { \ +qdev_property_add_static(_dev, &_array[i]); \ +} \ +} while (0) + #ifndef CONFIG_USER_ONLY static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) { @@ -1942,21 +1949,10 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_misa_properties(obj); -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_extensions); i++) { -qdev_property_add_static(dev, &riscv_cpu_extensions[i]); -} - -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { -qdev_property_add_static(dev, &riscv_cpu_options[i]); -} - -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_vendor_exts); i++) { -qdev_property_add_static(dev, &riscv_cpu_vendor_exts[i]); -} - -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_experimental_exts); i++) { -qdev_property_add_static(dev, &riscv_cpu_experimental_exts[i]); -} +ADD_CPU_QDEV_PROPERTIES_ARRAY(dev, riscv_cpu_extensions); +ADD_CPU_QDEV_PROPERTIES_ARRAY(dev, riscv_cpu_options); +ADD_CPU_QDEV_PROPERTIES_ARRAY(dev, riscv_cpu_vendor_exts); +ADD_CPU_QDEV_PROPERTIES_ARRAY(dev, riscv_cpu_experimental_exts); } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH for-8.2 v4 02/11] target/riscv/cpu.c: skip 'bool' check when filtering KVM props
After the introduction of riscv_cpu_options[] all properties in riscv_cpu_extensions[] are booleans. This check is now obsolete. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 14 -- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 587a5a9548..29f2543f6d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1905,17 +1905,11 @@ static void riscv_cpu_add_user_properties(Object *obj) * Set the default to disabled for every extension * unknown to KVM and error out if the user attempts * to enable any of them. - * - * We're giving a pass for non-bool properties since they're - * not related to the availability of extensions and can be - * safely ignored as is. */ -if (prop->info == &qdev_prop_bool) { -object_property_add(obj, prop->name, "bool", -NULL, cpu_set_cfg_unavailable, -NULL, (void *)prop->name); -continue; -} +object_property_add(obj, prop->name, "bool", +NULL, cpu_set_cfg_unavailable, +NULL, (void *)prop->name); +continue; } #endif qdev_property_add_static(dev, prop); -- 2.41.0
[PATCH for-8.2 v4 11/11] target/riscv: deprecate the 'any' CPU type
The 'any' CPU type was introduced in commit dc5bd18fa5725 ("RISC-V CPU Core Definition"), being around since the beginning. It's not an easy CPU to use: it's undocumented and its name doesn't tell users much about what the CPU is supposed to bring. 'git log' doesn't help us either in knowing what was the original design of this CPU type. The closest we have is a comment from Alistair [1] where he recalls from memory that the 'any' CPU is supposed to behave like the newly added 'max' CPU. He also suggested that the 'any' CPU should be removed. The default CPUs are rv32 and rv64, so removing the 'any' CPU will have impact only on users that might have a script that uses '-cpu any'. And those users are better off using the default CPUs or the new 'max' CPU. We would love to just remove the code and be done with it, but one does not simply remove a feature in QEMU. We'll put the CPU in quarantine first, letting users know that we have the intent of removing it in the future. [1] https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg02891.html Signed-off-by: Daniel Henrique Barboza --- docs/about/deprecated.rst | 12 target/riscv/cpu.c| 5 + 2 files changed, 17 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 02ea5a839f..68afa43fd0 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -371,6 +371,18 @@ QEMU's ``vhost`` feature, which would eliminate the high latency costs under which the 9p ``proxy`` backend currently suffers. However as of to date nobody has indicated plans for such kind of reimplemention unfortunately. +RISC-V 'any' CPU type ``-cpu any`` (since 8.2) +^^ + +The 'any' CPU type was introduced back in 2018 and has been around since the +initial RISC-V QEMU port. Its usage has always been unclear: users don't know +what to expect from a CPU called 'any', and in fact the CPU does not do anything +special that aren't already done by the default CPUs rv32/rv64. + +After the introduction of the 'max' CPU type RISC-V now has a good coverage +of generic CPUs: rv32 and rv64 as default CPUs and 'max' as a feature complete +CPU for both 32 and 64 bit builds. Users are then discouraged to use the 'any' +CPU type starting in 8.2. Block device options diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7fdde68dee..edf3b95a14 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1470,6 +1470,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); Error *local_err = NULL; +if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_ANY) != NULL) { +warn_report("The 'any' CPU is deprecated and will be " +"removed in the future."); +} + cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); -- 2.41.0
[PATCH for-8.2 v4 06/11] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[]
Create a new riscv_cpu_experimental_exts[] to store the non-ratified extensions properties. Once they are ratified we'll move them back to riscv_cpu_extensions[]. riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties() are changed to keep adding non-ratified properties to users. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 41 ++--- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index b59b06cddd..4d78276058 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1807,21 +1807,6 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false), DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false), DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false), - -/* These are experimental so mark with 'x-' */ -DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false), - -/* ePMP 0.9.3 */ -DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), -DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false), -DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false), - -DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false), -DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false), - -DEFINE_PROP_BOOL("x-zfbfmin", RISCVCPU, cfg.ext_zfbfmin, false), -DEFINE_PROP_BOOL("x-zvfbfmin", RISCVCPU, cfg.ext_zvfbfmin, false), -DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false), }; static Property riscv_cpu_vendor_exts[] = { @@ -1839,6 +1824,23 @@ static Property riscv_cpu_vendor_exts[] = { DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), }; +/* These are experimental so mark with 'x-' */ +static Property riscv_cpu_experimental_exts[] = { +DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false), + +/* ePMP 0.9.3 */ +DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), +DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false), +DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false), + +DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false), +DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false), + +DEFINE_PROP_BOOL("x-zfbfmin", RISCVCPU, cfg.ext_zfbfmin, false), +DEFINE_PROP_BOOL("x-zvfbfmin", RISCVCPU, cfg.ext_zvfbfmin, false), +DEFINE_PROP_BOOL("x-zvfbfwma", RISCVCPU, cfg.ext_zvfbfwma, false), +}; + static Property riscv_cpu_options[] = { DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), @@ -1904,6 +1906,11 @@ static void riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_vendor_exts[i].name); } +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_experimental_exts); i++) { +riscv_cpu_add_kvm_unavail_prop(obj, + riscv_cpu_experimental_exts[i].name); +} + for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { /* Check if KVM created the property already */ if (object_property_find(obj, riscv_cpu_options[i].name)) { @@ -1946,6 +1953,10 @@ static void riscv_cpu_add_user_properties(Object *obj) for (int i = 0; i < ARRAY_SIZE(riscv_cpu_vendor_exts); i++) { qdev_property_add_static(dev, &riscv_cpu_vendor_exts[i]); } + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_experimental_exts); i++) { +qdev_property_add_static(dev, &riscv_cpu_experimental_exts[i]); +} } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH for-8.2 v4 03/11] target/riscv/cpu.c: split kvm prop handling to its own helper
Future patches will split the existing Property arrays even further, and the existing code in riscv_cpu_add_user_properties() will start to scale bad with it because it's dealing with KVM constraints mixed in with TCG constraints. We're going to pay a high price to share a couple of common lines of code between the two. Create a new riscv_cpu_add_kvm_properties() that will be forked from riscv_cpu_add_user_properties() if we're running KVM. The helper includes all properties that a KVM CPU will add. The rest of riscv_cpu_add_user_properties() body will then be relieved from having to deal with KVM constraints. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 65 ++ 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 29f2543f6d..1b6d546522 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1872,6 +1872,46 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, } #endif +#ifndef CONFIG_USER_ONLY +static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) +{ +/* Check if KVM created the property already */ +if (object_property_find(obj, prop_name)) { +return; +} + +/* + * Set the default to disabled for every extension + * unknown to KVM and error out if the user attempts + * to enable any of them. + */ +object_property_add(obj, prop_name, "bool", +NULL, cpu_set_cfg_unavailable, +NULL, (void *)prop_name); +} + +static void riscv_cpu_add_kvm_properties(Object *obj) +{ +Property *prop; +DeviceState *dev = DEVICE(obj); + +kvm_riscv_init_user_properties(obj); +riscv_cpu_add_misa_properties(obj); + +for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { +riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +} + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { +/* Check if KVM created the property already */ +if (object_property_find(obj, riscv_cpu_options[i].name)) { +continue; +} +qdev_property_add_static(dev, &riscv_cpu_options[i]); +} +} +#endif + /* * Add CPU properties with user-facing flags. * @@ -1887,39 +1927,18 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_add_satp_mode_properties(obj); if (kvm_enabled()) { -kvm_riscv_init_user_properties(obj); +riscv_cpu_add_kvm_properties(obj); +return; } #endif riscv_cpu_add_misa_properties(obj); for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -#ifndef CONFIG_USER_ONLY -if (kvm_enabled()) { -/* Check if KVM created the property already */ -if (object_property_find(obj, prop->name)) { -continue; -} - -/* - * Set the default to disabled for every extension - * unknown to KVM and error out if the user attempts - * to enable any of them. - */ -object_property_add(obj, prop->name, "bool", -NULL, cpu_set_cfg_unavailable, -NULL, (void *)prop->name); -continue; -} -#endif qdev_property_add_static(dev, prop); } for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { -/* Check if KVM created the property already */ -if (object_property_find(obj, riscv_cpu_options[i].name)) { -continue; -} qdev_property_add_static(dev, &riscv_cpu_options[i]); } } -- 2.41.0
[PATCH for-8.2 v4 08/11] target/riscv/cpu.c: add ADD_UNAVAIL_KVM_PROP_ARRAY() macro
Use a macro in riscv_cpu_add_kvm_properties() to eliminate some of its code repetition, similar to what we're already doing with ADD_CPU_QDEV_PROPERTIES_ARRAY(). Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 22 ++ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 58cbe410e2..7f79585bd1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1898,6 +1898,13 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) NULL, (void *)prop_name); } +#define ADD_UNAVAIL_KVM_PROP_ARRAY(_obj, _array) \ +do { \ +for (int i = 0; i < ARRAY_SIZE(_array); i++) { \ +riscv_cpu_add_kvm_unavail_prop(_obj, _array[i].name); \ +} \ +} while (0) + static void riscv_cpu_add_kvm_properties(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -1905,18 +1912,9 @@ static void riscv_cpu_add_kvm_properties(Object *obj) kvm_riscv_init_user_properties(obj); riscv_cpu_add_misa_properties(obj); -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_extensions); i++) { -riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_extensions[i].name); -} - -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_vendor_exts); i++) { -riscv_cpu_add_kvm_unavail_prop(obj, riscv_cpu_vendor_exts[i].name); -} - -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_experimental_exts); i++) { -riscv_cpu_add_kvm_unavail_prop(obj, - riscv_cpu_experimental_exts[i].name); -} +ADD_UNAVAIL_KVM_PROP_ARRAY(obj, riscv_cpu_extensions); +ADD_UNAVAIL_KVM_PROP_ARRAY(obj, riscv_cpu_vendor_exts); +ADD_UNAVAIL_KVM_PROP_ARRAY(obj, riscv_cpu_experimental_exts); for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { /* Check if KVM created the property already */ -- 2.41.0
[PATCH 07/14] target/s390x: Fix assertion failure in VFMIN/VFMAX with reserved type
Passing reserved type to VFMIN/VFMAX causes an assertion failure in vfmin_res() and vfmax_res(). These instructions should raise a specification exception in this case. Cc: qemu-sta...@nongnu.org Fixes: da4807527f3b ("s390x/tcg: Implement VECTOR FP (MAXIMUM|MINIMUM)") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/vec_fpu_helper.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/target/s390x/tcg/vec_fpu_helper.c b/target/s390x/tcg/vec_fpu_helper.c index 75cf605b9f4..f1671679879 100644 --- a/target/s390x/tcg/vec_fpu_helper.c +++ b/target/s390x/tcg/vec_fpu_helper.c @@ -915,7 +915,7 @@ static void vfminmax32(S390Vector *v1, const S390Vector *v2, float32 b = s390_vec_read_float32(v3, i); float32 result; -if (type != S390_MINMAX_TYPE_IEEE) { +if (type > S390_MINMAX_TYPE_IEEE && type <= S390_MINMAX_TYPE_F) { S390MinMaxRes res; if (is_abs) { @@ -944,12 +944,14 @@ static void vfminmax32(S390Vector *v1, const S390Vector *v2, default: g_assert_not_reached(); } -} else if (!is_abs) { +} else if (type == S390_MINMAX_TYPE_IEEE && !is_abs) { result = is_min ? float32_minnum(a, b, &env->fpu_status) : float32_maxnum(a, b, &env->fpu_status); -} else { +} else if (type == S390_MINMAX_TYPE_IEEE) { result = is_min ? float32_minnummag(a, b, &env->fpu_status) : float32_maxnummag(a, b, &env->fpu_status); +} else { +tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); } s390_vec_write_float32(&tmp, i, result); @@ -977,7 +979,7 @@ static void vfminmax64(S390Vector *v1, const S390Vector *v2, float64 b = s390_vec_read_float64(v3, i); float64 result; -if (type != S390_MINMAX_TYPE_IEEE) { +if (type > S390_MINMAX_TYPE_IEEE && type <= S390_MINMAX_TYPE_F) { S390MinMaxRes res; if (is_abs) { @@ -1006,12 +1008,14 @@ static void vfminmax64(S390Vector *v1, const S390Vector *v2, default: g_assert_not_reached(); } -} else if (!is_abs) { +} else if (type == S390_MINMAX_TYPE_IEEE && !is_abs) { result = is_min ? float64_minnum(a, b, &env->fpu_status) : float64_maxnum(a, b, &env->fpu_status); -} else { +} else if (type == S390_MINMAX_TYPE_IEEE) { result = is_min ? float64_minnummag(a, b, &env->fpu_status) : float64_maxnummag(a, b, &env->fpu_status); +} else { +tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); } s390_vec_write_float64(&tmp, i, result); @@ -1035,7 +1039,7 @@ static void vfminmax128(S390Vector *v1, const S390Vector *v2, uint8_t vxc, vec_exc = 0; float128 result; -if (type != S390_MINMAX_TYPE_IEEE) { +if (type > S390_MINMAX_TYPE_IEEE && type <= S390_MINMAX_TYPE_F) { S390MinMaxRes res; if (is_abs) { @@ -1064,12 +1068,14 @@ static void vfminmax128(S390Vector *v1, const S390Vector *v2, default: g_assert_not_reached(); } -} else if (!is_abs) { +} else if (type == S390_MINMAX_TYPE_IEEE && !is_abs) { result = is_min ? float128_minnum(a, b, &env->fpu_status) : float128_maxnum(a, b, &env->fpu_status); -} else { +} else if (type == S390_MINMAX_TYPE_IEEE) { result = is_min ? float128_minnummag(a, b, &env->fpu_status) : float128_maxnummag(a, b, &env->fpu_status); +} else { +tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); } vxc = check_ieee_exc(env, 0, false, &vec_exc); -- 2.41.0
[PATCH 09/14] tests/tcg/s390x: Test CLGEBR and CGEBRA
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.target | 5 + tests/tcg/s390x/cgebra.c| 32 tests/tcg/s390x/clgebr.c| 32 3 files changed, 69 insertions(+) create mode 100644 tests/tcg/s390x/cgebra.c create mode 100644 tests/tcg/s390x/clgebr.c diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 19fbbc6e531..71bf39b78d3 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -39,12 +39,17 @@ TESTS+=mxdb TESTS+=epsw TESTS+=larl TESTS+=mdeb +TESTS+=cgebra +TESTS+=clgebr cdsg: CFLAGS+=-pthread cdsg: LDFLAGS+=-pthread rxsbg: CFLAGS+=-O2 +cgebra: LDFLAGS+=-lm +clgebr: LDFLAGS+=-lm + include $(S390X_SRC)/pgm-specification.mak $(PGM_SPECIFICATION_TESTS): pgm-specification-user.o $(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-user.o diff --git a/tests/tcg/s390x/cgebra.c b/tests/tcg/s390x/cgebra.c new file mode 100644 index 000..f91e10d2d3c --- /dev/null +++ b/tests/tcg/s390x/cgebra.c @@ -0,0 +1,32 @@ +/* + * Test the CGEBRA instruction. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include +#include + +int main(void) +{ +float r2 = 1E+300; +long long r1; +int cc; + +feclearexcept(FE_ALL_EXCEPT); +asm("cgebra %[r1],%[m3],%[r2],%[m4]\n" +"ipm %[cc]\n" +: [r1] "=r" (r1) +, [cc] "=r" (cc) +: [m3] "i" (5) /* round toward 0 */ +, [r2] "f" (r2) +, [m4] "i" (8) /* bit 0 is set, but must be ignored; XxC is not set */ +: "cc"); +cc >>= 28; + +assert(r1 == 0x7fffLL); +assert(cc == 3); +assert(fetestexcept(FE_ALL_EXCEPT) == (FE_INVALID | FE_INEXACT)); + +return EXIT_SUCCESS; +} diff --git a/tests/tcg/s390x/clgebr.c b/tests/tcg/s390x/clgebr.c new file mode 100644 index 000..d491899b56e --- /dev/null +++ b/tests/tcg/s390x/clgebr.c @@ -0,0 +1,32 @@ +/* + * Test the CLGEBR instruction. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include +#include + +int main(void) +{ +float r2 = -1; +long long r1; +int cc; + +feclearexcept(FE_ALL_EXCEPT); +asm("clgebr %[r1],%[m3],%[r2],%[m4]\n" +"ipm %[cc]\n" +: [r1] "=r" (r1) +, [cc] "=r" (cc) +: [m3] "i" (5) /* round toward 0 */ +, [r2] "f" (r2) +, [m4] "i" (8) /* bit 0 is set, but must be ignored; XxC is not set */ +: "cc"); +cc >>= 28; + +assert(r1 == 0); +assert(cc == 3); +assert(fetestexcept(FE_ALL_EXCEPT) == (FE_INVALID | FE_INEXACT)); + +return EXIT_SUCCESS; +} -- 2.41.0
[PATCH 00/14] target/s390x: Miscellaneous TCG fixes, part 2
Hi, Here is another set of fixes for issues found by randomized testing. Most of them have to do with simple insufficient error handling or corner cases, but 3/14 and 6/14 took a while to figure out, and hopefully I got the fixes right. 13/14 is a test for an issue that Richard has already fixed, but I thought it would be helpful to have it anyway. Best regards, Ilya Ilya Leoshkevich (14): target/s390x: Make CKSM raise an exception if R2 is odd target/s390x: Fix CLM with M3=0 target/s390x: Fix CONVERT TO LOGICAL/FIXED with out-of-range inputs target/s390x: Fix ICM with M3=0 target/s390x: Make MC raise specification exception when class >= 16 tcg/{i386,s390x}: Add earlyclobber to the op_add2's first output target/s390x: Fix assertion failure in VFMIN/VFMAX with reserved type tests/tcg/s390x: Test CKSM tests/tcg/s390x: Test CLGEBR and CGEBRA tests/tcg/s390x: Test CLM tests/tcg/s390x: Test ICM tests/tcg/s390x: Test MC tests/tcg/s390x: Test STPQ tests/tcg/s390x: Test VCKSM target/s390x/tcg/excp_helper.c | 2 +- target/s390x/tcg/fpu_helper.c | 3 +- target/s390x/tcg/mem_helper.c | 5 +++ target/s390x/tcg/translate.c| 21 -- target/s390x/tcg/vec_fpu_helper.c | 24 +++ tcg/i386/tcg-target-con-set.h | 2 +- tcg/i386/tcg-target.c.inc | 2 +- tcg/s390x/tcg-target-con-set.h | 5 +-- tcg/s390x/tcg-target.c.inc | 4 +- tcg/tcg.c | 8 +++- tests/tcg/s390x/Makefile.softmmu-target | 5 +++ tests/tcg/s390x/Makefile.target | 6 +++ tests/tcg/s390x/cgebra.c| 32 ++ tests/tcg/s390x/cksm.S | 29 + tests/tcg/s390x/clgebr.c| 32 ++ tests/tcg/s390x/clm.S | 29 + tests/tcg/s390x/icm.S | 32 ++ tests/tcg/s390x/mc.S| 56 + tests/tcg/s390x/stpq.S | 20 + tests/tcg/s390x/vcksm.c | 31 ++ tests/tcg/s390x/vx.h| 2 + 21 files changed, 327 insertions(+), 23 deletions(-) create mode 100644 tests/tcg/s390x/cgebra.c create mode 100644 tests/tcg/s390x/cksm.S create mode 100644 tests/tcg/s390x/clgebr.c create mode 100644 tests/tcg/s390x/clm.S create mode 100644 tests/tcg/s390x/icm.S create mode 100644 tests/tcg/s390x/mc.S create mode 100644 tests/tcg/s390x/stpq.S create mode 100644 tests/tcg/s390x/vcksm.c -- 2.41.0
[PATCH 08/14] tests/tcg/s390x: Test CKSM
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/cksm.S | 29 + 2 files changed, 30 insertions(+) create mode 100644 tests/tcg/s390x/cksm.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 242c7b0f83c..e813e318db9 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -16,6 +16,7 @@ LDFLAGS=-nostdlib -static ASM_TESTS = \ bal \ +cksm \ exrl-ssm-early \ sam \ lpsw \ diff --git a/tests/tcg/s390x/cksm.S b/tests/tcg/s390x/cksm.S new file mode 100644 index 000..a45f3ef6bfd --- /dev/null +++ b/tests/tcg/s390x/cksm.S @@ -0,0 +1,29 @@ +.org 0x8e +program_interruption_code: +.org 0x1d0 /* program new PSW */ +.quad 0,pgm +.org 0x200 /* lowcore padding */ +.globl _start +_start: +lmg %r0,%r1,cksm_args +cksm %r2,%r0 +c %r2,cksm_exp +jne failure +cksm %r2,%r15 +failure: +lpswe failure_psw +pgm: +chhsi program_interruption_code,6 /* specification exception? */ +jne failure +lpswe success_psw +cksm_args: +.quad cksm_buf, 16 +cksm_buf: +.quad 0x, 0x12345678 +cksm_exp: +.long 0x89ab1234 +.align 8 +success_psw: +.quad 0x2,0xfff/* see is_special_wait_psw() */ +failure_psw: +.quad 0x2,0/* disabled wait */ -- 2.41.0
[PATCH 12/14] tests/tcg/s390x: Test MC
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/mc.S| 56 + 2 files changed, 57 insertions(+) create mode 100644 tests/tcg/s390x/mc.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 58684d7da71..145e0bfde16 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -24,6 +24,7 @@ ASM_TESTS = \ lpsw \ lpswe-early \ lra \ +mc \ ssm-early \ stosm-early \ unaligned-lowcore diff --git a/tests/tcg/s390x/mc.S b/tests/tcg/s390x/mc.S new file mode 100644 index 000..e7466bb4b57 --- /dev/null +++ b/tests/tcg/s390x/mc.S @@ -0,0 +1,56 @@ +.org 0x8d +ilc: +.org 0x8e +program_interruption_code: +.org 0x94 +monitor_class: +.org 0xb0 +monitor_code: +.org 0x150 +program_old_psw: +.org 0x1d0 /* program new PSW */ +.quad 0x18000,pgm /* 64-bit mode */ +.org 0x200 /* lowcore padding */ +.globl _start +_start: +stctg %c8,%c8,c8/* enable only monitor class 1 */ +mvhhi c8+6,0x4000 +lctlg %c8,%c8,c8 +mc_nop: +mc 123,0 +mc_monitor_event: +mc 321,1 +j failure +mc_specification: +mc 333,16 +j failure +pgm: +lgrl %r0,program_old_psw+8 /* ilc adjustment */ +llgc %r1,ilc +sgr %r0,%r1 +larl %r1,mc_monitor_event /* dispatch based on old PSW */ +cgrje %r0,%r1,pgm_monitor_event +larl %r1,mc_specification +cgrje %r0,%r1,pgm_specification +j failure +pgm_monitor_event: +chhsi program_interruption_code,0x40/* monitor event? */ +jne failure +chhsi monitor_class,1 /* class from mc_monitor_event? */ +jne failure +cghsi monitor_code,321 /* code from mc_monitor_event? */ +jne failure +j mc_specification /* next test */ +pgm_specification: +chhsi program_interruption_code,6 /* specification exception? */ +jne failure +lpswe success_psw +failure: +lpswe failure_psw +.align 8 +c8: +.quad 0 +success_psw: +.quad 0x2,0xfff /* see is_special_wait_psw() */ +failure_psw: +.quad 0x2,0 /* disabled wait */ -- 2.41.0
[PATCH 06/14] tcg/{i386, s390x}: Add earlyclobber to the op_add2's first output
i386 and s390x implementations of op_add2 require an earlyclobber, which is currently missing. This breaks VCKSM in s390x guests. E.g., on x86_64 the following op: add2_i32 tmp2,tmp3,tmp2,tmp3,tmp3,tmp2 dead: 0 2 3 4 5 pref=none,0x is translated to: addl %ebx, %r12d adcl %r12d, %ebx Introduce a new C_N1_O1_I4 constraint, and make sure that earlyclobber of aliased outputs is honored. Cc: qemu-sta...@nongnu.org Fixes: 82790a870992 ("tcg: Add markup for output requires new register") Signed-off-by: Ilya Leoshkevich --- tcg/i386/tcg-target-con-set.h | 2 +- tcg/i386/tcg-target.c.inc | 2 +- tcg/s390x/tcg-target-con-set.h | 5 ++--- tcg/s390x/tcg-target.c.inc | 4 ++-- tcg/tcg.c | 8 +++- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tcg/i386/tcg-target-con-set.h b/tcg/i386/tcg-target-con-set.h index 91ceb0e1da2..cb4b25263e9 100644 --- a/tcg/i386/tcg-target-con-set.h +++ b/tcg/i386/tcg-target-con-set.h @@ -53,4 +53,4 @@ C_O2_I1(r, r, L) C_O2_I2(a, d, a, r) C_O2_I2(r, r, L, L) C_O2_I3(a, d, 0, 1, r) -C_O2_I4(r, r, 0, 1, re, re) +C_N1_O1_I4(r, r, 0, 1, re, re) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index ab997b5fb39..77482da0709 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -3335,7 +3335,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_add2_i64: case INDEX_op_sub2_i32: case INDEX_op_sub2_i64: -return C_O2_I4(r, r, 0, 1, re, re); +return C_N1_O1_I4(r, r, 0, 1, re, re); case INDEX_op_ctz_i32: case INDEX_op_ctz_i64: diff --git a/tcg/s390x/tcg-target-con-set.h b/tcg/s390x/tcg-target-con-set.h index cbad91b2b56..ce779e8b44a 100644 --- a/tcg/s390x/tcg-target-con-set.h +++ b/tcg/s390x/tcg-target-con-set.h @@ -41,6 +41,5 @@ C_O2_I1(o, m, r) C_O2_I2(o, m, 0, r) C_O2_I2(o, m, r, r) C_O2_I3(o, m, 0, 1, r) -C_O2_I4(r, r, 0, 1, rA, r) -C_O2_I4(r, r, 0, 1, ri, r) -C_O2_I4(r, r, 0, 1, r, r) +C_N1_O1_I4(r, r, 0, 1, ri, r) +C_N1_O1_I4(r, r, 0, 1, rA, r) diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index a878acd8ca6..a94f7908d64 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -3229,11 +3229,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_add2_i32: case INDEX_op_sub2_i32: -return C_O2_I4(r, r, 0, 1, ri, r); +return C_N1_O1_I4(r, r, 0, 1, ri, r); case INDEX_op_add2_i64: case INDEX_op_sub2_i64: -return C_O2_I4(r, r, 0, 1, rA, r); +return C_N1_O1_I4(r, r, 0, 1, rA, r); case INDEX_op_st_vec: return C_O0_I2(v, r); diff --git a/tcg/tcg.c b/tcg/tcg.c index 652e8ea6b93..ddfe9a96cb7 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -648,6 +648,7 @@ static void tcg_out_movext3(TCGContext *s, const TCGMovExtend *i1, #define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2), #define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3), #define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4), +#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4), typedef enum { #include "tcg-target-con-set.h" @@ -668,6 +669,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); #undef C_O2_I2 #undef C_O2_I3 #undef C_O2_I4 +#undef C_N1_O1_I4 /* Put all of the constraint sets into an array, indexed by the enum. */ @@ -687,6 +689,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); #define C_O2_I2(O1, O2, I1, I2) { .args_ct_str = { #O1, #O2, #I1, #I2 } }, #define C_O2_I3(O1, O2, I1, I2, I3) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3 } }, #define C_O2_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3, #I4 } }, +#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { "&" #O1, #O2, #I1, #I2, #I3, #I4 } }, static const TCGTargetOpDef constraint_sets[] = { #include "tcg-target-con-set.h" @@ -706,6 +709,7 @@ static const TCGTargetOpDef constraint_sets[] = { #undef C_O2_I2 #undef C_O2_I3 #undef C_O2_I4 +#undef C_N1_O1_I4 /* Expand the enumerator to be returned from tcg_target_op_def(). */ @@ -725,6 +729,7 @@ static const TCGTargetOpDef constraint_sets[] = { #define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2) #define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3) #define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4) +#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4) #include "tcg-target.c.inc" @@ -4703,7 +4708,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) * dead after the instruction, we must allocate a new * register and move it. */ -if (temp_readonly(ts) || !IS_DEAD_ARG(i)) { +if (temp_readonly(ts) ||
[PATCH 11/14] tests/tcg/s390x: Test ICM
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/icm.S | 32 + 2 files changed, 33 insertions(+) create mode 100644 tests/tcg/s390x/icm.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 062d8e368aa..58684d7da71 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -19,6 +19,7 @@ ASM_TESTS = \ cksm \ clm \ exrl-ssm-early \ +icm \ sam \ lpsw \ lpswe-early \ diff --git a/tests/tcg/s390x/icm.S b/tests/tcg/s390x/icm.S new file mode 100644 index 000..d24d1f52fb8 --- /dev/null +++ b/tests/tcg/s390x/icm.S @@ -0,0 +1,32 @@ +.org 0x8e +program_interruption_code: +.org 0x1d0 /* program new PSW */ +.quad 0,pgm +.org 0x200 /* lowcore padding */ +.globl _start +_start: +lgrl %r0,op1 +icm %r0,10,op2 +cg %r0,exp +jne failure +lgrl %r1,bad_addr +icm %r0,0,0(%r1) +failure: +lpswe failure_psw +pgm: +chhsi program_interruption_code,5 /* addressing exception? */ +jne failure +lpswe success_psw +.align 8 +op1: +.quad 0x1234567887654321 +op2: +.quad 0x0011223344556677 +exp: +.quad 0x1234567800651121 +bad_addr: +.quad 0x +success_psw: +.quad 0x2,0xfff/* see is_special_wait_psw() */ +failure_psw: +.quad 0x2,0/* disabled wait */ -- 2.41.0
[PATCH 05/14] target/s390x: Make MC raise specification exception when class >= 16
MC requires bit positions 8-11 (upper 4 bits of class) to be zeros, otherwise it must raise a specification exception. Cc: qemu-sta...@nongnu.org Fixes: 20d143e2cab8 ("s390x/tcg: Implement MONITOR CALL") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/excp_helper.c | 2 +- target/s390x/tcg/translate.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c index 228aa9f2373..3da337f7c72 100644 --- a/target/s390x/tcg/excp_helper.c +++ b/target/s390x/tcg/excp_helper.c @@ -639,7 +639,7 @@ void monitor_event(CPUS390XState *env, void HELPER(monitor_call)(CPUS390XState *env, uint64_t monitor_code, uint32_t monitor_class) { -g_assert(monitor_class <= 0xff); +g_assert(monitor_class <= 0xf); if (env->cregs[8] & (0x8000 >> monitor_class)) { monitor_event(env, monitor_code, monitor_class, GETPC()); diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 2d7cc8963b4..4b32c2333c2 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -3184,9 +3184,9 @@ static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o) static DisasJumpType op_mc(DisasContext *s, DisasOps *o) { -const uint16_t monitor_class = get_field(s, i2); +const uint8_t monitor_class = get_field(s, i2); -if (monitor_class & 0xff00) { +if (monitor_class & 0xf0) { gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } -- 2.41.0
[PATCH 03/14] target/s390x: Fix CONVERT TO LOGICAL/FIXED with out-of-range inputs
CONVERT TO LOGICAL/FIXED deviate from IEEE 754 in that they raise an inexact exception on out-of-range inputs. float_flag_invalid_cvti aligns nicely with that behavior, so convert it to S390_IEEE_MASK_INEXACT. Cc: qemu-sta...@nongnu.org Fixes: defb0e3157af ("s390x: Implement opcode helpers") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/fpu_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c index 4b7fa58af3e..3d941ed2d28 100644 --- a/target/s390x/tcg/fpu_helper.c +++ b/target/s390x/tcg/fpu_helper.c @@ -52,7 +52,8 @@ uint8_t s390_softfloat_exc_to_ieee(unsigned int exc) s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0; s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0; s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0; -s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0; +s390_exc |= (exc & (float_flag_inexact | float_flag_invalid_cvti)) ? +S390_IEEE_MASK_INEXACT : 0; return s390_exc; } -- 2.41.0
[PATCH 04/14] target/s390x: Fix ICM with M3=0
When the mask is zero, access exceptions should still be recognized for 1 byte at the second-operand address. CC should be set to 0. Cc: qemu-sta...@nongnu.org Fixes: e023e832d0ac ("s390x: translate engine for s390x CPU") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/translate.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 2f61e879878..2d7cc8963b4 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -2516,6 +2516,12 @@ static DisasJumpType op_icm(DisasContext *s, DisasOps *o) len = 8; goto one_insert; +case 0: +/* Recognize access exceptions for the first byte. */ +tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); +gen_op_movi_cc(s, 0); +return DISAS_NEXT; + one_insert: pos = base + ctz32(m3) * 8; tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len); -- 2.41.0
[PATCH 14/14] tests/tcg/s390x: Test VCKSM
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/vcksm.c | 31 +++ tests/tcg/s390x/vx.h| 2 ++ 3 files changed, 34 insertions(+) create mode 100644 tests/tcg/s390x/vcksm.c diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 71bf39b78d3..1fc98099070 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -58,6 +58,7 @@ TESTS += $(PGM_SPECIFICATION_TESTS) Z13_TESTS=vistr Z13_TESTS+=lcbb Z13_TESTS+=locfhr +Z13_TESTS+=vcksm $(Z13_TESTS): CFLAGS+=-march=z13 -O2 TESTS+=$(Z13_TESTS) diff --git a/tests/tcg/s390x/vcksm.c b/tests/tcg/s390x/vcksm.c new file mode 100644 index 000..452daaae6ce --- /dev/null +++ b/tests/tcg/s390x/vcksm.c @@ -0,0 +1,31 @@ +/* + * Test the VCKSM instruction. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include +#include +#include "vx.h" + +int main(void) +{ +S390Vector v1; +S390Vector v2 = { +.d[0] = 0xb2261c8140edce49ULL, +.d[1] = 0x387bf5a433af39d1ULL, +}; +S390Vector v3 = { +.d[0] = 0x73b03d2c7f9e654eULL, +.d[1] = 0x23d74e51fb479877ULL, +}; +S390Vector exp = {.d[0] = 0xdedd7f8eULL, .d[1] = 0ULL}; + +asm volatile("vcksm %[v1],%[v2],%[v3]" + : [v1] "=v" (v1.v) + : [v2] "v" (v2.v) + , [v3] "v" (v3.v)); +assert(memcmp(&v1, &exp, sizeof(v1)) == 0); + +return EXIT_SUCCESS; +} diff --git a/tests/tcg/s390x/vx.h b/tests/tcg/s390x/vx.h index 02e7fd518a8..00701dbe35f 100644 --- a/tests/tcg/s390x/vx.h +++ b/tests/tcg/s390x/vx.h @@ -1,6 +1,8 @@ #ifndef QEMU_TESTS_S390X_VX_H #define QEMU_TESTS_S390X_VX_H +#include + typedef union S390Vector { uint64_t d[2]; /* doubleword */ uint32_t w[4]; /* word */ -- 2.41.0
[PATCH 10/14] tests/tcg/s390x: Test CLM
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/clm.S | 29 + 2 files changed, 30 insertions(+) create mode 100644 tests/tcg/s390x/clm.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index e813e318db9..062d8e368aa 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -17,6 +17,7 @@ LDFLAGS=-nostdlib -static ASM_TESTS = \ bal \ cksm \ +clm \ exrl-ssm-early \ sam \ lpsw \ diff --git a/tests/tcg/s390x/clm.S b/tests/tcg/s390x/clm.S new file mode 100644 index 000..17156a81f2a --- /dev/null +++ b/tests/tcg/s390x/clm.S @@ -0,0 +1,29 @@ +.org 0x8e +program_interruption_code: +.org 0x1d0 /* program new PSW */ +.quad 0,pgm +.org 0x200 /* lowcore padding */ +.globl _start +_start: +lgrl %r0,op1 +clm %r0,6,op2 +jle failure +lgrl %r1,bad_addr +clm %r0,0,0(%r1) +failure: +lpswe failure_psw +pgm: +chhsi program_interruption_code,5 /* addressing exception? */ +jne failure +lpswe success_psw +.align 8 +op1: +.quad 0x1234567887654321 +op2: +.quad 0x3456789abcdef012 +bad_addr: +.quad 0x +success_psw: +.quad 0x2,0xfff/* see is_special_wait_psw() */ +failure_psw: +.quad 0x2,0/* disabled wait */ -- 2.41.0
[PATCH 02/14] target/s390x: Fix CLM with M3=0
When the mask is zero, access exceptions should still be recognized for 1 byte at the second-operand address. CC should be set to 0. Cc: qemu-sta...@nongnu.org Fixes: defb0e3157af ("s390x: Implement opcode helpers") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/mem_helper.c | 5 + 1 file changed, 5 insertions(+) diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index f417fb1183c..d6dc8b32620 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -667,6 +667,11 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask, HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%" PRIx64 "\n", __func__, r1, mask, addr); +if (!mask) { +/* Recognize access exceptions for the first byte */ +cpu_ldub_data_ra(env, addr, ra); +} + while (mask) { if (mask & 8) { uint8_t d = cpu_ldub_data_ra(env, addr, ra); -- 2.41.0
[PATCH 01/14] target/s390x: Make CKSM raise an exception if R2 is odd
R2 designates an even-odd register pair; the instruction should raise a specification exception when R2 is not even. Cc: qemu-sta...@nongnu.org Fixes: e023e832d0ac ("s390x: translate engine for s390x CPU") Signed-off-by: Ilya Leoshkevich --- target/s390x/tcg/translate.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 6661b27efa4..2f61e879878 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -1991,11 +1991,18 @@ static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o) static DisasJumpType op_cksm(DisasContext *s, DisasOps *o) { int r2 = get_field(s, r2); -TCGv_i128 pair = tcg_temp_new_i128(); -TCGv_i64 len = tcg_temp_new_i64(); +TCGv_i128 pair; +TCGv_i64 len; + +if (r2 & 1) { +gen_program_exception(s, PGM_SPECIFICATION); +return DISAS_NORETURN; +} +pair = tcg_temp_new_i128(); gen_helper_cksm(pair, cpu_env, o->in1, o->in2, regs[r2 + 1]); set_cc_static(s); +len = tcg_temp_new_i64(); tcg_gen_extr_i128_i64(o->out, len, pair); tcg_gen_add_i64(regs[r2], regs[r2], len); -- 2.41.0
Re: [RFC PATCH 10/17] misc/i2c_mctp_cxl: Initial device emulation
On Mon, Jul 17, 2023 at 06:16:39PM +0100, Jonathan Cameron wrote: > @@ -397,8 +401,9 @@ struct CXLType3Dev { > AddressSpace hostpmem_as; > CXLComponentState cxl_cstate; > CXLDeviceState cxl_dstate; > -CXLCCI cci; > - > +CXLCCI cci; /* Primary PCI mailbox CCI */ > +CXLCCI oob_mctp_cci; /* Initialized only if targetted */ > + I've been humming and hawing over this on the MHD stuff because I wanted to figure out how to "add a CCI command" to a type-3 device without either having a billion definitions for CCI command sets - or doing something like this. I don't hate this design pattern, I just want to ask whether your intent is to end up with CXLType3Dev hosting many CXLCCI's based on what wrapper types you have. Example: a type-3 device with mctp pass through and the MHD command set CXLType3Dev { ... CXLCCI cci; CXLCCI oob_mctp_cci; CXLCCI mhd_cci; ... } Instantiate: -device cxl-type3,bus=swport0,memdev=cxl-mem1,id=cxl-pmem1,lsa=cxl-lsa1,sn=3 -device i2c_mctp_cxl,bus=aspeed.i2c.bus.0,address=5,target=cxl-pmem1 -device cxl-mhd,target=cxl-pmem1,...whatever else... where the MHD code is contained within its own type/file, and the type3 device hosts the CCI for it. Similar to how you've implemented the MTCP stuff here. The reason I ask is because certain CCI's don't necessarily get associated with "a bus" so much as "a device". the MHD example - it's still part of "the device", but it's optional. So does it make sense to create this wrapper without a bus association, or to just pile it on top CXLType3Dev and have to duplicate the code across any other multi-headed devices that folks may conjur up? ~Gregory
[PATCH 13/14] tests/tcg/s390x: Test STPQ
Add a small test to prevent regressions. Signed-off-by: Ilya Leoshkevich --- tests/tcg/s390x/Makefile.softmmu-target | 1 + tests/tcg/s390x/stpq.S | 20 2 files changed, 21 insertions(+) create mode 100644 tests/tcg/s390x/stpq.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 145e0bfde16..76345b6e643 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -27,6 +27,7 @@ ASM_TESTS = \ mc \ ssm-early \ stosm-early \ +stpq \ unaligned-lowcore include $(S390X_SRC)/pgm-specification.mak diff --git a/tests/tcg/s390x/stpq.S b/tests/tcg/s390x/stpq.S new file mode 100644 index 000..687a52eafa7 --- /dev/null +++ b/tests/tcg/s390x/stpq.S @@ -0,0 +1,20 @@ +.org 0x200 /* lowcore padding */ +.globl _start +_start: +lgrl %r0,value +lgrl %r1,value+8 +stpq %r0,stored_value +clc stored_value(16),value +jne failure +lpswe success_psw +failure: +lpswe failure_psw +.align 16 +value: +.quad 0x1234567887654321, 0x8765432112345678 +stored_value: +.quad 0, 0 +success_psw: +.quad 0x2,0xfff/* see is_special_wait_psw() */ +failure_psw: +.quad 0x2,0/* disabled wait */ -- 2.41.0
Re: [PATCH v2] plugins: Set final instruction count in plugin_gen_tb_end
Matt Borgerson writes: > Thanks Alex! > > > On Mon, Jul 17, 2023 at 8:34 AM Alex Bennée wrote: >> >> >> Alex Bennée writes: >> >> > Matt Borgerson writes: >> > >> >> Translation logic may partially decode an instruction, then abort and >> >> remove the instruction from the TB. This can happen for example when an >> >> instruction spans two pages. In this case, plugins may get an incorrect >> >> result when calling qemu_plugin_tb_n_insns to query for the number of >> >> instructions in the TB. This patch updates plugin_gen_tb_end to set the >> >> final instruction count. >> > >> > For some reason this fails to apply cleanly: >> > >> > git am >> > ./v2_20230714_contact_plugins_set_final_instruction_count_in_plugin_gen_tb_end.mbx >> > Applying: plugins: Set final instruction count in plugin_gen_tb_end >> > error: corrupt patch at line 31 >> > Patch failed at 0001 plugins: Set final instruction count in >> > plugin_gen_tb_end >> >> I think some newlines crept in, I was able to fix. Queued to >> for-8.1/misc-fixes with the assert added. Hmm so I ran into an issue: ./qemu-sh4 -plugin tests/plugin/libbb.so -d plugin ./tests/tcg/sh4-linux-user/testthread ERROR:../../accel/tcg/plugin-gen.c:874:plugin_gen_tb_end: assertion failed: (num_insns <= ptb->n) Bail out! ERROR:../../accel/tcg/plugin-gen.c:874:plugin_gen_tb_end: assertion failed: (num_insns <= ptb->n) qemu: uncaught target signal 11 (Segmentation fault) - core dumped bb's: 9202, insns: 42264 fish: Job 1, './qemu-sh4 -plugin tests/plugin…' terminated by signal SIGSEGV (Address boundary error) Further investigation shows that gUSA sequences can cause the number of instructions to run ahead, which also makes the setting of the ptb->n = num_insns unsafe, running ahead of the number of instructions signalled by plugin_gen_insn_start/plugin_gen_insn_end. Thread 1 hit Hardware watchpoint 5: *(int *) 0x7ffd410a2904 Old value = 4 New value = 1 0x55f148c00ea8 in decode_gusa (ctx=0x7ffd410a28f0, env=0x55f14a4106e8) at ../../target/sh4/translate.c:2167 2167ctx->base.num_insns += max_insns - 1; (rr) p max_insns $6 = 4 (rr) p max_insns -1 $7 = 3 (rr) p ctx->base.num_insns $8 = 1 So I think we have to drop this for now until we can either fix decode_gusa or find something else. Richard, Any ideas? -- Alex Bennée Virtualisation Tech Lead @ Linaro
Re: PING: [PATCH v4 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
On 2023-07-19 오전 3:56, Stefan Hajnoczi wrote: On Tue, Jul 11, 2023 at 07:31:02PM +0900, Jeuk Kim wrote: Hi, Any more reviews...? Dear Stefan If you don't mind, Could you give it "reviewed-by"? And is there anything else I should do...? Sorry for the late reply. I was on vacation and am working my way through pending code review and bug reports. I have started reviewing this series and should be finish on Wednesday or Thursday. Stefan Thank you for your review. I have seen your comments on PATCH v4. I'll send you a patch v5 as soon as I fix the things you commented on. Thanks again. Jeuk
Re: [PATCH qemu 2/2] dump: Only use the makedumpfile flattened format when necessary
Marc-André Lureau writes: > Hi > > On Mon, Jul 17, 2023 at 8:45 PM Stephen Brennan < > stephen.s.bren...@oracle.com> wrote: > >> The flattened format is used by makedumpfile only when it is outputting >> a vmcore to a file which is not seekable. The flattened format functions >> essentially as a set of instructions of the form "seek to the given >> offset, then write the given bytes out". >> >> The flattened format can be reconstructed using makedumpfile -R, or >> makedumpfile-R.pl, but it is a slow process beacuse it requires copying >> the entire vmcore. The flattened format can also be directly read by >> crash, but still, it requires a lengthy reassembly phase. >> >> To sum up, the flattened format is not an ideal one: it should only be >> used on files which are actually not seekable. This is the exact >> strategy which makedumpfile uses, as seen in the implementation of >> "write_buffer()" in makedumpfile [1]. >> >> So, update the "dump-guest-memory" monitor command implementation so >> that it will directly do the seeks and writes, in the same strategy as >> makedumpfile. However, if the file is not seekable, then we can fall >> back to the flattened format. >> >> [1]: >> https://github.com/makedumpfile/makedumpfile/blob/f23bb943568188a2746dbf9b6692668f5a2ac3b6/makedumpfile.c#L5008-L5040 >> >> Signed-off-by: Stephen Brennan >> > > Reviewed-by: Marc-André Lureau > Tested-by: Marc-André Lureau > > I am a bit reluctant to change the dump format by default. But since the > flatten format is more "complicated" than the "normal" format, perhaps we > can assume all users will handle it. > > The change is probably late for 8.1 though.. Thank you for your review and testing! I totally understand the concern about making the change by default. I do believe that nobody should notice too much because the normal format should be easier to work with, and more broadly compatible. I don't know of any tool which deals with the flattened format that can't handle the normal format, except for "makedumpfile -R" itself. If it's a blocker, I can go ahead and add a new flag to the command to enable the behavior. However there are a few good justifications not to add a new flag. I think it's going to be difficult to explain the difference between the two formats in documentation, as the implementation of the formats is a bit "into the weeds". The libvirt API also specifies each format separately (kdump-zlib, kdump-lzo, kdump-snappy) and so adding several new options there would be unfortunate for end-users as well. At the end of the day, it's your judgment call, and I'll implement it how you prefer. Thanks, Stephen >> dump/dump.c | 30 +- >> include/sysemu/dump.h | 1 + >> 2 files changed, 26 insertions(+), 5 deletions(-) >> >> diff --git a/dump/dump.c b/dump/dump.c >> index 2708ddc135..384d275e39 100644 >> --- a/dump/dump.c >> +++ b/dump/dump.c >> @@ -813,6 +813,13 @@ static int write_start_flat_header(DumpState *s) >> { >> MakedumpfileHeader *mh; >> int ret = 0; >> +loff_t offset = lseek(s->fd, 0, SEEK_CUR); >> + >> +/* If the file is seekable, don't output flattened header */ >> +if (offset == 0) { >> +s->seekable = true; >> +return 0; >> +} >> >> QEMU_BUILD_BUG_ON(sizeof *mh > MAX_SIZE_MDF_HEADER); >> mh = g_malloc0(MAX_SIZE_MDF_HEADER); >> @@ -837,6 +844,10 @@ static int write_end_flat_header(DumpState *s) >> { >> MakedumpfileDataHeader mdh; >> >> +if (s->seekable) { >> +return 0; >> +} >> + >> mdh.offset = END_FLAG_FLAT_HEADER; >> mdh.buf_size = END_FLAG_FLAT_HEADER; >> >> @@ -853,13 +864,21 @@ static int write_buffer(DumpState *s, off_t offset, >> const void *buf, size_t size >> { >> size_t written_size; >> MakedumpfileDataHeader mdh; >> +loff_t seek_loc; >> >> -mdh.offset = cpu_to_be64(offset); >> -mdh.buf_size = cpu_to_be64(size); >> +if (s->seekable) { >> +seek_loc = lseek(s->fd, offset, SEEK_SET); >> +if (seek_loc == (off_t) -1) { >> +return -1; >> +} >> +} else { >> +mdh.offset = cpu_to_be64(offset); >> +mdh.buf_size = cpu_to_be64(size); >> >> -written_size = qemu_write_full(s->fd, &mdh, sizeof(mdh)); >> -if (written_size != sizeof(mdh)) { >> -return -1; >> +written_size = qemu_write_full(s->fd, &mdh, sizeof(mdh)); >> +if (written_size != sizeof(mdh)) { >> +return -1; >> +} >> } >> >> written_size = qemu_write_full(s->fd, buf, size); >> @@ -1786,6 +1805,7 @@ static void dump_init(DumpState *s, int fd, bool >> has_format, >> s->has_format = has_format; >> s->format = format; >> s->written_size = 0; >> +s->seekable = false; >> >> /* kdump-compressed is conflict with paging and filter */ >> if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) { >> diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
[PATCH 2/3] ppc/pegasos2: Fix reg property of ROM BARs
The register offset of the ROM BAR is 0x30 not 0x28. This fixes the reg property entry of the ROM region in the device tree. Signed-off-by: BALATON Zoltan --- hw/ppc/pegasos2.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 4a2ab35f19..8ed13a42a2 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -766,7 +766,11 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) if (!d->io_regions[i].size) { continue; } -cells[j] = cpu_to_be32(d->devfn << 8 | (PCI_BASE_ADDRESS_0 + i * 4)); +cells[j] = PCI_BASE_ADDRESS_0 + i * 4; +if (cells[j] == 0x28) { +cells[j] = 0x30; +} +cells[j] = cpu_to_be32(d->devfn << 8 | cells[j]); if (d->io_regions[i].type & PCI_BASE_ADDRESS_SPACE_IO) { cells[j] |= cpu_to_be32(1 << 24); } else { -- 2.30.9
[PATCH 3/3] ppc/pegasos2: Fix naming of device tree nodes
The board firmware names devices by their class so match that for common devices. Also make sure the /rtas node has a name. This is needed because VOF otherwise does not include it in results got by nextprop which is how AmigaOS queries it and fails if no name property is found. Signed-off-by: BALATON Zoltan --- hw/ppc/pegasos2.c | 8 1 file changed, 8 insertions(+) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 8ed13a42a2..6475acfbed 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -739,6 +739,13 @@ static void add_pci_device(PCIBus *bus, PCIDevice *d, void *opaque) pci_get_word(&d->config[PCI_VENDOR_ID]), pci_get_word(&d->config[PCI_DEVICE_ID])); +if (pci_get_word(&d->config[PCI_CLASS_DEVICE]) == +PCI_CLASS_NETWORK_ETHERNET) { +name = "ethernet"; +} else if (pci_get_word(&d->config[PCI_CLASS_DEVICE]) >> 8 == +PCI_BASE_CLASS_DISPLAY) { +name = "display"; +} for (i = 0; device_map[i].id; i++) { if (!strcmp(pn, device_map[i].id)) { name = device_map[i].name; @@ -929,6 +936,7 @@ static void *build_fdt(MachineState *machine, int *fdt_size) qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-display-device", 0); qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size", 20); qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-version", 1); +qemu_fdt_setprop_string(fdt, "/rtas", "name", "rtas"); /* cpus */ qemu_fdt_add_subnode(fdt, "/cpus"); -- 2.30.9
[PATCH 0/3] pegasos2 fixes for 8.1
These are some small fixes when using pegasos2 with the QEMU built in VOF instead of the non-free board firmware that fix bugs in the generated device tree and matches the board firmware in the reset state of on-board USB devices. This fixes booting AmigaOS with VOF and only touches parts that are used with VOF only so I'd like these to be merged for 8.1. Regards, BALATON Zoltan (3): ppc/pegasos2: Fix reset state of USB functions ppc/pegasos2: Fix reg property of ROM BARs ppc/pegasos2: Fix naming of device tree nodes hw/ppc/pegasos2.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) -- 2.30.9
[PATCH 1/3] ppc/pegasos2: Fix reset state of USB functions
The original non-free board firmware sets the command register of the USB functions to 7 and some guests rely on this for working USB. Match what the board firmware does when using VOF instead. Signed-off-by: BALATON Zoltan --- hw/ppc/pegasos2.c | 4 1 file changed, 4 insertions(+) diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index 4447bbe8ec..4a2ab35f19 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -324,9 +324,13 @@ static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason) pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 2) << 8) | PCI_INTERRUPT_LINE, 2, 0x409); +pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 2) << 8) | + PCI_COMMAND, 2, 0x7); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 3) << 8) | PCI_INTERRUPT_LINE, 2, 0x409); +pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 3) << 8) | + PCI_COMMAND, 2, 0x7); pegasos2_pci_config_write(pm, 1, (PCI_DEVFN(12, 4) << 8) | PCI_INTERRUPT_LINE, 2, 0x9); -- 2.30.9
Re: [PATCH v8 01/15] target/riscv: Refactor some of the generic vector functionality
On Wed, Jul 12, 2023 at 2:59 AM Max Chou wrote: > > From: Kiran Ostrolenk > > Take some functions/macros out of `vector_helper` and put them in a new > module called `vector_internals`. This ensures they can be used by both > vector and vector-crypto helpers (latter implemented in proceeding > commits). > > Signed-off-by: Kiran Ostrolenk > Reviewed-by: Weiwei Li > Signed-off-by: Max Chou Acked-by: Alistair Francis Alistair > --- > target/riscv/meson.build| 1 + > target/riscv/vector_helper.c| 201 +--- > target/riscv/vector_internals.c | 81 + > target/riscv/vector_internals.h | 182 + > 4 files changed, 265 insertions(+), 200 deletions(-) > create mode 100644 target/riscv/vector_internals.c > create mode 100644 target/riscv/vector_internals.h > > diff --git a/target/riscv/meson.build b/target/riscv/meson.build > index 7f56c5f88d4..c3801ee5e04 100644 > --- a/target/riscv/meson.build > +++ b/target/riscv/meson.build > @@ -16,6 +16,7 @@ riscv_ss.add(files( >'gdbstub.c', >'op_helper.c', >'vector_helper.c', > + 'vector_internals.c', >'bitmanip_helper.c', >'translate.c', >'m128_helper.c', > diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c > index 71bb9b4457b..6434fd2f7e8 100644 > --- a/target/riscv/vector_helper.c > +++ b/target/riscv/vector_helper.c > @@ -26,6 +26,7 @@ > #include "fpu/softfloat.h" > #include "tcg/tcg-gvec-desc.h" > #include "internals.h" > +#include "vector_internals.h" > #include > > target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, > @@ -72,68 +73,6 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, > target_ulong s1, > return vl; > } > > -/* > - * Note that vector data is stored in host-endian 64-bit chunks, > - * so addressing units smaller than that needs a host-endian fixup. > - */ > -#if HOST_BIG_ENDIAN > -#define H1(x) ((x) ^ 7) > -#define H1_2(x) ((x) ^ 6) > -#define H1_4(x) ((x) ^ 4) > -#define H2(x) ((x) ^ 3) > -#define H4(x) ((x) ^ 1) > -#define H8(x) ((x)) > -#else > -#define H1(x) (x) > -#define H1_2(x) (x) > -#define H1_4(x) (x) > -#define H2(x) (x) > -#define H4(x) (x) > -#define H8(x) (x) > -#endif > - > -static inline uint32_t vext_nf(uint32_t desc) > -{ > -return FIELD_EX32(simd_data(desc), VDATA, NF); > -} > - > -static inline uint32_t vext_vm(uint32_t desc) > -{ > -return FIELD_EX32(simd_data(desc), VDATA, VM); > -} > - > -/* > - * Encode LMUL to lmul as following: > - * LMULvlmullmul > - * 1 000 0 > - * 2 001 1 > - * 4 010 2 > - * 8 011 3 > - * - 100 - > - * 1/8 101 -3 > - * 1/4 110 -2 > - * 1/2 111 -1 > - */ > -static inline int32_t vext_lmul(uint32_t desc) > -{ > -return sextract32(FIELD_EX32(simd_data(desc), VDATA, LMUL), 0, 3); > -} > - > -static inline uint32_t vext_vta(uint32_t desc) > -{ > -return FIELD_EX32(simd_data(desc), VDATA, VTA); > -} > - > -static inline uint32_t vext_vma(uint32_t desc) > -{ > -return FIELD_EX32(simd_data(desc), VDATA, VMA); > -} > - > -static inline uint32_t vext_vta_all_1s(uint32_t desc) > -{ > -return FIELD_EX32(simd_data(desc), VDATA, VTA_ALL_1S); > -} > - > /* > * Get the maximum number of elements can be operated. > * > @@ -152,21 +91,6 @@ static inline uint32_t vext_max_elems(uint32_t desc, > uint32_t log2_esz) > return scale < 0 ? vlenb >> -scale : vlenb << scale; > } > > -/* > - * Get number of total elements, including prestart, body and tail elements. > - * Note that when LMUL < 1, the tail includes the elements past VLMAX that > - * are held in the same vector register. > - */ > -static inline uint32_t vext_get_total_elems(CPURISCVState *env, uint32_t > desc, > -uint32_t esz) > -{ > -uint32_t vlenb = simd_maxsz(desc); > -uint32_t sew = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW); > -int8_t emul = ctzl(esz) - ctzl(sew) + vext_lmul(desc) < 0 ? 0 : > - ctzl(esz) - ctzl(sew) + vext_lmul(desc); > -return (vlenb << emul) / esz; > -} > - > static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr) > { > return (addr & ~env->cur_pmmask) | env->cur_pmbase; > @@ -199,20 +123,6 @@ static void probe_pages(CPURISCVState *env, target_ulong > addr, > } > } > > -/* set agnostic elements to 1s */ > -static void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt, > - uint32_t tot) > -{ > -if (is_agnostic == 0) { > -/* policy undisturbed */ > -return; > -} > -if (tot - cnt == 0) { > -return; > -} > -memset(base + cnt, -1, tot - cnt); > -} > - > static inline void vext_set_elem_mask(void *v0, int index, >uint8_t value) > { > @@ -222,18 +132,6 @@ static inline
Re: [PATCH v2 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c
On Tue, Jul 4, 2023 at 4:34 AM Philippe Mathieu-Daudé wrote: > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/cpu_helper.c| 84 --- > target/riscv/tcg/cpu.c | 98 > target/riscv/tcg/meson.build | 1 + > 3 files changed, 99 insertions(+), 84 deletions(-) > create mode 100644 target/riscv/tcg/cpu.c > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 597c47bc56..6f8778c6d3 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -64,90 +64,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) > #endif > } > > -void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, > - uint64_t *cs_base, uint32_t *pflags) > -{ > -CPUState *cs = env_cpu(env); > -RISCVCPU *cpu = RISCV_CPU(cs); > -RISCVExtStatus fs, vs; > -uint32_t flags = 0; > - > -*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc; > -*cs_base = 0; > - > -if (cpu->cfg.ext_zve32f) { > -/* > - * If env->vl equals to VLMAX, we can use generic vector operation > - * expanders (GVEC) to accerlate the vector operations. > - * However, as LMUL could be a fractional number. The maximum > - * vector size can be operated might be less than 8 bytes, > - * which is not supported by GVEC. So we set vl_eq_vlmax flag to true > - * only when maxsz >= 8 bytes. > - */ > -uint32_t vlmax = vext_get_vlmax(cpu, env->vtype); > -uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW); > -uint32_t maxsz = vlmax << sew; > -bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) && > - (maxsz >= 8); > -flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill); > -flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew); > -flags = FIELD_DP32(flags, TB_FLAGS, LMUL, > - FIELD_EX64(env->vtype, VTYPE, VLMUL)); > -flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); > -flags = FIELD_DP32(flags, TB_FLAGS, VTA, > - FIELD_EX64(env->vtype, VTYPE, VTA)); > -flags = FIELD_DP32(flags, TB_FLAGS, VMA, > - FIELD_EX64(env->vtype, VTYPE, VMA)); > -flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == > 0); > -} else { > -flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); > -} > - > -#ifdef CONFIG_USER_ONLY > -fs = EXT_STATUS_DIRTY; > -vs = EXT_STATUS_DIRTY; > -#else > -flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv); > - > -flags |= cpu_mmu_index(env, 0); > -fs = get_field(env->mstatus, MSTATUS_FS); > -vs = get_field(env->mstatus, MSTATUS_VS); > - > -if (env->virt_enabled) { > -flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1); > -/* > - * Merge DISABLED and !DIRTY states using MIN. > - * We will set both fields when dirtying. > - */ > -fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS)); > -vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS)); > -} > - > -/* With Zfinx, floating point is enabled/disabled by Smstateen. */ > -if (!riscv_has_ext(env, RVF)) { > -fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE) > - ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED; > -} > - > -if (cpu->cfg.debug && !icount_enabled()) { > -flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled); > -} > -#endif > - > -flags = FIELD_DP32(flags, TB_FLAGS, FS, fs); > -flags = FIELD_DP32(flags, TB_FLAGS, VS, vs); > -flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl); > -flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env)); > -if (env->cur_pmmask != 0) { > -flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1); > -} > -if (env->cur_pmbase != 0) { > -flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1); > -} > - > -*pflags = flags; > -} > - > void riscv_cpu_update_mask(CPURISCVState *env) > { > target_ulong mask = 0, base = 0; > diff --git a/target/riscv/tcg/cpu.c b/target/riscv/tcg/cpu.c > new file mode 100644 > index 00..2ae6919b80 > --- /dev/null > +++ b/target/riscv/tcg/cpu.c > @@ -0,0 +1,98 @@ > +/* > + * RISC-V CPU helpers (TCG specific) > + * > + * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu > + * Copyright (c) 2017-2018 SiFive, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "cpu.h" > +#ifndef CONFIG_USER_ONLY > +#include "sysemu/cpu-timers.h" > +#endif > + > +void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, > + uint64_t *cs_base, uint32_t *pflags) > +{ > +CPUState *cs = env_cpu(env); > +RISCVCPU *cpu = RISCV_CPU(cs); > +RISCVExtStatus
Re: [PATCH v3 07/16] target/riscv: Move TCG-specific files to target/riscv/tcg/
On Tue, Jul 11, 2023 at 10:21 PM Philippe Mathieu-Daudé wrote: > > Move TCG-specific files to the a new 'tcg' sub-directory. Add > stubs for riscv_cpu_[get/set]_fflags and riscv_raise_exception(). > Adapt meson rules. > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/{ => tcg}/XVentanaCondOps.decode | 0 > target/riscv/{ => tcg}/insn16.decode | 0 > target/riscv/{ => tcg}/insn32.decode | 0 > target/riscv/{ => tcg}/xthead.decode | 0 > target/riscv/{ => tcg}/bitmanip_helper.c | 0 > target/riscv/{ => tcg}/crypto_helper.c| 0 > target/riscv/{ => tcg}/fpu_helper.c | 0 > target/riscv/{ => tcg}/m128_helper.c | 0 > target/riscv/{ => tcg}/op_helper.c| 0 > target/riscv/tcg/tcg-stub.c | 25 +++ > target/riscv/{ => tcg}/translate.c| 0 > target/riscv/{ => tcg}/vector_helper.c| 0 > target/riscv/{ => tcg}/zce_helper.c | 0 > target/riscv/meson.build | 18 + > target/riscv/tcg/meson.build | 19 ++ > 15 files changed, 45 insertions(+), 17 deletions(-) > rename target/riscv/{ => tcg}/XVentanaCondOps.decode (100%) > rename target/riscv/{ => tcg}/insn16.decode (100%) > rename target/riscv/{ => tcg}/insn32.decode (100%) > rename target/riscv/{ => tcg}/xthead.decode (100%) > rename target/riscv/{ => tcg}/bitmanip_helper.c (100%) > rename target/riscv/{ => tcg}/crypto_helper.c (100%) > rename target/riscv/{ => tcg}/fpu_helper.c (100%) > rename target/riscv/{ => tcg}/m128_helper.c (100%) > rename target/riscv/{ => tcg}/op_helper.c (100%) > create mode 100644 target/riscv/tcg/tcg-stub.c > rename target/riscv/{ => tcg}/translate.c (100%) > rename target/riscv/{ => tcg}/vector_helper.c (100%) > rename target/riscv/{ => tcg}/zce_helper.c (100%) > create mode 100644 target/riscv/tcg/meson.build > > diff --git a/target/riscv/XVentanaCondOps.decode > b/target/riscv/tcg/XVentanaCondOps.decode > similarity index 100% > rename from target/riscv/XVentanaCondOps.decode > rename to target/riscv/tcg/XVentanaCondOps.decode > diff --git a/target/riscv/insn16.decode b/target/riscv/tcg/insn16.decode > similarity index 100% > rename from target/riscv/insn16.decode > rename to target/riscv/tcg/insn16.decode > diff --git a/target/riscv/insn32.decode b/target/riscv/tcg/insn32.decode > similarity index 100% > rename from target/riscv/insn32.decode > rename to target/riscv/tcg/insn32.decode > diff --git a/target/riscv/xthead.decode b/target/riscv/tcg/xthead.decode > similarity index 100% > rename from target/riscv/xthead.decode > rename to target/riscv/tcg/xthead.decode > diff --git a/target/riscv/bitmanip_helper.c > b/target/riscv/tcg/bitmanip_helper.c > similarity index 100% > rename from target/riscv/bitmanip_helper.c > rename to target/riscv/tcg/bitmanip_helper.c > diff --git a/target/riscv/crypto_helper.c b/target/riscv/tcg/crypto_helper.c > similarity index 100% > rename from target/riscv/crypto_helper.c > rename to target/riscv/tcg/crypto_helper.c > diff --git a/target/riscv/fpu_helper.c b/target/riscv/tcg/fpu_helper.c > similarity index 100% > rename from target/riscv/fpu_helper.c > rename to target/riscv/tcg/fpu_helper.c > diff --git a/target/riscv/m128_helper.c b/target/riscv/tcg/m128_helper.c > similarity index 100% > rename from target/riscv/m128_helper.c > rename to target/riscv/tcg/m128_helper.c > diff --git a/target/riscv/op_helper.c b/target/riscv/tcg/op_helper.c > similarity index 100% > rename from target/riscv/op_helper.c > rename to target/riscv/tcg/op_helper.c > diff --git a/target/riscv/tcg/tcg-stub.c b/target/riscv/tcg/tcg-stub.c > new file mode 100644 > index 00..dfe42ae2ac > --- /dev/null > +++ b/target/riscv/tcg/tcg-stub.c > @@ -0,0 +1,25 @@ > +/* > + * QEMU RISC-V TCG stubs > + * > + * Copyright (c) 2023 Linaro > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#include "qemu/osdep.h" > +#include "cpu.h" > + > +target_ulong riscv_cpu_get_fflags(CPURISCVState *env) > +{ > +g_assert_not_reached(); > +} > + > +void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong) > +{ > +g_assert_not_reached(); > +} > + > +G_NORETURN void riscv_raise_exception(CPURISCVState *env, > + uint32_t exception, uintptr_t pc) > +{ > +g_assert_not_reached(); > +} > diff --git a/target/riscv/translate.c b/target/riscv/tcg/translate.c > similarity index 100% > rename from target/riscv/translate.c > rename to target/riscv/tcg/translate.c > diff --git a/target/riscv/vector_helper.c b/target/riscv/tcg/vector_helper.c > similarity index 100% > rename from target/riscv/vector_helper.c > rename to target/riscv/tcg/vector_helper.c > diff --git a/target/riscv/zce_helper.c b/target/riscv/tcg/zce_helper.c > similarity index 100% > rename from target/riscv/zce_helper.c > rename to target/riscv/tcg/zce_helper.c
Re: [PATCH v3 08/16] target/riscv: Move TCG-specific cpu_get_tb_cpu_state() to tcg/cpu.c
On Tue, Jul 11, 2023 at 10:18 PM Philippe Mathieu-Daudé wrote: > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/cpu_helper.c| 84 --- > target/riscv/tcg/cpu.c | 98 > target/riscv/tcg/meson.build | 1 + > 3 files changed, 99 insertions(+), 84 deletions(-) > create mode 100644 target/riscv/tcg/cpu.c > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 597c47bc56..6f8778c6d3 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -64,90 +64,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) > #endif > } > > -void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, > - uint64_t *cs_base, uint32_t *pflags) > -{ > -CPUState *cs = env_cpu(env); > -RISCVCPU *cpu = RISCV_CPU(cs); > -RISCVExtStatus fs, vs; > -uint32_t flags = 0; > - > -*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc; > -*cs_base = 0; > - > -if (cpu->cfg.ext_zve32f) { > -/* > - * If env->vl equals to VLMAX, we can use generic vector operation > - * expanders (GVEC) to accerlate the vector operations. > - * However, as LMUL could be a fractional number. The maximum > - * vector size can be operated might be less than 8 bytes, > - * which is not supported by GVEC. So we set vl_eq_vlmax flag to true > - * only when maxsz >= 8 bytes. > - */ > -uint32_t vlmax = vext_get_vlmax(cpu, env->vtype); > -uint32_t sew = FIELD_EX64(env->vtype, VTYPE, VSEW); > -uint32_t maxsz = vlmax << sew; > -bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) && > - (maxsz >= 8); > -flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill); > -flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew); > -flags = FIELD_DP32(flags, TB_FLAGS, LMUL, > - FIELD_EX64(env->vtype, VTYPE, VLMUL)); > -flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); > -flags = FIELD_DP32(flags, TB_FLAGS, VTA, > - FIELD_EX64(env->vtype, VTYPE, VTA)); > -flags = FIELD_DP32(flags, TB_FLAGS, VMA, > - FIELD_EX64(env->vtype, VTYPE, VMA)); > -flags = FIELD_DP32(flags, TB_FLAGS, VSTART_EQ_ZERO, env->vstart == > 0); > -} else { > -flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); > -} > - > -#ifdef CONFIG_USER_ONLY > -fs = EXT_STATUS_DIRTY; > -vs = EXT_STATUS_DIRTY; > -#else > -flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv); > - > -flags |= cpu_mmu_index(env, 0); > -fs = get_field(env->mstatus, MSTATUS_FS); > -vs = get_field(env->mstatus, MSTATUS_VS); > - > -if (env->virt_enabled) { > -flags = FIELD_DP32(flags, TB_FLAGS, VIRT_ENABLED, 1); > -/* > - * Merge DISABLED and !DIRTY states using MIN. > - * We will set both fields when dirtying. > - */ > -fs = MIN(fs, get_field(env->mstatus_hs, MSTATUS_FS)); > -vs = MIN(vs, get_field(env->mstatus_hs, MSTATUS_VS)); > -} > - > -/* With Zfinx, floating point is enabled/disabled by Smstateen. */ > -if (!riscv_has_ext(env, RVF)) { > -fs = (smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR) == RISCV_EXCP_NONE) > - ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED; > -} > - > -if (cpu->cfg.debug && !icount_enabled()) { > -flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled); > -} > -#endif > - > -flags = FIELD_DP32(flags, TB_FLAGS, FS, fs); > -flags = FIELD_DP32(flags, TB_FLAGS, VS, vs); > -flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl); > -flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env)); > -if (env->cur_pmmask != 0) { > -flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1); > -} > -if (env->cur_pmbase != 0) { > -flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1); > -} > - > -*pflags = flags; > -} > - > void riscv_cpu_update_mask(CPURISCVState *env) > { > target_ulong mask = 0, base = 0; > diff --git a/target/riscv/tcg/cpu.c b/target/riscv/tcg/cpu.c > new file mode 100644 > index 00..2ae6919b80 > --- /dev/null > +++ b/target/riscv/tcg/cpu.c > @@ -0,0 +1,98 @@ > +/* > + * RISC-V CPU helpers (TCG specific) > + * > + * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu > + * Copyright (c) 2017-2018 SiFive, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "cpu.h" > +#ifndef CONFIG_USER_ONLY > +#include "sysemu/cpu-timers.h" > +#endif > + > +void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, > + uint64_t *cs_base, uint32_t *pflags) > +{ > +CPUState *cs = env_cpu(env); > +RISCVCPU *cpu = RISCV_CPU(cs); > +RISCVExtStat
Re: [PATCH v3 09/16] target/riscv: Expose some 'trigger' prototypes from debug.c
On Tue, Jul 11, 2023 at 10:16 PM Philippe Mathieu-Daudé wrote: > > We want to extract TCG-specific code from debug.c, but some > functions call get_trigger_type() / do_trigger_action(). > Expose these prototypes in "debug.h". > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/debug.h | 4 > target/riscv/debug.c | 5 ++--- > 2 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/target/riscv/debug.h b/target/riscv/debug.h > index c471748d5a..65cd45b8f3 100644 > --- a/target/riscv/debug.h > +++ b/target/riscv/debug.h > @@ -147,4 +147,8 @@ void riscv_trigger_init(CPURISCVState *env); > > bool riscv_itrigger_enabled(CPURISCVState *env); > void riscv_itrigger_update_priv(CPURISCVState *env); > + > +target_ulong get_trigger_type(CPURISCVState *env, target_ulong > trigger_index); > +void do_trigger_action(CPURISCVState *env, target_ulong trigger_index); > + > #endif /* RISCV_DEBUG_H */ > diff --git a/target/riscv/debug.c b/target/riscv/debug.c > index 75ee1c4971..5676f2c57e 100644 > --- a/target/riscv/debug.c > +++ b/target/riscv/debug.c > @@ -88,8 +88,7 @@ static inline target_ulong > extract_trigger_type(CPURISCVState *env, > } > } > > -static inline target_ulong get_trigger_type(CPURISCVState *env, > -target_ulong trigger_index) > +target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index) > { > return extract_trigger_type(env, env->tdata1[trigger_index]); > } > @@ -217,7 +216,7 @@ static inline void warn_always_zero_bit(target_ulong val, > target_ulong mask, > } > } > > -static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index) > +void do_trigger_action(CPURISCVState *env, target_ulong trigger_index) > { > trigger_action_t action = get_trigger_action(env, trigger_index); > > -- > 2.38.1 > >
Re: [PATCH for-8.0] tcg/sparc64: Disable direct linking for goto_tb
On 5/4/23 1:04 am, Richard Henderson wrote: Something is wrong with this code, and also wrong with gdb on the sparc systems to which I have access, so I cannot debug it either. Disable for now, so the release is not broken. I'm not sure if it is the entire problem but it looks like the broken code had the same race as on ppc [1] between loading TCG_REG_TB and patching and executing the direct branch. [1] https://lore.kernel.org/qemu-devel/20230717093001.13167-1-jniet...@gmail.com/#t Signed-off-by: Richard Henderson --- tcg/sparc64/tcg-target.c.inc | 30 -- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index ccc4144f7c..694f2b9dd4 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -1445,12 +1445,12 @@ static void tcg_out_goto_tb(TCGContext *s, int which) { ptrdiff_t off = tcg_tbrel_diff(s, (void *)get_jmp_target_addr(s, which)); -/* Direct branch will be patched by tb_target_set_jmp_target. */ +/* Load link and indirect branch. */ set_jmp_insn_offset(s, which); -tcg_out32(s, CALL); -/* delay slot */ -tcg_debug_assert(check_fit_ptr(off, 13)); tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, TCG_REG_TB, off); +tcg_out_arithi(s, TCG_REG_G0, TCG_REG_TB, 0, JMPL); +/* delay slot */ +tcg_out_nop(s); set_jmp_reset_offset(s, which); /* @@ -1469,28 +1469,6 @@ static void tcg_out_goto_tb(TCGContext *s, int which) void tb_target_set_jmp_target(const TranslationBlock *tb, int n, uintptr_t jmp_rx, uintptr_t jmp_rw) { -uintptr_t addr = tb->jmp_target_addr[n]; -intptr_t br_disp = (intptr_t)(addr - jmp_rx) >> 2; -tcg_insn_unit insn; - -br_disp >>= 2; -if (check_fit_ptr(br_disp, 19)) { -/* ba,pt %icc, addr */ -insn = deposit32(INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A) - | BPCC_ICC | BPCC_PT, 0, 19, br_disp); -} else if (check_fit_ptr(br_disp, 22)) { -/* ba addr */ -insn = deposit32(INSN_OP(0) | INSN_OP2(2) | INSN_COND(COND_A), - 0, 22, br_disp); -} else { -/* The code_gen_buffer can't be larger than 2GB. */ -tcg_debug_assert(check_fit_ptr(br_disp, 30)); -/* call addr */ -insn = deposit32(CALL, 0, 30, br_disp); -} - -qatomic_set((uint32_t *)jmp_rw, insn); -flush_idcache_range(jmp_rx, jmp_rw, 4); } static void tcg_out_op(TCGContext *s, TCGOpcode opc,
Re: [PATCH v3 10/16] target/riscv: Extract TCG-specific code from debug.c
On Tue, Jul 11, 2023 at 10:21 PM Philippe Mathieu-Daudé wrote: > > Extract TCG-specific code from debug.c to tcg/sysemu/debug.c, > restrict the prototypes to TCG, adapt meson rules. > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/debug.h| 2 + > target/riscv/debug.c| 148 - > target/riscv/tcg/sysemu/debug.c | 165 > target/riscv/tcg/meson.build| 2 + > target/riscv/tcg/sysemu/meson.build | 3 + > 5 files changed, 172 insertions(+), 148 deletions(-) > create mode 100644 target/riscv/tcg/sysemu/debug.c > create mode 100644 target/riscv/tcg/sysemu/meson.build > > diff --git a/target/riscv/debug.h b/target/riscv/debug.h > index 65cd45b8f3..0b3bdd5be1 100644 > --- a/target/riscv/debug.h > +++ b/target/riscv/debug.h > @@ -139,9 +139,11 @@ void tdata_csr_write(CPURISCVState *env, int > tdata_index, target_ulong val); > > target_ulong tinfo_csr_read(CPURISCVState *env); > > +#ifdef CONFIG_TCG > void riscv_cpu_debug_excp_handler(CPUState *cs); > bool riscv_cpu_debug_check_breakpoint(CPUState *cs); > bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); > +#endif > > void riscv_trigger_init(CPURISCVState *env); > > diff --git a/target/riscv/debug.c b/target/riscv/debug.c > index 5676f2c57e..45a2605d8a 100644 > --- a/target/riscv/debug.c > +++ b/target/riscv/debug.c > @@ -754,154 +754,6 @@ target_ulong tinfo_csr_read(CPURISCVState *env) > BIT(TRIGGER_TYPE_AD_MATCH6); > } > > -void riscv_cpu_debug_excp_handler(CPUState *cs) > -{ > -RISCVCPU *cpu = RISCV_CPU(cs); > -CPURISCVState *env = &cpu->env; > - > -if (cs->watchpoint_hit) { > -if (cs->watchpoint_hit->flags & BP_CPU) { > -do_trigger_action(env, DBG_ACTION_BP); > -} > -} else { > -if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { > -do_trigger_action(env, DBG_ACTION_BP); > -} > -} > -} > - > -bool riscv_cpu_debug_check_breakpoint(CPUState *cs) > -{ > -RISCVCPU *cpu = RISCV_CPU(cs); > -CPURISCVState *env = &cpu->env; > -CPUBreakpoint *bp; > -target_ulong ctrl; > -target_ulong pc; > -int trigger_type; > -int i; > - > -QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { > -for (i = 0; i < RV_MAX_TRIGGERS; i++) { > -trigger_type = get_trigger_type(env, i); > - > -switch (trigger_type) { > -case TRIGGER_TYPE_AD_MATCH: > -/* type 2 trigger cannot be fired in VU/VS mode */ > -if (env->virt_enabled) { > -return false; > -} > - > -ctrl = env->tdata1[i]; > -pc = env->tdata2[i]; > - > -if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { > -/* check U/S/M bit against current privilege level */ > -if ((ctrl >> 3) & BIT(env->priv)) { > -return true; > -} > -} > -break; > -case TRIGGER_TYPE_AD_MATCH6: > -ctrl = env->tdata1[i]; > -pc = env->tdata2[i]; > - > -if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) { > -if (env->virt_enabled) { > -/* check VU/VS bit against current privilege level */ > -if ((ctrl >> 23) & BIT(env->priv)) { > -return true; > -} > -} else { > -/* check U/S/M bit against current privilege level */ > -if ((ctrl >> 3) & BIT(env->priv)) { > -return true; > -} > -} > -} > -break; > -default: > -/* other trigger types are not supported or irrelevant */ > -break; > -} > -} > -} > - > -return false; > -} > - > -bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) > -{ > -RISCVCPU *cpu = RISCV_CPU(cs); > -CPURISCVState *env = &cpu->env; > -target_ulong ctrl; > -target_ulong addr; > -int trigger_type; > -int flags; > -int i; > - > -for (i = 0; i < RV_MAX_TRIGGERS; i++) { > -trigger_type = get_trigger_type(env, i); > - > -switch (trigger_type) { > -case TRIGGER_TYPE_AD_MATCH: > -/* type 2 trigger cannot be fired in VU/VS mode */ > -if (env->virt_enabled) { > -return false; > -} > - > -ctrl = env->tdata1[i]; > -addr = env->tdata2[i]; > -flags = 0; > - > -if (ctrl & TYPE2_LOAD) { > -flags |= BP_MEM_READ; > -} > -if (ctrl & TYPE2_STORE) { > -flags |= BP_MEM_WRITE; > -
Re: [PATCH v3 11/16] target/riscv: Move sysemu-specific debug files to target/riscv/sysemu/
On Tue, Jul 11, 2023 at 10:22 PM Philippe Mathieu-Daudé wrote: > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/cpu.h| 2 +- > target/riscv/{ => sysemu}/debug.h | 0 > target/riscv/cpu_helper.c | 2 +- > target/riscv/{ => sysemu}/debug.c | 0 > target/riscv/meson.build | 4 > target/riscv/sysemu/meson.build | 1 + > 6 files changed, 3 insertions(+), 6 deletions(-) > rename target/riscv/{ => sysemu}/debug.h (100%) > rename target/riscv/{ => sysemu}/debug.c (100%) > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > index 0602b948d4..8d8e30d6c1 100644 > --- a/target/riscv/cpu.h > +++ b/target/riscv/cpu.h > @@ -94,7 +94,7 @@ typedef enum { > > #if !defined(CONFIG_USER_ONLY) > #include "sysemu/pmp.h" > -#include "debug.h" > +#include "sysemu/debug.h" > #endif > > #define RV_VLEN_MAX 1024 > diff --git a/target/riscv/debug.h b/target/riscv/sysemu/debug.h > similarity index 100% > rename from target/riscv/debug.h > rename to target/riscv/sysemu/debug.h > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 6f8778c6d3..6c773000a5 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -32,7 +32,7 @@ > #include "sysemu/cpu-timers.h" > #endif > #include "cpu_bits.h" > -#include "debug.h" > +#include "sysemu/debug.h" > #include "tcg/oversized-guest.h" > > int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) > diff --git a/target/riscv/debug.c b/target/riscv/sysemu/debug.c > similarity index 100% > rename from target/riscv/debug.c > rename to target/riscv/sysemu/debug.c > diff --git a/target/riscv/meson.build b/target/riscv/meson.build > index 8ef47f43f9..49cdcde679 100644 > --- a/target/riscv/meson.build > +++ b/target/riscv/meson.build > @@ -8,10 +8,6 @@ riscv_ss.add(files( >'gdbstub.c', > )) > > -riscv_system_ss.add(files( > - 'debug.c', > -)) > - > subdir('tcg') > subdir('sysemu') > > diff --git a/target/riscv/sysemu/meson.build b/target/riscv/sysemu/meson.build > index 64de0256a5..e902ba2dad 100644 > --- a/target/riscv/sysemu/meson.build > +++ b/target/riscv/sysemu/meson.build > @@ -1,5 +1,6 @@ > riscv_system_ss.add(files( >'arch_dump.c', > + 'debug.c', >'machine.c', >'monitor.c', >'pmp.c', > -- > 2.38.1 > >
Re: [PATCH v3 12/16] target/riscv: Expose riscv_cpu_pending_to_irq() from cpu_helper.c
On Tue, Jul 11, 2023 at 10:22 PM Philippe Mathieu-Daudé wrote: > > We want to extract TCG/sysemu-specific code from cpu_helper.c, > but some functions call riscv_cpu_pending_to_irq(). Expose the > prototype in "internals.h". > > Signed-off-by: Philippe Mathieu-Daudé Acked-by: Alistair Francis Alistair > --- > target/riscv/internals.h | 4 > target/riscv/cpu_helper.c | 6 +++--- > 2 files changed, 7 insertions(+), 3 deletions(-) > > diff --git a/target/riscv/internals.h b/target/riscv/internals.h > index b5f823c7ec..b6881b4815 100644 > --- a/target/riscv/internals.h > +++ b/target/riscv/internals.h > @@ -72,6 +72,10 @@ target_ulong fclass_d(uint64_t frs1); > > #ifndef CONFIG_USER_ONLY > extern const VMStateDescription vmstate_riscv_cpu; > + > +int riscv_cpu_pending_to_irq(CPURISCVState *env, > + int extirq, unsigned int extirq_def_prio, > + uint64_t pending, uint8_t *iprio); > #endif > > enum { > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 6c773000a5..e73cf56e5c 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -256,9 +256,9 @@ uint8_t riscv_cpu_default_priority(int irq) > return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO; > }; > > -static int riscv_cpu_pending_to_irq(CPURISCVState *env, > -int extirq, unsigned int extirq_def_prio, > -uint64_t pending, uint8_t *iprio) > +int riscv_cpu_pending_to_irq(CPURISCVState *env, > + int extirq, unsigned int extirq_def_prio, > + uint64_t pending, uint8_t *iprio) > { > int irq, best_irq = RISCV_EXCP_NONE; > unsigned int prio, best_prio = UINT_MAX; > -- > 2.38.1 > >
Re: [PATCH] target/riscv/cpu.c: check priv_ver before auto-enable zca/zcd/zcf
On Tue, Jul 18, 2023 at 1:42 AM Daniel Henrique Barboza wrote: > > Commit bd30559568 made changes in how we're checking and disabling > extensions based on env->priv_ver. One of the changes was to move the > extension disablement code to the end of realize(), being able to > disable extensions after we've auto-enabled some of them. > > An unfortunate side effect of this change started to happen with CPUs > that has an older priv version, like sifive-u54. Starting on commit > 2288a5ce43e5 we're auto-enabling zca, zcd and zcf if RVC is enabled, > but these extensions are priv version 1.12.0. When running a cpu that > has an older priv ver (like sifive-u54) the user is spammed with > warnings like these: > > qemu-system-riscv64: warning: disabling zca extension for hart > 0x because privilege spec version does not match > qemu-system-riscv64: warning: disabling zcd extension for hart > 0x because privilege spec version does not match > > The warnings are part of the code that disables the extension, but in this > case we're throwing user warnings for stuff that we enabled on our own, > without user intervention. Users are left wondering what they did wrong. > > A quick 8.1 fix for this nuisance is to check the CPU priv spec before > auto-enabling zca/zcd/zcf. A more appropriate fix will include a more > robust framework that will account for both priv_ver and user choice > when auto-enabling/disabling extensions, but for 8.1 we'll make it do > with this simple check. > > It's also worth noticing that this is the only case where we're > auto-enabling extensions based on a criteria (in this case RVC) that > doesn't match the priv spec of the extensions we're enabling. There's no > need for more 8.1 band-aids. > > Cc: Conor Dooley > Fixes: 2288a5ce43e5 ("target/riscv: add cfg properties for Zc* extension") > Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Alistair > --- > target/riscv/cpu.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 9339c0241d..6b93b04453 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -1225,7 +1225,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, > Error **errp) > } > } > > -if (riscv_has_ext(env, RVC)) { > +/* zca, zcd and zcf has a PRIV 1.12.0 restriction */ > +if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { > cpu->cfg.ext_zca = true; > if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { > cpu->cfg.ext_zcf = true; > -- > 2.41.0 > >
Re: Tips for local testing guestfwd
Hi all, I am continuing debugging the ipv6 guestfwd feature, and I would like to understand the behavior of slirp better. Progress I've made: Let QEMU take parameter like following: guestfwd=tcp:[fec0::105]:54322-tcp:[::1]:6655 For slirp side, I basically searched for the appearance of gfwd_list and made all code traverse the fwd list compatible with ipv6. With these change, now I can see the packets coming out of the guest OS to the assigned guest server port via tcpdump: ``` 00:38:18.831831 IP6 fdb5:481:10ce:0:8c41:aaff:fea9:f674.52190 > fec0::105.54322: tcp 0 0x: 600a 1f94 0028 0640 fdb5 0481 10ce `(.@ 0x0010: 8c41 aaff fea9 f674 fec0 .A.t 0x0020: 0105 cbde d432 df6d 8332 ...2.m.2 0x0030: a0*02* fd20 535f 0204 05a0 S_.. 0x0040: 0402 080a b87b fd3b 0103 0307 .{.; ``` 02 == SYN so it looks good. But both tcpdump and wireshark (looking into packet dump provided by QEMU invocation) didn't see any response and this packet never reached the host. I added multiple prints inside slirp and confirmed the ipv6 version of [1] was reached. in tcp_output function [2], I got following print: qemu-system-aarch64: info: Slirp: AF_INET6 out dst ip = fdb5:481:10ce:0:8c41:aaff:fea9:f674, port = 52190 qemu-system-aarch64: info: Slirp: AF_INET6 out src ip = fec0::105, port = 54322 It looks like there should be something being sent back to the guest, unless my understanding of tcp_output is wrong. To understand the datapath of guestfwd better, I have the following questions: 1. What's the meaning of tcp_input and tcp_output? My guess is the following graph, but I would like to confirm. tcp_input tcp_output QEMU > slirp --> host < <-- tcp_output tcp_input 2. I don't see port 6655 in the above process. How does slirp know 6655 is the port that needs to be visited on the host side? Thanks in advance, Felix [1]. https://gitlab.freedesktop.org/slirp/libslirp/-/blob/master/src/tcp_input.c#L630 [2]. https://gitlab.freedesktop.org/slirp/libslirp/-/blob/master/src/tcp_output.c#L477 On Mon, Jun 26, 2023 at 3:08 AM Samuel Thibault wrote: > Hello, > > Felix Wu wrote: > > 2. I want to understand what ip I should use. Currently I have following > > formats for the QEMU invocation in ipv6: > > ``` > > guestfwd=tcp:[::1]:1234-tcp:[my:host:ip:from:ifconfig]:22 > > ``` > > I know the general form is `guestfwd=tcp:server:port-dev`, where > > server:port is for guest, > > Yes, the address to be used within the guest network. So it needs to be > within the guest network. > > > Is the aforementioned invocation correct? > > No, because ::1 isn't in the guest network. > > > Or in this case [::1] is the local host address and I should put qemu > > address for it instead? > > You can use whatever IP you want, as long as it's in the guest network. > e.g. [fec0::1234] if you're with the default fec0::/64 network. > > > 3. Is there a default ipv6 address for QEMU instance? I think I need it > in > > the invocation. > > By default it's address 2 within the prefix, i.e. fec0::2 with the > default fec0::/64 network. > > Samuel >
Re: [PATCH] target/riscv/cpu.c: check priv_ver before auto-enable zca/zcd/zcf
On Tue, Jul 18, 2023 at 7:50 PM Daniel Henrique Barboza wrote: > > > > On 7/17/23 22:36, LIU Zhiwei wrote: > > > > On 2023/7/17 23:41, Daniel Henrique Barboza wrote: > >> Commit bd30559568 made changes in how we're checking and disabling > >> extensions based on env->priv_ver. One of the changes was to move the > >> extension disablement code to the end of realize(), being able to > >> disable extensions after we've auto-enabled some of them. > >> > >> An unfortunate side effect of this change started to happen with CPUs > >> that has an older priv version, like sifive-u54. Starting on commit > >> 2288a5ce43e5 we're auto-enabling zca, zcd and zcf if RVC is enabled, > >> but these extensions are priv version 1.12.0. When running a cpu that > >> has an older priv ver (like sifive-u54) the user is spammed with > >> warnings like these: > >> > >> qemu-system-riscv64: warning: disabling zca extension for hart > >> 0x because privilege spec version does not match > >> qemu-system-riscv64: warning: disabling zcd extension for hart > >> 0x because privilege spec version does not match > >> > >> The warnings are part of the code that disables the extension, but in this > >> case we're throwing user warnings for stuff that we enabled on our own, > >> without user intervention. Users are left wondering what they did wrong. > >> > >> A quick 8.1 fix for this nuisance is to check the CPU priv spec before > >> auto-enabling zca/zcd/zcf. A more appropriate fix will include a more > >> robust framework that will account for both priv_ver and user choice > >> when auto-enabling/disabling extensions, but for 8.1 we'll make it do > >> with this simple check. > >> > >> It's also worth noticing that this is the only case where we're > >> auto-enabling extensions based on a criteria (in this case RVC) that > >> doesn't match the priv spec of the extensions we're enabling. There's no > >> need for more 8.1 band-aids. > >> > >> Cc: Conor Dooley > >> Fixes: 2288a5ce43e5 ("target/riscv: add cfg properties for Zc* extension") > >> Signed-off-by: Daniel Henrique Barboza > >> --- > >> target/riscv/cpu.c | 3 ++- > >> 1 file changed, 2 insertions(+), 1 deletion(-) > >> > >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > >> index 9339c0241d..6b93b04453 100644 > >> --- a/target/riscv/cpu.c > >> +++ b/target/riscv/cpu.c > >> @@ -1225,7 +1225,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU > >> *cpu, Error **errp) > >> } > >> } > >> -if (riscv_has_ext(env, RVC)) { > >> +/* zca, zcd and zcf has a PRIV 1.12.0 restriction */ > > > > I think the Zca/zcd/zcf doesn't have much relationship with the privilege > > specification. The privilege specification doesn't define any > > CSR or rules that Zca/zcd/zcf depend on. Maybe I missed something. Does > > anyone know why we should check PRIV_VERSION_1_12_0 for zca/zcf/zcd? > > I always thought about this priv spec filter as a way to determine the time > window that the extension was ratified/defined. In this example it's been used > to filter out zca/zcd/zcf from the sifive-u54 chip because this chip is older > than those extensions, so it doesn't make sense to enable them. That's true. The priv spec check is also there because we needed newer versions of the priv spec for some extensions, and if we are going to check some it's simpler to just check all of them. > > > > > I think we should remove the check for priv_ver for many user mode > > extensions. We should set the checking privilege specification version for > > these extensions to PRIV_VERSION_1_10_0. > > I think it's hard to pick and choose which extensions will have a priv > version check > or not. If we're bothered with the priv spec check per se then we should > remove it Agreed > entirely. Here's my plan to do it: I think that'll work > > - remove cfg.priv_ver. This is a very old attribute that allow users to set > the priv_ver > for generic CPUs like rv64. I'm doing changes in the user options for TCG > flags and the > very existence of this option forces me to make priv checks for all > extensions we're > auto-enabling during realize() (because I can't be sure whether the user > changed the > priv_ver of rv64 to something older); I'm not sure about that though. As we see more CPUs being released and then future spec changes I feel like differentiating between priv specs is a useful feature. Alistair > > - split the realize() functions between generic and vendor CPUs again. It was > merged together > earlier this year (I did it) because, back then, we were doing too much stuff > during > realize() that was needed for named CPUs, but the side effect is what we're > seeing now: > the common code is enabling unwanted extensions for vendor CPUs. The code is > very different > now, and I believe that we can at least skip validate_set_extensions() for > vendor CPUs; > > - at this point, vendor CPUs aren't auto-enabling any features and gen
Re: [PATCH] target/riscv/cpu.c: check priv_ver before auto-enable zca/zcd/zcf
On Tue, Jul 18, 2023 at 1:42 AM Daniel Henrique Barboza wrote: > > Commit bd30559568 made changes in how we're checking and disabling > extensions based on env->priv_ver. One of the changes was to move the > extension disablement code to the end of realize(), being able to > disable extensions after we've auto-enabled some of them. > > An unfortunate side effect of this change started to happen with CPUs > that has an older priv version, like sifive-u54. Starting on commit > 2288a5ce43e5 we're auto-enabling zca, zcd and zcf if RVC is enabled, > but these extensions are priv version 1.12.0. When running a cpu that > has an older priv ver (like sifive-u54) the user is spammed with > warnings like these: > > qemu-system-riscv64: warning: disabling zca extension for hart > 0x because privilege spec version does not match > qemu-system-riscv64: warning: disabling zcd extension for hart > 0x because privilege spec version does not match > > The warnings are part of the code that disables the extension, but in this > case we're throwing user warnings for stuff that we enabled on our own, > without user intervention. Users are left wondering what they did wrong. > > A quick 8.1 fix for this nuisance is to check the CPU priv spec before > auto-enabling zca/zcd/zcf. A more appropriate fix will include a more > robust framework that will account for both priv_ver and user choice > when auto-enabling/disabling extensions, but for 8.1 we'll make it do > with this simple check. > > It's also worth noticing that this is the only case where we're > auto-enabling extensions based on a criteria (in this case RVC) that > doesn't match the priv spec of the extensions we're enabling. There's no > need for more 8.1 band-aids. > > Cc: Conor Dooley > Fixes: 2288a5ce43e5 ("target/riscv: add cfg properties for Zc* extension") > Signed-off-by: Daniel Henrique Barboza Thanks! Applied to riscv-to-apply.next Alistair > --- > target/riscv/cpu.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 9339c0241d..6b93b04453 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -1225,7 +1225,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, > Error **errp) > } > } > > -if (riscv_has_ext(env, RVC)) { > +/* zca, zcd and zcf has a PRIV 1.12.0 restriction */ > +if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { > cpu->cfg.ext_zca = true; > if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { > cpu->cfg.ext_zcf = true; > -- > 2.41.0 > >
Re: [PATCH] hw/riscv: Fix topo field in error_report
On Tue, Jul 18, 2023 at 5:57 PM Zhao Liu wrote: > > From: Zhao Liu > > "smp.cpus" means the number of online CPUs and "smp.max_cpus" means the > total number of CPUs. > > riscv_numa_get_default_cpu_node_id() checks "smp.cpus" and the > "available CPUs" description in the next error message also indicates > online CPUs. > > So report "smp.cpus" in error_report() instand of "smp.max_cpus". > > Since "smp.cpus" is "unsigned int", use "%u". > > Signed-off-by: Zhao Liu Reviewed-by: Alistair Francis Alistair > --- > hw/riscv/numa.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/hw/riscv/numa.c b/hw/riscv/numa.c > index e0414d5b1b73..d319aefb4511 100644 > --- a/hw/riscv/numa.c > +++ b/hw/riscv/numa.c > @@ -209,8 +209,8 @@ int64_t riscv_numa_get_default_cpu_node_id(const > MachineState *ms, int idx) > > if (ms->numa_state->num_nodes > ms->smp.cpus) { > error_report("Number of NUMA nodes (%d)" > - " cannot exceed the number of available CPUs (%d).", > - ms->numa_state->num_nodes, ms->smp.max_cpus); > + " cannot exceed the number of available CPUs (%u).", > + ms->numa_state->num_nodes, ms->smp.cpus); > exit(EXIT_FAILURE); > } > if (ms->numa_state->num_nodes) { > -- > 2.34.1 > >
Re: [PATCH v2] target/riscv: Fix LMUL check to use VLEN
On 2023/7/18 21:11, Rob Bradford wrote: The previous check was failing with: VLEN=128 ELEN = 64 SEW = 16 and LMUL = 1/8 which is a valid combination. Fix the check to allow valid combinations when VLEN is a multiple of ELEN. From the specification: "In general, the requirement is to support LMUL ≥ SEWMIN/ELEN, where SEWMIN is the narrowest supported SEW value and ELEN is the widest supported SEW value. In the standard extensions, SEWMIN=8. For standard vector extensions with ELEN=32, fractional LMULs of 1/2 and 1/4 must be supported. For standard vector extensions with ELEN=64, fractional LMULs of 1/2, 1/4, and 1/8 must be supported." Elsewhere in the specification it makes clear that VLEN>=ELEN. From inspection this new check allows: VLEN=ELEN=64 1/2, 1/4, 1/8 for SEW >=8 VLEN=ELEN=32 1/2, 1/4 for SEW >=8 Fixes: d9b7609a1fb2 ("target/riscv: rvv-1.0: configure instructions") Signed-off-by: Rob Bradford --- V2: Switch check to use VLEN and active SEW vs ELEN and minimum SEW --- Reviewed-by: Weiwei Li Weiwei Li target/riscv/vector_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index cfacf2ebba..4d06754826 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -43,9 +43,9 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, xlen - 1 - R_VTYPE_RESERVED_SHIFT); if (lmul & 4) { -/* Fractional LMUL. */ +/* Fractional LMUL - check LMUL * VLEN >= SEW */ if (lmul == 4 || -cpu->cfg.elen >> (8 - lmul) < sew) { +cpu->cfg.vlen >> (8 - lmul) < sew) { vill = true; } }
Re: [PATCH 1/3] target/riscv: Add cycle & instret privilege mode filtering properties
On 2023/7/19 06:47, Kaiwen Xue wrote: This adds the properties for ISA extension smcntrpmf. Patches implementing it will follow. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + 2 files changed, 3 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9339c0241d..31a1862561 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -132,6 +132,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), +ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval), @@ -1753,6 +1754,7 @@ static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), +DEFINE_PROP_BOOL("smcntrpmf", RISCVCPU, cfg.ext_smcntrpmf, false), Normally, property should be exposed to user at last after the function is implemented. Regards, Weiwei Li DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 2bd9510ba3..424246cbec 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -69,6 +69,7 @@ struct RISCVCPUConfig { bool ext_zihintpause; bool ext_smstateen; bool ext_sstc; +bool ext_smcntrpmf; bool ext_svadu; bool ext_svinval; bool ext_svnapot;
Re: [PATCH] hw/riscv: Fix topo field in error_report
On Tue, Jul 18, 2023 at 5:57 PM Zhao Liu wrote: > > From: Zhao Liu > > "smp.cpus" means the number of online CPUs and "smp.max_cpus" means the > total number of CPUs. > > riscv_numa_get_default_cpu_node_id() checks "smp.cpus" and the > "available CPUs" description in the next error message also indicates > online CPUs. > > So report "smp.cpus" in error_report() instand of "smp.max_cpus". > > Since "smp.cpus" is "unsigned int", use "%u". > > Signed-off-by: Zhao Liu I fixed up the typo in the commit title Thanks! Applied to riscv-to-apply.next Alistair > --- > hw/riscv/numa.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/hw/riscv/numa.c b/hw/riscv/numa.c > index e0414d5b1b73..d319aefb4511 100644 > --- a/hw/riscv/numa.c > +++ b/hw/riscv/numa.c > @@ -209,8 +209,8 @@ int64_t riscv_numa_get_default_cpu_node_id(const > MachineState *ms, int idx) > > if (ms->numa_state->num_nodes > ms->smp.cpus) { > error_report("Number of NUMA nodes (%d)" > - " cannot exceed the number of available CPUs (%d).", > - ms->numa_state->num_nodes, ms->smp.max_cpus); > + " cannot exceed the number of available CPUs (%u).", > + ms->numa_state->num_nodes, ms->smp.cpus); > exit(EXIT_FAILURE); > } > if (ms->numa_state->num_nodes) { > -- > 2.34.1 > >
[PATCH 2/3] target/riscv: Add cycle & instret privilege mode filtering definitions
This adds the definitions for ISA extension smcntrpmf. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue --- target/riscv/cpu.h | 6 ++ target/riscv/cpu_bits.h | 29 + 2 files changed, 35 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6ea22e0eea..3cdf5d09f7 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -283,6 +283,12 @@ struct CPUArchState { target_ulong mcountinhibit; +/* PMU cycle & instret privilege mode filtering */ +target_ulong mcyclecfg; +target_ulong mcyclecfgh; +target_ulong minstretcfg; +target_ulong minstretcfgh; + /* PMU counter state */ PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 59f0ffd9e1..0a25fb276b 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -401,6 +401,10 @@ /* Machine counter-inhibit register */ #define CSR_MCOUNTINHIBIT 0x320 +/* Machine counter configuration registers */ +#define CSR_MCYCLECFG 0x321 +#define CSR_MINSTRETCFG 0x322 + #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 @@ -431,6 +435,9 @@ #define CSR_MHPMEVENT30 0x33e #define CSR_MHPMEVENT31 0x33f +#define CSR_MCYCLECFGH 0x721 +#define CSR_MINSTRETCFGH0x722 + #define CSR_MHPMEVENT3H 0x723 #define CSR_MHPMEVENT4H 0x724 #define CSR_MHPMEVENT5H 0x725 @@ -879,6 +886,28 @@ typedef enum RISCVException { /* PMU related bits */ #define MIE_LCOFIE (1 << IRQ_PMU_OVF) +#define MCYCLECFG_BIT_MINH BIT_ULL(62) +#define MCYCLECFGH_BIT_MINHBIT(30) +#define MCYCLECFG_BIT_SINH BIT_ULL(61) +#define MCYCLECFGH_BIT_SINHBIT(29) +#define MCYCLECFG_BIT_UINH BIT_ULL(60) +#define MCYCLECFGH_BIT_UINHBIT(28) +#define MCYCLECFG_BIT_VSINHBIT_ULL(59) +#define MCYCLECFGH_BIT_VSINH BIT(27) +#define MCYCLECFG_BIT_VUINHBIT_ULL(58) +#define MCYCLECFGH_BIT_VUINH BIT(26) + +#define MINSTRETCFG_BIT_MINH BIT_ULL(62) +#define MINSTRETCFGH_BIT_MINH BIT(30) +#define MINSTRETCFG_BIT_SINH BIT_ULL(61) +#define MINSTRETCFGH_BIT_SINH BIT(29) +#define MINSTRETCFG_BIT_UINH BIT_ULL(60) +#define MINSTRETCFGH_BIT_UINH BIT(28) +#define MINSTRETCFG_BIT_VSINH BIT_ULL(59) +#define MINSTRETCFGH_BIT_VSINH BIT(27) +#define MINSTRETCFG_BIT_VUINH BIT_ULL(58) +#define MINSTRETCFGH_BIT_VUINH BIT(26) + #define MHPMEVENT_BIT_OF BIT_ULL(63) #define MHPMEVENTH_BIT_OF BIT(31) #define MHPMEVENT_BIT_MINH BIT_ULL(62) -- 2.34.1
[PATCH 3/3] target/riscv: Add cycle & instret privilege mode filtering support
QEMU only calculates dummy cycles and instructions, so there is no actual means to stop the icount in QEMU. Hence this patch merely adds the functionality of accessing the cfg registers, and cause no actual effects on the counting of cycle and instret counters. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue --- target/riscv/csr.c | 73 ++ 1 file changed, 73 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ea7585329e..b1d5e85a79 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -218,6 +218,17 @@ static RISCVException sscofpmf(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } +static RISCVException smcntrpmf(CPURISCVState *env, int csrno) +{ +RISCVCPU *cpu = env_archcpu(env); + +if (!cpu->cfg.ext_smcntrpmf) { +return RISCV_EXCP_ILLEGAL_INST; +} + +return RISCV_EXCP_NONE; +} + static RISCVException any(CPURISCVState *env, int csrno) { return RISCV_EXCP_NONE; @@ -800,6 +811,54 @@ static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) #else /* CONFIG_USER_ONLY */ +static int read_mcyclecfg(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->mcyclecfg; +return RISCV_EXCP_NONE; +} + +static int write_mcyclecfg(CPURISCVState *env, int csrno, target_ulong val) +{ +env->mcyclecfg = val; +return RISCV_EXCP_NONE; +} + +static int read_mcyclecfgh(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->mcyclecfgh; +return RISCV_EXCP_NONE; +} + +static int write_mcyclecfgh(CPURISCVState *env, int csrno, target_ulong val) +{ +env->mcyclecfgh = val; +return RISCV_EXCP_NONE; +} + +static int read_minstretcfg(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->minstretcfg; +return RISCV_EXCP_NONE; +} + +static int write_minstretcfg(CPURISCVState *env, int csrno, target_ulong val) +{ +env->minstretcfg = val; +return RISCV_EXCP_NONE; +} + +static int read_minstretcfgh(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->minstretcfgh; +return RISCV_EXCP_NONE; +} + +static int write_minstretcfgh(CPURISCVState *env, int csrno, target_ulong val) +{ +env->minstretcfgh = val; +return RISCV_EXCP_NONE; +} + static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) { int evt_index = csrno - CSR_MCOUNTINHIBIT; @@ -4506,6 +4565,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0 }, +[CSR_MCYCLECFG] = { "mcyclecfg", smcntrpmf, read_mcyclecfg, + write_mcyclecfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, +[CSR_MINSTRETCFG]= { "minstretcfg", smcntrpmf, read_minstretcfg, + write_minstretcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_mhpmevent, write_mhpmevent }, [CSR_MHPMEVENT4] = { "mhpmevent4", any,read_mhpmevent, @@ -4565,6 +4631,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHPMEVENT31]= { "mhpmevent31",any,read_mhpmevent, write_mhpmevent }, +[CSR_MCYCLECFGH] = { "mcyclecfgh", smcntrpmf, read_mcyclecfgh, + write_mcyclecfgh, + .min_priv_ver = PRIV_VERSION_1_12_0}, +[CSR_MINSTRETCFGH] = { "minstretcfgh", smcntrpmf, read_minstretcfgh, + write_minstretcfgh, + .min_priv_ver = PRIV_VERSION_1_12_0}, + [CSR_MHPMEVENT3H]= { "mhpmevent3h",sscofpmf, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0}, -- 2.34.1
[PATCH 1/3] target/riscv: Add cycle & instret privilege mode filtering properties
This adds the properties for ISA extension smcntrpmf. Patches implementing it will follow. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + 2 files changed, 3 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9339c0241d..31a1862561 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -132,6 +132,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), +ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval), @@ -1753,6 +1754,7 @@ static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), +DEFINE_PROP_BOOL("smcntrpmf", RISCVCPU, cfg.ext_smcntrpmf, false), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 2bd9510ba3..424246cbec 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -69,6 +69,7 @@ struct RISCVCPUConfig { bool ext_zihintpause; bool ext_smstateen; bool ext_sstc; +bool ext_smcntrpmf; bool ext_svadu; bool ext_svinval; bool ext_svnapot; -- 2.34.1
[PATCH 0/3] risc-v: Add ISA extension smcntrpmf support
This patch series adds the support for RISC-V ISA extension smcntrpmf (cycle and privilege mode filtering) [1]. QEMU only calculates dummy cycles and instructions, so there is no actual means to stop the icount in QEMU. Therefore, this series only add the read/write behavior of the relevant CSRs such that the implemented firmware support [2] can work without causing unnecessary illegal instruction exceptions. [1] https://github.com/riscv/riscv-smcntrpmf [2] https://github.com/rivosinc/opensbi/tree/dev/kaiwenx/smcntrpmf_upstream Kaiwen Xue (3): target/riscv: Add cycle & instret privilege mode filtering properties target/riscv: Add cycle & instret privilege mode filtering definitions target/riscv: Add cycle & instret privilege mode filtering support target/riscv/cpu.c | 2 ++ target/riscv/cpu.h | 6 target/riscv/cpu_bits.h | 29 target/riscv/cpu_cfg.h | 1 + target/riscv/csr.c | 73 + 5 files changed, 111 insertions(+) -- 2.34.1
Re: [PATCH 3/3] target/riscv: Add cycle & instret privilege mode filtering support
On 2023/7/19 06:47, Kaiwen Xue wrote: QEMU only calculates dummy cycles and instructions, so there is no actual means to stop the icount in QEMU. Hence this patch merely adds the functionality of accessing the cfg registers, and cause no actual effects on the counting of cycle and instret counters. Maybe you can record/accumulate them when privilege mode changes/switchs. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue --- target/riscv/csr.c | 73 ++ 1 file changed, 73 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ea7585329e..b1d5e85a79 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -218,6 +218,17 @@ static RISCVException sscofpmf(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } +static RISCVException smcntrpmf(CPURISCVState *env, int csrno) +{ +RISCVCPU *cpu = env_archcpu(env); + +if (!cpu->cfg.ext_smcntrpmf) { +return RISCV_EXCP_ILLEGAL_INST; +} + +return RISCV_EXCP_NONE; +} + static RISCVException any(CPURISCVState *env, int csrno) { return RISCV_EXCP_NONE; @@ -800,6 +811,54 @@ static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) #else /* CONFIG_USER_ONLY */ +static int read_mcyclecfg(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->mcyclecfg; +return RISCV_EXCP_NONE; +} + +static int write_mcyclecfg(CPURISCVState *env, int csrno, target_ulong val) +{ +env->mcyclecfg = val; +return RISCV_EXCP_NONE; +} + +static int read_mcyclecfgh(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->mcyclecfgh; +return RISCV_EXCP_NONE; +} + +static int write_mcyclecfgh(CPURISCVState *env, int csrno, target_ulong val) +{ +env->mcyclecfgh = val; +return RISCV_EXCP_NONE; +} + +static int read_minstretcfg(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->minstretcfg; +return RISCV_EXCP_NONE; +} + +static int write_minstretcfg(CPURISCVState *env, int csrno, target_ulong val) +{ +env->minstretcfg = val; +return RISCV_EXCP_NONE; +} + +static int read_minstretcfgh(CPURISCVState *env, int csrno, target_ulong *val) +{ +*val = env->minstretcfgh; +return RISCV_EXCP_NONE; +} + +static int write_minstretcfgh(CPURISCVState *env, int csrno, target_ulong val) +{ +env->minstretcfgh = val; +return RISCV_EXCP_NONE; +} + static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) { int evt_index = csrno - CSR_MCOUNTINHIBIT; @@ -4506,6 +4565,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0 }, +[CSR_MCYCLECFG] = { "mcyclecfg", smcntrpmf, read_mcyclecfg, + write_mcyclecfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, +[CSR_MINSTRETCFG]= { "minstretcfg", smcntrpmf, read_minstretcfg, + write_minstretcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_mhpmevent, write_mhpmevent }, [CSR_MHPMEVENT4] = { "mhpmevent4", any,read_mhpmevent, @@ -4565,6 +4631,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHPMEVENT31]= { "mhpmevent31",any,read_mhpmevent, write_mhpmevent }, +[CSR_MCYCLECFGH] = { "mcyclecfgh", smcntrpmf, read_mcyclecfgh, + write_mcyclecfgh, + .min_priv_ver = PRIV_VERSION_1_12_0}, +[CSR_MINSTRETCFGH] = { "minstretcfgh", smcntrpmf, read_minstretcfgh, + write_minstretcfgh, + .min_priv_ver = PRIV_VERSION_1_12_0}, This two CSRs are RV32-only, they cannot directly share the same predicate as MCYCLECFG/MINSTRETCFG. Regards, Weiwei Li + [CSR_MHPMEVENT3H]= { "mhpmevent3h",sscofpmf, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0},
Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)
On Sat, Jul 15, 2023 at 7:14 PM Atish Patra wrote: > > On Fri, Jul 14, 2023 at 5:29 AM Conor Dooley wrote: > > > > On Fri, Jul 14, 2023 at 11:19:34AM +0100, Conor Dooley wrote: > > > On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote: > > > > > > > > > OpenSBI v1.3 > > > > > >_ _ > > > > > > / __ \ / | _ \_ _| > > > > > > | | | |_ __ ___ _ __ | (___ | |_) || | > > > > > > | | | | '_ \ / _ \ '_ \ \___ \| _ < | | > > > > > > | |__| | |_) | __/ | | |) | |_) || |_ > > > > > > \/| .__/ \___|_| |_|_/|___/_| > > > > > > | | > > > > > > |_| > > > > > > > > > > > > init_coldboot: ipi init failed (error -1009) > > > > > > > > > > > > Just to note, because we use our own firmware that vendors in > > > > > > OpenSBI > > > > > > and compiles only a significantly cut down number of files from it, > > > > > > we > > > > > > do not use the fw_dynamic etc flow on our hardware. As a result, we > > > > > > have > > > > > > not tested v1.3, nor do we have any immediate plans to change our > > > > > > platform firmware to vendor v1.3 either. > > > > > > > > > > > > I unless there's something obvious to you, it sounds like I will > > > > > > need to > > > > > > go and bisect OpenSBI. That's a job for another day though, given > > > > > > the > > > > > > time. > > > > > > > > > > > > > > The real issue is some CPU/HART DT nodes marked as disabled in the > > > > DT passed to OpenSBI 1.3. > > > > > > > > This issue does not exist in any of the DTs generated by QEMU but some > > > > of the DTs in the kernel (such as microchip and SiFive board DTs) have > > > > the E-core disabled. > > > > > > > > I had discovered this issue in a totally different context after the > > > > OpenSBI 1.3 > > > > release happened. This issue is already fixed in the latest OpenSBI by > > > > the > > > > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 ("lib: utils: > > > > Fix sbi_hartid_to_scratch() usage in ACLINT drivers"). > > > > > > Great, thanks Anup! I thought I had tested tip-of-tree too, but > > > obviously not. > > > > > > > I always assumed that Microchip hss.bin is the preferred BIOS for the > > > > QEMU microchip-icicle-kit machine but I guess that's not true. > > > > > > Unfortunately the HSS has not worked in QEMU for a long time, and while > > > I would love to fix it, but am pretty stretched for spare time to begin > > > with. > > > I usually just do direct kernel boots, which use the OpenSBI that comes > > > with QEMU, as I am sure you already know :) > > > > > > > At this point, you can either: > > > > 1) Use latest OpenSBI on QEMU microchip-icicle-kit machine > > > > I forgot to reply to this point, wondering what should be done with > > QEMU. Bumping to v1.3 in QEMU introduces a regression here, regardless > > of whether I can go and build a fixed version of OpenSBI. > > > FYI: The no-map fix went in OpenSBI v1.3. Without the upgrade, any > user using the latest kernel (> v6.4) > may hit those random linear map related issues (in hibernation or EFI > booting path). > > There are three possible scenarios: > > 1. Upgrade to OpenSBI v1.3: Any user of microchip-icicle-kit machine > or sifive fu540 machine users > may hit this issue if the device tree has the disabled hart (e core). > 2. No upgrade to OpenSBI v1.2. Any user using hibernation or UEFI may > have issues [1] > 3. Include a non-release version OpenSBI in Qemu with the fix as an exception. > > #3 probably deviates from policy and sets a bad precedent. So I am not > advocating for it though ;) > For both #1 & #2, the solution would be to use the latest OpenSBI in > -bios argument instead of the stock one. > I could be wrong but my guess is the number of users facing #2 would > be higher than #1. Thanks for that info Atish! We are stuck in a bad situation. The best solution would be if OpenSBI can release a 1.3.1, @Anup Patel do you think you could do that? Otherwise I think we should stick with OpenSBI 1.3. Considering that it fixes UEFI boot issues for the virt board (which would be the most used) it seems like a best call to make. People using the other boards are unfortunately stuck building their own OpenSBI release. If there is no OpenSBI 1.3.1 release we should add something to the release notes. @Conor Dooley are you able to give a clear sentence on how the boot fails? Alistair > > [1] > https://lore.kernel.org/linux-riscv/20230625140931.1266216-1-songshuaish...@tinylab.org/ > > > > 2) Ensure CPU0 DT node is enabled in DT when booting on QEMU > > > > microchip-icicle-kit machine with OpenSBI 1.3 > > > > > > Will OpenSBI disable it? If not, I think option 2) needs to be remove > > > the DT node. I'll just use tip-of-tree myself & up to the > > > > Clearly didn't finish this comment. It was meant to say "up to the QEMU > > maintainers what they want to do on the QEMU side of things". > > > > Thanks, > > Conor. > > > > -- > Rega
Re: [PATCH v2] target/riscv: Fix LMUL check to use VLEN
On Tue, Jul 18, 2023 at 11:14 PM Rob Bradford wrote: > > The previous check was failing with: > > VLEN=128 ELEN = 64 SEW = 16 and LMUL = 1/8 which is a > valid combination. > > Fix the check to allow valid combinations when VLEN is a multiple of > ELEN. > > From the specification: > > "In general, the requirement is to support LMUL ≥ SEWMIN/ELEN, where > SEWMIN is the narrowest supported SEW value and ELEN is the widest > supported SEW value. In the standard extensions, SEWMIN=8. For standard > vector extensions with ELEN=32, fractional LMULs of 1/2 and 1/4 must be > supported. For standard vector extensions with ELEN=64, fractional LMULs > of 1/2, 1/4, and 1/8 must be supported." Elsewhere in the specification > it makes clear that VLEN>=ELEN. > > From inspection this new check allows: > > VLEN=ELEN=64 1/2, 1/4, 1/8 for SEW >=8 > VLEN=ELEN=32 1/2, 1/4 for SEW >=8 > > Fixes: d9b7609a1fb2 ("target/riscv: rvv-1.0: configure instructions") > > Signed-off-by: Rob Bradford Thanks! Applied to riscv-to-apply.next Alistair > --- > V2: Switch check to use VLEN and active SEW vs ELEN and minimum SEW > --- > target/riscv/vector_helper.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c > index cfacf2ebba..4d06754826 100644 > --- a/target/riscv/vector_helper.c > +++ b/target/riscv/vector_helper.c > @@ -43,9 +43,9 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, > target_ulong s1, > xlen - 1 - > R_VTYPE_RESERVED_SHIFT); > > if (lmul & 4) { > -/* Fractional LMUL. */ > +/* Fractional LMUL - check LMUL * VLEN >= SEW */ > if (lmul == 4 || > -cpu->cfg.elen >> (8 - lmul) < sew) { > +cpu->cfg.vlen >> (8 - lmul) < sew) { > vill = true; > } > } > -- > 2.41.0 > >
Re: [PATCH] vhost: disable VHOST_OPS_DEBUG by default
On 7/17/2023 6:14 PM, Philippe Mathieu-Daudé wrote: Hi, On 17/7/23 19:44, Zhu Lingshan wrote: This commit disables VHOST_OPS_DEBUG by default These information are ususally only required in development environment Signed-off-by: Zhu Lingshan --- hw/virtio/vhost.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 82394331bf..ec435a3079 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -29,7 +29,9 @@ #include "trace.h" /* enabled until disconnected backend stabilizes */ -#define _VHOST_DEBUG 1 + +/* uncomment macro _VHOST_DEBUG to enable VHOST_OPS_DEBUG */ +/* #define _VHOST_DEBUG 1 */ Since you are looking at this, it would be more useful to convert VHOST_OPS_DEBUG() to trace events (see for example commit 163b8663b8 and other "Convert DPRINTF() debug macro to trace events" commits). Thanks Phil, I will look into this Regards, Phil.
[PATCH v5 0/3] hw/ufs: Add Universal Flash Storage (UFS) support
Since v4: Addressed review comment from Stefan Hajnoczi. The fixes are as follows. - Keep u->reg fields in host endian (Removed little-endian helper functions from MemoryRegionOps) - Remove unnecessary NULL checks for g_new and g_malloc0 - Replace DEFINE_PROP_DRIVE_IOTHREAD -> DEFINE_PROP_DRIVE In case you were wondering, ufs and ufs-lu have been tested for the following behaviours. 1. Checked ufs device recognition in Windows10 environment 2. Verified ufs device recognition in Ubuntu 22.04 environment 3. Verified io behaviour via fio in Ubuntu 22.04 environment 4. Verified query request via ufs-tools in Ubuntu 22.04 environment Since v3: - Replace softmmu_ss -> system_ss in meson Since v2: Addressed review comment from Stefan Hajnoczi. The main fixes are as follows. - Use of SPDX licence identifiers - fixed endianness error - removed memory leak - fixed DMA error handling logic Since v1: - use macros of "hw/registerfields.h" (Addressed Philippe's review comments) This patch series adds support for a new PCI-based UFS device. The UFS pci device id (PCI_DEVICE_ID_REDHAT_UFS) is not registered in the Linux kernel yet, so it does not work right away, but I confirmed that it works with Linux when the UFS pci device id is registered. I have also verified that it works with Windows 10. Jeuk Kim (3): hw/ufs: Initial commit for emulated Universal-Flash-Storage hw/ufs: Support for Query Transfer Requests hw/ufs: Support for UFS logical unit MAINTAINERS |6 + docs/specs/pci-ids.rst |2 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/lu.c | 1439 hw/ufs/meson.build |1 + hw/ufs/trace-events | 58 ++ hw/ufs/trace.h |1 + hw/ufs/ufs.c | 1494 ++ hw/ufs/ufs.h | 131 include/block/ufs.h | 1048 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + include/scsi/constants.h |1 + meson.build |1 + 16 files changed, 4190 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/lu.c create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h -- 2.34.1
[PATCH v5 2/3] hw/ufs: Support for Query Transfer Requests
From: Jeuk Kim This commit makes the UFS device support query and nop out transfer requests. The next patch would be support for UFS logical unit and scsi command transfer request. Signed-off-by: Jeuk Kim --- hw/ufs/trace-events | 1 + hw/ufs/ufs.c| 980 +++- hw/ufs/ufs.h| 46 +++ 3 files changed, 1025 insertions(+), 2 deletions(-) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events index d1badcad10..665e1a942b 100644 --- a/hw/ufs/trace-events +++ b/hw/ufs/trace-events @@ -18,6 +18,7 @@ ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to write utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" ufs_err_dma_write_rsp_upiu(uint32_t slot, uint64_t addr) "failed to write rsp upiu. UTRLDBR slot %"PRIu32", response upiu addr %"PRIu64"" +ufs_err_utrl_slot_error(uint32_t slot) "UTRLDBR slot %"PRIu32" is in error" ufs_err_utrl_slot_busy(uint32_t slot) "UTRLDBR slot %"PRIu32" is busy" ufs_err_unsupport_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is not yet supported" ufs_err_invalid_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is invalid" diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index 101082a8a3..cd33af2cde 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -15,10 +15,221 @@ #include "ufs.h" /* The QEMU-UFS device follows spec version 3.1 */ -#define UFS_SPEC_VER 0x0310 +#define UFS_SPEC_VER 0x0310 #define UFS_MAX_NUTRS 32 #define UFS_MAX_NUTMRS 8 +static MemTxResult ufs_addr_read(UfsHc *u, hwaddr addr, void *buf, int size) +{ +hwaddr hi = addr + size - 1; + +if (hi < addr) { +return MEMTX_DECODE_ERROR; +} + +if (!FIELD_EX32(u->reg.cap, CAP, 64AS) && (hi >> 32)) { +return MEMTX_DECODE_ERROR; +} + +return pci_dma_read(PCI_DEVICE(u), addr, buf, size); +} + +static MemTxResult ufs_addr_write(UfsHc *u, hwaddr addr, const void *buf, + int size) +{ +hwaddr hi = addr + size - 1; +if (hi < addr) { +return MEMTX_DECODE_ERROR; +} + +if (!FIELD_EX32(u->reg.cap, CAP, 64AS) && (hi >> 32)) { +return MEMTX_DECODE_ERROR; +} + +return pci_dma_write(PCI_DEVICE(u), addr, buf, size); +} + +static void ufs_complete_req(UfsRequest *req, UfsReqResult req_result); + +static inline hwaddr ufs_get_utrd_addr(UfsHc *u, uint32_t slot) +{ +hwaddr utrl_base_addr = (((hwaddr)u->reg.utrlbau) << 32) + u->reg.utrlba; +hwaddr utrd_addr = utrl_base_addr + slot * sizeof(UtpTransferReqDesc); + +return utrd_addr; +} + +static inline hwaddr ufs_get_req_upiu_base_addr(const UtpTransferReqDesc *utrd) +{ +uint32_t cmd_desc_base_addr_lo = +le32_to_cpu(utrd->command_desc_base_addr_lo); +uint32_t cmd_desc_base_addr_hi = +le32_to_cpu(utrd->command_desc_base_addr_hi); + +return (((hwaddr)cmd_desc_base_addr_hi) << 32) + cmd_desc_base_addr_lo; +} + +static inline hwaddr ufs_get_rsp_upiu_base_addr(const UtpTransferReqDesc *utrd) +{ +hwaddr req_upiu_base_addr = ufs_get_req_upiu_base_addr(utrd); +uint32_t rsp_upiu_byte_off = +le16_to_cpu(utrd->response_upiu_offset) * sizeof(uint32_t); +return req_upiu_base_addr + rsp_upiu_byte_off; +} + +static MemTxResult ufs_dma_read_utrd(UfsRequest *req) +{ +UfsHc *u = req->hc; +hwaddr utrd_addr = ufs_get_utrd_addr(u, req->slot); +MemTxResult ret; + +ret = ufs_addr_read(u, utrd_addr, &req->utrd, sizeof(req->utrd)); +if (ret) { +trace_ufs_err_dma_read_utrd(req->slot, utrd_addr); +} +return ret; +} + +static MemTxResult ufs_dma_read_req_upiu(UfsRequest *req) +{ +UfsHc *u = req->hc; +hwaddr req_upiu_base_addr = ufs_get_req_upiu_base_addr(&req->utrd); +UtpUpiuReq *req_upiu = &req->req_upiu; +uint32_t copy_size; +uint16_t data_segment_length; +MemTxResult ret; + +/* + * To know the size of the req_upiu, we need to read the + * data_segment_length in the header first. + */ +ret = ufs_addr_read(u, req_upiu_base_addr, &req_upiu->header, +sizeof(UtpUpiuHeader)); +if (ret) { +trace_ufs_err_dma_read_req_upiu(req->slot, req_upiu_base_addr); +return ret; +} +data_segment_length = be16_to_cpu(req_upiu->header.data_segment_length); + +copy_size = sizeof(UtpUpiuHeader) + UFS_TRANSACTION_SPECIFIC_FIELD_SIZE + +data_segment_length; + +ret = ufs_addr_read(u, req_upiu_base_addr, &req->req_upiu, copy_size); +if (ret) { +trace_ufs_err_dma_read_req_upiu(req->slot, req_upiu_base_addr); +} +return ret; +} + +static MemTxResult ufs_dma_read_prdt(UfsRequest *req) +{ +UfsHc *u = req->hc; +uint16_t prdt_len = le16_to_cpu(req->utrd.prd_table_length); +uint16_t prdt_byte_off
[PATCH v5 1/3] hw/ufs: Initial commit for emulated Universal-Flash-Storage
From: Jeuk Kim Universal Flash Storage (UFS) is a high-performance mass storage device with a serial interface. It is primarily used as a high-performance data storage device for embedded applications. This commit contains code for UFS device to be recognized as a UFS PCI device. Patches to handle UFS logical unit and Transfer Request will follow. Signed-off-by: Jeuk Kim --- MAINTAINERS |6 + docs/specs/pci-ids.rst |2 + hw/Kconfig |1 + hw/meson.build |1 + hw/ufs/Kconfig |4 + hw/ufs/meson.build |1 + hw/ufs/trace-events | 32 ++ hw/ufs/trace.h |1 + hw/ufs/ufs.c | 278 ++ hw/ufs/ufs.h | 42 ++ include/block/ufs.h | 1048 ++ include/hw/pci/pci.h |1 + include/hw/pci/pci_ids.h |1 + meson.build |1 + 14 files changed, 1419 insertions(+) create mode 100644 hw/ufs/Kconfig create mode 100644 hw/ufs/meson.build create mode 100644 hw/ufs/trace-events create mode 100644 hw/ufs/trace.h create mode 100644 hw/ufs/ufs.c create mode 100644 hw/ufs/ufs.h create mode 100644 include/block/ufs.h diff --git a/MAINTAINERS b/MAINTAINERS index 12e59b6b27..0c8a955b42 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2256,6 +2256,12 @@ F: tests/qtest/nvme-test.c F: docs/system/devices/nvme.rst T: git git://git.infradead.org/qemu-nvme.git nvme-next +ufs +M: Jeuk Kim +S: Supported +F: hw/ufs/* +F: include/block/ufs.h + megasas M: Hannes Reinecke L: qemu-bl...@nongnu.org diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst index e302bea484..d6707fa069 100644 --- a/docs/specs/pci-ids.rst +++ b/docs/specs/pci-ids.rst @@ -92,6 +92,8 @@ PCI devices (other than virtio): PCI PVPanic device (``-device pvpanic-pci``) 1b36:0012 PCI ACPI ERST device (``-device acpi-erst``) +1b36:0013 + PCI UFS device (``-device ufs``) All these devices are documented in :doc:`index`. diff --git a/hw/Kconfig b/hw/Kconfig index ba62ff6417..9ca7b38c31 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -38,6 +38,7 @@ source smbios/Kconfig source ssi/Kconfig source timer/Kconfig source tpm/Kconfig +source ufs/Kconfig source usb/Kconfig source virtio/Kconfig source vfio/Kconfig diff --git a/hw/meson.build b/hw/meson.build index c7ac7d3d75..f01fac4617 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -37,6 +37,7 @@ subdir('smbios') subdir('ssi') subdir('timer') subdir('tpm') +subdir('ufs') subdir('usb') subdir('vfio') subdir('virtio') diff --git a/hw/ufs/Kconfig b/hw/ufs/Kconfig new file mode 100644 index 00..b7b3392e85 --- /dev/null +++ b/hw/ufs/Kconfig @@ -0,0 +1,4 @@ +config UFS_PCI +bool +default y if PCI_DEVICES +depends on PCI diff --git a/hw/ufs/meson.build b/hw/ufs/meson.build new file mode 100644 index 00..eb5164bde9 --- /dev/null +++ b/hw/ufs/meson.build @@ -0,0 +1 @@ +system_ss.add(when: 'CONFIG_UFS_PCI', if_true: files('ufs.c')) diff --git a/hw/ufs/trace-events b/hw/ufs/trace-events new file mode 100644 index 00..d1badcad10 --- /dev/null +++ b/hw/ufs/trace-events @@ -0,0 +1,32 @@ +# ufs.c +ufs_irq_raise(void) "INTx" +ufs_irq_lower(void) "INTx" +ufs_mmio_read(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_mmio_write(uint64_t addr, uint64_t data, unsigned size) "addr 0x%"PRIx64" data 0x%"PRIx64" size %d" +ufs_process_db(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_process_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_complete_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_sendback_req(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_nop_cmd(uint32_t slot) "UTRLDBR slot %"PRIu32"" +ufs_exec_scsi_cmd(uint32_t slot, uint8_t lun, uint8_t opcode) "slot %"PRIu32", lun 0x%"PRIx8", opcode 0x%"PRIx8"" +ufs_exec_query_cmd(uint32_t slot, uint8_t opcode) "slot %"PRIu32", opcode 0x%"PRIx8"" +ufs_process_uiccmd(uint32_t uiccmd, uint32_t ucmdarg1, uint32_t ucmdarg2, uint32_t ucmdarg3) "uiccmd 0x%"PRIx32", ucmdarg1 0x%"PRIx32", ucmdarg2 0x%"PRIx32", ucmdarg3 0x%"PRIx32"" + +# error condition +ufs_err_dma_read_utrd(uint32_t slot, uint64_t addr) "failed to read utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_read_req_upiu(uint32_t slot, uint64_t addr) "failed to read req upiu. UTRLDBR slot %"PRIu32", request upiu addr %"PRIu64"" +ufs_err_dma_read_prdt(uint32_t slot, uint64_t addr) "failed to read prdt. UTRLDBR slot %"PRIu32", prdt addr %"PRIu64"" +ufs_err_dma_write_utrd(uint32_t slot, uint64_t addr) "failed to write utrd. UTRLDBR slot %"PRIu32", UTRD dma addr %"PRIu64"" +ufs_err_dma_write_rsp_upiu(uint32_t slot, uint64_t addr) "failed to write rsp upiu. UTRLDBR slot %"PRIu32", response upiu addr %"PRIu64"" +ufs_err_utrl_slot_busy(uint32_t slot) "UTRLDBR slot %"PRIu32" is busy" +ufs_err_unsupport_register_offset(uint32_t offset) "Register offset 0x%"PRIx32" is not yet supported" +ufs_err_invalid_register_
[PATCH v5 3/3] hw/ufs: Support for UFS logical unit
From: Jeuk Kim This commit adds support for ufs logical unit. The LU handles processing for the SCSI command, unit descriptor query request. This commit enables the UFS device to process IO requests. Signed-off-by: Jeuk Kim --- hw/ufs/lu.c | 1439 ++ hw/ufs/meson.build |2 +- hw/ufs/trace-events | 25 + hw/ufs/ufs.c | 252 ++- hw/ufs/ufs.h | 43 ++ include/scsi/constants.h |1 + 6 files changed, 1755 insertions(+), 7 deletions(-) create mode 100644 hw/ufs/lu.c diff --git a/hw/ufs/lu.c b/hw/ufs/lu.c new file mode 100644 index 00..ab40f42190 --- /dev/null +++ b/hw/ufs/lu.c @@ -0,0 +1,1439 @@ +/* + * QEMU UFS Logical Unit + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * Written by Jeuk Kim + * + * This code is licensed under the GNU GPL v2 or later. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qemu/memalign.h" +#include "hw/scsi/scsi.h" +#include "scsi/constants.h" +#include "sysemu/block-backend.h" +#include "qemu/cutils.h" +#include "trace.h" +#include "ufs.h" + +/* + * The code below handling SCSI commands is copied from hw/scsi/scsi-disk.c, + * with minor adjustments to make it work for UFS. + */ + +#define SCSI_DMA_BUF_SIZE (128 * KiB) +#define SCSI_MAX_INQUIRY_LEN 256 +#define SCSI_INQUIRY_DATA_SIZE 36 +#define SCSI_MAX_MODE_LEN 256 + +typedef struct UfsSCSIReq { +SCSIRequest req; +/* Both sector and sector_count are in terms of BDRV_SECTOR_SIZE bytes. */ +uint64_t sector; +uint32_t sector_count; +uint32_t buflen; +bool started; +bool need_fua_emulation; +struct iovec iov; +QEMUIOVector qiov; +BlockAcctCookie acct; +} UfsSCSIReq; + +static void ufs_scsi_free_request(SCSIRequest *req) +{ +UfsSCSIReq *r = DO_UPCAST(UfsSCSIReq, req, req); + +qemu_vfree(r->iov.iov_base); +} + +static void scsi_check_condition(UfsSCSIReq *r, SCSISense sense) +{ +trace_ufs_scsi_check_condition(r->req.tag, sense.key, sense.asc, + sense.ascq); +scsi_req_build_sense(&r->req, sense); +scsi_req_complete(&r->req, CHECK_CONDITION); +} + +static int ufs_scsi_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf, + uint32_t outbuf_len) +{ +UfsHc *u = UFS(req->bus->qbus.parent); +UfsLu *lu = DO_UPCAST(UfsLu, qdev, req->dev); +uint8_t page_code = req->cmd.buf[2]; +int start, buflen = 0; + +if (outbuf_len < SCSI_INQUIRY_DATA_SIZE) { +return -1; +} + +outbuf[buflen++] = lu->qdev.type & 0x1f; +outbuf[buflen++] = page_code; +outbuf[buflen++] = 0x00; +outbuf[buflen++] = 0x00; +start = buflen; + +switch (page_code) { +case 0x00: /* Supported page codes, mandatory */ +{ +trace_ufs_scsi_emulate_vpd_page_00(req->cmd.xfer); +outbuf[buflen++] = 0x00; /* list of supported pages (this page) */ +if (u->params.serial) { +outbuf[buflen++] = 0x80; /* unit serial number */ +} +outbuf[buflen++] = 0x87; /* mode page policy */ +break; +} +case 0x80: /* Device serial number, optional */ +{ +int l; + +if (!u->params.serial) { +trace_ufs_scsi_emulate_vpd_page_80_not_supported(); +return -1; +} + +l = strlen(u->params.serial); +if (l > SCSI_INQUIRY_DATA_SIZE) { +l = SCSI_INQUIRY_DATA_SIZE; +} + +trace_ufs_scsi_emulate_vpd_page_80(req->cmd.xfer); +memcpy(outbuf + buflen, u->params.serial, l); +buflen += l; +break; +} +case 0x87: /* Mode Page Policy, mandatory */ +{ +trace_ufs_scsi_emulate_vpd_page_87(req->cmd.xfer); +outbuf[buflen++] = 0x3f; /* apply to all mode pages and subpages */ +outbuf[buflen++] = 0xff; +outbuf[buflen++] = 0; /* shared */ +outbuf[buflen++] = 0; +break; +} +default: +return -1; +} +/* done with EVPD */ +assert(buflen - start <= 255); +outbuf[start - 1] = buflen - start; +return buflen; +} + +static int ufs_scsi_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf, +uint32_t outbuf_len) +{ +int buflen = 0; + +if (outbuf_len < SCSI_INQUIRY_DATA_SIZE) { +return -1; +} + +if (req->cmd.buf[1] & 0x1) { +/* Vital product data */ +return ufs_scsi_emulate_vpd_page(req, outbuf, outbuf_len); +} + +/* Standard INQUIRY data */ +if (req->cmd.buf[2] != 0) { +return -1; +} + +/* PAGE CODE == 0 */ +buflen = req->cmd.xfer; +if (buflen > SCSI_MAX_INQUIRY_LEN) { +buflen = SCSI_MAX_INQUIRY_LEN; +} + +if (is_wlun(req->lun)) { +outbuf[0] = TYPE_WLUN; +} else { +outbuf[0] = 0; +} +outbuf[1] = 0; + +strpadcpy((char *)&outbuf[16], 16, "QEMU UFS",
Re: [PATCH 04/10] hw/riscv: virt: Add PCIe HIGHMEM in memmap
On Tue, Jul 18, 2023 at 05:05:12PM -0300, Daniel Henrique Barboza wrote: > > > On 7/12/23 13:39, Sunil V L wrote: > > PCIe High MMIO base is actually dynamic and fixed at > > run time based on the RAM configured. Currently, this is > > not part of the memmap and kept in separate static variable > > in virt.c. However, ACPI code also needs this information > > to populate DSDT. So, once the base is discovered, merge > > this into the final memmap which can be used to create > > ACPI tables later. > > > > Signed-off-by: Sunil V L > > --- > > hw/riscv/virt.c | 31 ++- > > include/hw/riscv/virt.h | 9 +++-- > > 2 files changed, 37 insertions(+), 3 deletions(-) > > > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > > index f6067db8ec..7aee06f021 100644 > > --- a/hw/riscv/virt.c > > +++ b/hw/riscv/virt.c > > @@ -84,6 +84,22 @@ static const MemMapEntry virt_memmap[] = { > > static MemMapEntry virt_high_pcie_memmap; > > +/* > > + * virt_memmap doesn't include floating High Mem IO address entry. To > > enable > > + * code organization in multiple files (ex: ACPI), it is better to have > > single > > + * memmap which has complete information. > > + * > > + * VIRT_HIGH_PCIE_MMIO is always greater than the last memmap entry and > > hence > > + * full_virt_memmap is capable of holding both virt_memmap and > > + * VIRT_HIGH_PCIE_MMIO entry. > > + * > > + * The values for these floating entries will be updated when top of RAM is > > + * discovered. > > + */ > > +static MemMapEntry full_virt_memmap[] = { > > +[VIRT_HIGH_PCIE_MMIO] = { 0x0, 0 }, > > +}; > > + > > #define VIRT_FLASH_SECTOR_SIZE (256 * KiB) > > static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s, > > @@ -1444,7 +1460,20 @@ static void virt_machine_init(MachineState *machine) > > ROUND_UP(virt_high_pcie_memmap.base, > > virt_high_pcie_memmap.size); > > } > > -s->memmap = virt_memmap; > > +/* > > + * Initialize the floating values in full memory map > > + */ > > +full_virt_memmap[VIRT_HIGH_PCIE_MMIO].base = > > virt_high_pcie_memmap.base; > > +full_virt_memmap[VIRT_HIGH_PCIE_MMIO].size = > > virt_high_pcie_memmap.size; > > + > > +s->memmap = full_virt_memmap; > > +/* > > + * Copy the base virt_memmap entries to full memmap > > + */ > > +for (i = 0; i < ARRAY_SIZE(virt_memmap); i++) { > > +s->memmap[i] = virt_memmap[i]; > > +} > > + > > This change here kind of convinces me of the point I made earlier in patch 2: > we can simplify gpex_pcie_init() to use just the RISCVVirtState as a parameter > and get everything else from it. > > It's also something for a follow-up. As for this patch: > > Reviewed-by: Daniel Henrique Barboza > Thanks Daniel. I agree. I can send another follow-up patch to simplify gpex_pcie_init. Thanks, Sunil
Re: [PATCH QEMU v8 4/9] migration: Introduce dirty-limit capability
On Tue, Jul 18, 2023 at 7:04 PM Markus Armbruster wrote: > Yong Huang writes: > > > On Thu, Jul 13, 2023 at 8:44 PM Markus Armbruster > wrote: > > > >> ~hyman writes: > >> > >> > From: Hyman Huang(黄勇) > >> > > >> > Introduce migration dirty-limit capability, which can > >> > be turned on before live migration and limit dirty > >> > page rate durty live migration. > >> > > >> > Introduce migrate_dirty_limit function to help check > >> > if dirty-limit capability enabled during live migration. > >> > > >> > Meanwhile, refactor vcpu_dirty_rate_stat_collect > >> > so that period can be configured instead of hardcoded. > >> > > >> > dirty-limit capability is kind of like auto-converge > >> > but using dirty limit instead of traditional cpu-throttle > >> > to throttle guest down. To enable this feature, turn on > >> > the dirty-limit capability before live migration using > >> > migrate-set-capabilities, and set the parameters > >> > "x-vcpu-dirty-limit-period", "vcpu-dirty-limit" suitably > >> > to speed up convergence. > >> > > >> > Signed-off-by: Hyman Huang(黄勇) > >> > Acked-by: Peter Xu > >> > Reviewed-by: Juan Quintela > >> > >> [...] > >> > >> > diff --git a/qapi/migration.json b/qapi/migration.json > >> > index e43371955a..031832cde5 100644 > >> > --- a/qapi/migration.json > >> > +++ b/qapi/migration.json > >> > @@ -497,6 +497,15 @@ > >> > # are present. 'return-path' capability must be enabled to use > >> > # it. (since 8.1) > >> > # > >> > +# @dirty-limit: If enabled, migration will use the dirty-limit > >> > +# algorithm to throttle down guest instead of auto-converge > >> > +# algorithm. This algorithm only works when vCPU's dirtyrate > >> > >> Two spaces after sentence-ending punctuation, please. > >> > >> "dirty rate" with a space, because that's how we spell it elsewhere. > >> > >> > +# greater than 'vcpu-dirty-limit', read processes in guest os > >> > +# aren't penalized any more, so the algorithm can improve > >> > +# performance of vCPU during live migration. This is an optional > >> > +# performance feature and should not affect the correctness of > the > >> > +# existing auto-converge algorithm. (since 8.1) > >> > +# > >> > >> I'm still confused. > >> > >> The text suggests there are two separate algorithms "to throttle down > >> guest": "auto converge" and "dirty limit", and we get to pick one. > >> Correct? > >> > > Yes, indeed ! > > > >> > >> If it is correct, then the last sentence feels redundant: picking > >> another algorithm can't affect the algorithm we're *not* using. What > >> are you trying to express here? > >> > > What i want to express is that the new algorithm implementation does > > not affect the original algorithm, leaving it in the comments seems > > redundant indeed. I'll drop this in the next version. > > Works for me. > > >> When do we use "auto converge", and when do we use "dirty limit"? > >> > >> What does the user really need to know about these algorithms? Enough > >> to pick one, I guess. That means advantages and disadvantages of the > >> two algorithms. Which are? > > > > 1. The implementation of dirty-limit is based on dirty-ring, which is > > qualified > >to big systems with huge memories and can improve huge guest VM > > responsiveness remarkably during live migration. As a consequence, > > dirty-limit > > is recommended on platforms with huge guest VMs as is the way with > > dirty-ring. > > 2. dirty-limit convergence algorithm does not affect the "read-process" > in > > guest > >VM, so guest VM gains the equal read performance nearly as it runs on > > host > >during the live migration. As a result, dirty-limit is recommended if > > the guest > > VM requires a stable read performance. > > The above explanation is about the recommendation of dirty-limit, please > > review, > > if it's ok, i'll place it in the comment of the dirty-limit capability. > > Yes, please. But before that, I have still more questions. "This > algorithm only works when vCPU's dirtyrate greater than > 'vcpu-dirty-limit'" is a condition: "FEATURE only works when CONDITION". > I failed to express my meaning again : ( . "Throttle algo only works when vCPU's dirtyrate greater than 'vcpu-dirty-limit' " should change to "vCPU throttle only works when vCPU's dirtyrate greater than 'vcpu-dirty-limit'". Not the whole "algo" ! > What happens when the condition is not met? How can the user ensure the > condition is met? > > [...] > > -- Best regards
[PULL 2/5] riscv/disas: Fix disas output of upper immediates
From: Christoph Müllner The GNU assembler produces the following output for instructions with upper immediates: 2597auipc a1,0x2 24b7lui s1,0x2 6409lui s0,0x2 # c.lui The immediate operands of upper immediates are not shifted. However, the QEMU disassembler prints them shifted: 2597 auipc a1,8192 24b7 lui s1,8192 6409 lui s0,8192 # c.lui The current implementation extracts the immediate bits and shifts the by 12, so the internal representation of the immediate is the actual immediate. However, the immediates are later printed using rv_fmt_rd_imm or rv_fmt_rd_offset, which don't undo the shift. Let's fix this by using specific output formats for instructions with upper immediates, that take care of the shift. Signed-off-by: Christoph Müllner Acked-by: Alistair Francis Message-Id: <20230711075051.1531007-1-christoph.muell...@vrull.eu> Signed-off-by: Alistair Francis --- disas/riscv.h | 2 ++ disas/riscv.c | 19 --- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/disas/riscv.h b/disas/riscv.h index 9cf901fc1e..8abb578b51 100644 --- a/disas/riscv.h +++ b/disas/riscv.h @@ -227,7 +227,9 @@ enum { #define rv_fmt_pred_succ "O\tp,s" #define rv_fmt_rs1_rs2"O\t1,2" #define rv_fmt_rd_imm "O\t0,i" +#define rv_fmt_rd_uimm"O\t0,Ui" #define rv_fmt_rd_offset "O\t0,o" +#define rv_fmt_rd_uoffset "O\t0,Uo" #define rv_fmt_rd_rs1_rs2 "O\t0,1,2" #define rv_fmt_frd_rs1"O\t3,1" #define rv_fmt_frd_rs1_rs2"O\t3,1,2" diff --git a/disas/riscv.c b/disas/riscv.c index cd7b6e86a7..3873a69157 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -1135,8 +1135,8 @@ static const rv_comp_data rvcp_fsgnjx_q[] = { const rv_opcode_data rvi_opcode_data[] = { { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 }, -{ "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 }, -{ "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 }, +{ "lui", rv_codec_u, rv_fmt_rd_uimm, NULL, 0, 0, 0 }, +{ "auipc", rv_codec_u, rv_fmt_rd_uoffset, NULL, 0, 0, 0 }, { "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 }, { "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 }, { "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 }, @@ -1382,7 +1382,7 @@ const rv_opcode_data rvi_opcode_data[] = { rv_op_addi }, { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi, rvcd_imm_nz }, -{ "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, +{ "c.lui", rv_codec_ci_lui, rv_fmt_rd_uimm, NULL, rv_op_lui, rv_op_lui, rv_op_lui, rvcd_imm_nz }, { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli, rvcd_imm_nz }, @@ -4694,6 +4694,19 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec) dec->pc + dec->imm); append(buf, tmp, buflen); break; +case 'U': +fmt++; +snprintf(tmp, sizeof(tmp), "%d", dec->imm >> 12); +append(buf, tmp, buflen); +if (*fmt == 'o') { +while (strlen(buf) < tab * 2) { +append(buf, " ", buflen); +} +snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64, +dec->pc + dec->imm); +append(buf, tmp, buflen); +} +break; case 'c': { const char *name = csr_name(dec->imm & 0xfff); if (name) { -- 2.40.1
[PULL 0/5] riscv-to-apply queue
The following changes since commit 361d5397355276e3007825cc17217c1e4d4320f7: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-07-17 15:49:27 +0100) are available in the Git repository at: https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20230719-1 for you to fetch changes up to 32be32509987fbe42cf5c2fd3cea3c2ad6eae179: target/riscv: Fix LMUL check to use VLEN (2023-07-19 14:37:26 +1000) Fourth RISC-V PR for 8.1 * Fix LMUL check to use VLEN * Fix typo field in NUMA error_report * check priv_ver before auto-enable zca/zcd/zcf * Fix disas output of upper immediates * tidy CPU firmware section Christoph Müllner (1): riscv/disas: Fix disas output of upper immediates Daniel Henrique Barboza (2): docs/system/target-riscv.rst: tidy CPU firmware section target/riscv/cpu.c: check priv_ver before auto-enable zca/zcd/zcf Rob Bradford (1): target/riscv: Fix LMUL check to use VLEN Zhao Liu (1): hw/riscv: Fix typo field in error_report docs/system/target-riscv.rst | 24 disas/riscv.h| 2 ++ disas/riscv.c| 19 --- hw/riscv/numa.c | 4 ++-- target/riscv/cpu.c | 3 ++- target/riscv/vector_helper.c | 4 ++-- 6 files changed, 40 insertions(+), 16 deletions(-)
[PULL 4/5] hw/riscv: Fix typo field in error_report
From: Zhao Liu "smp.cpus" means the number of online CPUs and "smp.max_cpus" means the total number of CPUs. riscv_numa_get_default_cpu_node_id() checks "smp.cpus" and the "available CPUs" description in the next error message also indicates online CPUs. So report "smp.cpus" in error_report() instand of "smp.max_cpus". Since "smp.cpus" is "unsigned int", use "%u". Signed-off-by: Zhao Liu Reviewed-by: Alistair Francis Message-Id: <20230718080712.50-1-zhao1@linux.intel.com> Signed-off-by: Alistair Francis --- hw/riscv/numa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/riscv/numa.c b/hw/riscv/numa.c index e0414d5b1b..d319aefb45 100644 --- a/hw/riscv/numa.c +++ b/hw/riscv/numa.c @@ -209,8 +209,8 @@ int64_t riscv_numa_get_default_cpu_node_id(const MachineState *ms, int idx) if (ms->numa_state->num_nodes > ms->smp.cpus) { error_report("Number of NUMA nodes (%d)" - " cannot exceed the number of available CPUs (%d).", - ms->numa_state->num_nodes, ms->smp.max_cpus); + " cannot exceed the number of available CPUs (%u).", + ms->numa_state->num_nodes, ms->smp.cpus); exit(EXIT_FAILURE); } if (ms->numa_state->num_nodes) { -- 2.40.1
[PULL 5/5] target/riscv: Fix LMUL check to use VLEN
From: Rob Bradford The previous check was failing with: VLEN=128 ELEN = 64 SEW = 16 and LMUL = 1/8 which is a valid combination. Fix the check to allow valid combinations when VLEN is a multiple of ELEN. >From the specification: "In general, the requirement is to support LMUL ≥ SEWMIN/ELEN, where SEWMIN is the narrowest supported SEW value and ELEN is the widest supported SEW value. In the standard extensions, SEWMIN=8. For standard vector extensions with ELEN=32, fractional LMULs of 1/2 and 1/4 must be supported. For standard vector extensions with ELEN=64, fractional LMULs of 1/2, 1/4, and 1/8 must be supported." Elsewhere in the specification it makes clear that VLEN>=ELEN. >From inspection this new check allows: VLEN=ELEN=64 1/2, 1/4, 1/8 for SEW >=8 VLEN=ELEN=32 1/2, 1/4 for SEW >=8 Fixes: d9b7609a1fb2 ("target/riscv: rvv-1.0: configure instructions") Signed-off-by: Rob Bradford Reviewed-by: Weiwei Li Message-Id: <20230718131316.12283-2-rbradf...@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/vector_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index cfacf2ebba..4d06754826 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -43,9 +43,9 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, xlen - 1 - R_VTYPE_RESERVED_SHIFT); if (lmul & 4) { -/* Fractional LMUL. */ +/* Fractional LMUL - check LMUL * VLEN >= SEW */ if (lmul == 4 || -cpu->cfg.elen >> (8 - lmul) < sew) { +cpu->cfg.vlen >> (8 - lmul) < sew) { vill = true; } } -- 2.40.1
[PULL 1/5] docs/system/target-riscv.rst: tidy CPU firmware section
From: Daniel Henrique Barboza This is how the content of the "RISC-V CPU firmware" section is displayed after the html is generated: "When using the sifive_u or virt machine there are three different firmware boot options: 1. -bios default - This is the default behaviour if no -bios option is included. (...) 3. -bios - Tells QEMU to load the specified file as the firmware." It's all in the same paragraph, in a numbered list, and no special formatting for the options. Tidy it a bit by adding line breaks between items and its description. Remove the numbered list. And apply formatting for the options cited in the middle of the text. Cc: qemu-triv...@nongnu.org Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-Id: <20230712143728.383528-1-dbarb...@ventanamicro.com> Signed-off-by: Alistair Francis --- docs/system/target-riscv.rst | 24 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 89a866e4f4..ba195f1518 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -76,11 +76,19 @@ RISC-V CPU firmware When using the ``sifive_u`` or ``virt`` machine there are three different firmware boot options: -1. ``-bios default`` - This is the default behaviour if no -bios option -is included. This option will load the default OpenSBI firmware automatically. -The firmware is included with the QEMU release and no user interaction is -required. All a user needs to do is specify the kernel they want to boot -with the -kernel option -2. ``-bios none`` - QEMU will not automatically load any firmware. It is up -to the user to load all the images they need. -3. ``-bios `` - Tells QEMU to load the specified file as the firmware. + +* ``-bios default`` + +This is the default behaviour if no ``-bios`` option is included. This option +will load the default OpenSBI firmware automatically. The firmware is included +with the QEMU release and no user interaction is required. All a user needs to +do is specify the kernel they want to boot with the ``-kernel`` option + +* ``-bios none`` + +QEMU will not automatically load any firmware. It is up to the user to load all +the images they need. + +* ``-bios `` + +Tells QEMU to load the specified file as the firmware. -- 2.40.1
[PULL 3/5] target/riscv/cpu.c: check priv_ver before auto-enable zca/zcd/zcf
From: Daniel Henrique Barboza Commit bd30559568 made changes in how we're checking and disabling extensions based on env->priv_ver. One of the changes was to move the extension disablement code to the end of realize(), being able to disable extensions after we've auto-enabled some of them. An unfortunate side effect of this change started to happen with CPUs that has an older priv version, like sifive-u54. Starting on commit 2288a5ce43e5 we're auto-enabling zca, zcd and zcf if RVC is enabled, but these extensions are priv version 1.12.0. When running a cpu that has an older priv ver (like sifive-u54) the user is spammed with warnings like these: qemu-system-riscv64: warning: disabling zca extension for hart 0x because privilege spec version does not match qemu-system-riscv64: warning: disabling zcd extension for hart 0x because privilege spec version does not match The warnings are part of the code that disables the extension, but in this case we're throwing user warnings for stuff that we enabled on our own, without user intervention. Users are left wondering what they did wrong. A quick 8.1 fix for this nuisance is to check the CPU priv spec before auto-enabling zca/zcd/zcf. A more appropriate fix will include a more robust framework that will account for both priv_ver and user choice when auto-enabling/disabling extensions, but for 8.1 we'll make it do with this simple check. It's also worth noticing that this is the only case where we're auto-enabling extensions based on a criteria (in this case RVC) that doesn't match the priv spec of the extensions we're enabling. There's no need for more 8.1 band-aids. Cc: Conor Dooley Fixes: 2288a5ce43e5 ("target/riscv: add cfg properties for Zc* extension") Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Weiwei Li Tested-by: Conor Dooley Message-Id: <20230717154141.60898-1-dbarb...@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9339c0241d..6b93b04453 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1225,7 +1225,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } } -if (riscv_has_ext(env, RVC)) { +/* zca, zcd and zcf has a PRIV 1.12.0 restriction */ +if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { cpu->cfg.ext_zca = true; if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { cpu->cfg.ext_zcf = true; -- 2.40.1
Re: [PATCH QEMU v8 4/9] migration: Introduce dirty-limit capability
Yong Huang writes: > On Tue, Jul 18, 2023 at 7:04 PM Markus Armbruster wrote: > >> Yong Huang writes: >> >> > On Thu, Jul 13, 2023 at 8:44 PM Markus Armbruster >> wrote: >> > >> >> ~hyman writes: >> >> >> >> > From: Hyman Huang(黄勇) >> >> > >> >> > Introduce migration dirty-limit capability, which can >> >> > be turned on before live migration and limit dirty >> >> > page rate durty live migration. >> >> > >> >> > Introduce migrate_dirty_limit function to help check >> >> > if dirty-limit capability enabled during live migration. >> >> > >> >> > Meanwhile, refactor vcpu_dirty_rate_stat_collect >> >> > so that period can be configured instead of hardcoded. >> >> > >> >> > dirty-limit capability is kind of like auto-converge >> >> > but using dirty limit instead of traditional cpu-throttle >> >> > to throttle guest down. To enable this feature, turn on >> >> > the dirty-limit capability before live migration using >> >> > migrate-set-capabilities, and set the parameters >> >> > "x-vcpu-dirty-limit-period", "vcpu-dirty-limit" suitably >> >> > to speed up convergence. >> >> > >> >> > Signed-off-by: Hyman Huang(黄勇) >> >> > Acked-by: Peter Xu >> >> > Reviewed-by: Juan Quintela >> >> >> >> [...] >> >> >> >> > diff --git a/qapi/migration.json b/qapi/migration.json >> >> > index e43371955a..031832cde5 100644 >> >> > --- a/qapi/migration.json >> >> > +++ b/qapi/migration.json >> >> > @@ -497,6 +497,15 @@ >> >> > # are present. 'return-path' capability must be enabled to use >> >> > # it. (since 8.1) >> >> > # >> >> > +# @dirty-limit: If enabled, migration will use the dirty-limit >> >> > +# algorithm to throttle down guest instead of auto-converge >> >> > +# algorithm. This algorithm only works when vCPU's dirtyrate >> >> >> >> Two spaces after sentence-ending punctuation, please. >> >> >> >> "dirty rate" with a space, because that's how we spell it elsewhere. >> >> >> >> > +# greater than 'vcpu-dirty-limit', read processes in guest os >> >> > +# aren't penalized any more, so the algorithm can improve >> >> > +# performance of vCPU during live migration. This is an optional >> >> > +# performance feature and should not affect the correctness of >> the >> >> > +# existing auto-converge algorithm. (since 8.1) >> >> > +# >> >> >> >> I'm still confused. >> >> >> >> The text suggests there are two separate algorithms "to throttle down >> >> guest": "auto converge" and "dirty limit", and we get to pick one. >> >> Correct? >> >> >> > Yes, indeed ! >> > >> >> >> >> If it is correct, then the last sentence feels redundant: picking >> >> another algorithm can't affect the algorithm we're *not* using. What >> >> are you trying to express here? >> >> >> > What i want to express is that the new algorithm implementation does >> > not affect the original algorithm, leaving it in the comments seems >> > redundant indeed. I'll drop this in the next version. >> >> Works for me. >> >> >> When do we use "auto converge", and when do we use "dirty limit"? >> >> >> >> What does the user really need to know about these algorithms? Enough >> >> to pick one, I guess. That means advantages and disadvantages of the >> >> two algorithms. Which are? >> > >> > 1. The implementation of dirty-limit is based on dirty-ring, which is >> > qualified >> >to big systems with huge memories and can improve huge guest VM >> > responsiveness remarkably during live migration. As a consequence, >> > dirty-limit >> > is recommended on platforms with huge guest VMs as is the way with >> > dirty-ring. >> > 2. dirty-limit convergence algorithm does not affect the "read-process" >> in >> > guest >> >VM, so guest VM gains the equal read performance nearly as it runs on >> > host >> >during the live migration. As a result, dirty-limit is recommended if >> > the guest >> > VM requires a stable read performance. >> > The above explanation is about the recommendation of dirty-limit, please >> > review, >> > if it's ok, i'll place it in the comment of the dirty-limit capability. >> >> Yes, please. But before that, I have still more questions. "This >> algorithm only works when vCPU's dirtyrate greater than >> 'vcpu-dirty-limit'" is a condition: "FEATURE only works when CONDITION". >> > I failed to express my meaning again : ( . "Throttle algo only works when > vCPU's dirtyrate greater than 'vcpu-dirty-limit' " should change to > "vCPU throttle only works when vCPU's dirtyrate greater than > 'vcpu-dirty-limit'". > Not the whole "algo" ! Let me paraphrase to make sure I got it... The vCPU is throttled as needed to keep its dirty rate within the limit set with set-vcpu-dirty-limit. Correct? What happens when I enable the dirty limit convergence algorithm without setting a limit with set-vcpu-dirty-limit? >> What happens when the condition is not met? How can the user ensure the >> condition is met? >> >> [...] >> >>
[PATCH] ppc: Add stub implementation of TRIG SPRs
Linux sets these to control cache flush behaviour on Power9. Supervisor and hypervisor are allowed to write, and reads are noops. Add implementations to avoid noisy messages when booting Linux under the pseries machine with guest_errors enabled. Reviewed-by: Nicholas Piggin Signed-off-by: Joel Stanley --- target/ppc/cpu.h | 2 ++ target/ppc/cpu_init.c | 10 ++ 2 files changed, 12 insertions(+) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 25fac9577aa4..6826702ea658 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1897,7 +1897,9 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_PSSCR (0x357) #define SPR_440_INV0 (0x370) #define SPR_440_INV1 (0x371) +#define SPR_TRIG1 (0x371) #define SPR_440_INV2 (0x372) +#define SPR_TRIG2 (0x372) #define SPR_440_INV3 (0x373) #define SPR_440_ITV0 (0x374) #define SPR_440_ITV1 (0x375) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 02b7aad9b0e3..3b6ccb5ea4e6 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5660,6 +5660,16 @@ static void register_power_common_book4_sprs(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_tfmr, &spr_write_tfmr, 0x); +spr_register_hv(env, SPR_TRIG1, "TRIG1", + SPR_NOACCESS, SPR_NOACCESS, + &spr_access_nop, &spr_write_generic, + &spr_access_nop, &spr_write_generic, + 0x); +spr_register_hv(env, SPR_TRIG2, "TRIG2", + SPR_NOACCESS, SPR_NOACCESS, + &spr_access_nop, &spr_write_generic, + &spr_access_nop, &spr_write_generic, + 0x); #endif } -- 2.40.1
Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)
On Wed, Jul 19, 2023 at 7:03 AM Alistair Francis wrote: > > On Sat, Jul 15, 2023 at 7:14 PM Atish Patra wrote: > > > > On Fri, Jul 14, 2023 at 5:29 AM Conor Dooley wrote: > > > > > > On Fri, Jul 14, 2023 at 11:19:34AM +0100, Conor Dooley wrote: > > > > On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote: > > > > > > > > > > > OpenSBI v1.3 > > > > > > >_ _ > > > > > > > / __ \ / | _ \_ _| > > > > > > > | | | |_ __ ___ _ __ | (___ | |_) || | > > > > > > > | | | | '_ \ / _ \ '_ \ \___ \| _ < | | > > > > > > > | |__| | |_) | __/ | | |) | |_) || |_ > > > > > > > \/| .__/ \___|_| |_|_/|___/_| > > > > > > > | | > > > > > > > |_| > > > > > > > > > > > > > > init_coldboot: ipi init failed (error -1009) > > > > > > > > > > > > > > Just to note, because we use our own firmware that vendors in > > > > > > > OpenSBI > > > > > > > and compiles only a significantly cut down number of files from > > > > > > > it, we > > > > > > > do not use the fw_dynamic etc flow on our hardware. As a result, > > > > > > > we have > > > > > > > not tested v1.3, nor do we have any immediate plans to change our > > > > > > > platform firmware to vendor v1.3 either. > > > > > > > > > > > > > > I unless there's something obvious to you, it sounds like I will > > > > > > > need to > > > > > > > go and bisect OpenSBI. That's a job for another day though, given > > > > > > > the > > > > > > > time. > > > > > > > > > > > > > > > > > The real issue is some CPU/HART DT nodes marked as disabled in the > > > > > DT passed to OpenSBI 1.3. > > > > > > > > > > This issue does not exist in any of the DTs generated by QEMU but some > > > > > of the DTs in the kernel (such as microchip and SiFive board DTs) have > > > > > the E-core disabled. > > > > > > > > > > I had discovered this issue in a totally different context after the > > > > > OpenSBI 1.3 > > > > > release happened. This issue is already fixed in the latest OpenSBI > > > > > by the > > > > > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 ("lib: > > > > > utils: > > > > > Fix sbi_hartid_to_scratch() usage in ACLINT drivers"). > > > > > > > > Great, thanks Anup! I thought I had tested tip-of-tree too, but > > > > obviously not. > > > > > > > > > I always assumed that Microchip hss.bin is the preferred BIOS for the > > > > > QEMU microchip-icicle-kit machine but I guess that's not true. > > > > > > > > Unfortunately the HSS has not worked in QEMU for a long time, and while > > > > I would love to fix it, but am pretty stretched for spare time to begin > > > > with. > > > > I usually just do direct kernel boots, which use the OpenSBI that comes > > > > with QEMU, as I am sure you already know :) > > > > > > > > > At this point, you can either: > > > > > 1) Use latest OpenSBI on QEMU microchip-icicle-kit machine > > > > > > I forgot to reply to this point, wondering what should be done with > > > QEMU. Bumping to v1.3 in QEMU introduces a regression here, regardless > > > of whether I can go and build a fixed version of OpenSBI. > > > > > FYI: The no-map fix went in OpenSBI v1.3. Without the upgrade, any > > user using the latest kernel (> v6.4) > > may hit those random linear map related issues (in hibernation or EFI > > booting path). > > > > There are three possible scenarios: > > > > 1. Upgrade to OpenSBI v1.3: Any user of microchip-icicle-kit machine > > or sifive fu540 machine users > > may hit this issue if the device tree has the disabled hart (e core). > > 2. No upgrade to OpenSBI v1.2. Any user using hibernation or UEFI may > > have issues [1] > > 3. Include a non-release version OpenSBI in Qemu with the fix as an > > exception. > > > > #3 probably deviates from policy and sets a bad precedent. So I am not > > advocating for it though ;) > > For both #1 & #2, the solution would be to use the latest OpenSBI in > > -bios argument instead of the stock one. > > I could be wrong but my guess is the number of users facing #2 would > > be higher than #1. > > Thanks for that info Atish! > > We are stuck in a bad situation. > > The best solution would be if OpenSBI can release a 1.3.1, @Anup Patel > do you think you could do that? OpenSBI has a major number and minor number in the version but it does not have release/patch number so best would be to treat OpenSBI vX.Y.Z as bug fixes on-top-of OpenSBI vX.Y. In other words, supervisor software won't be able to differentiate between OpenSBI vX.Y.Z and OpenSBI vX.Y using sbi_get_impl_version(). There are only three commits between the ACLINT fix and OpenSBI v1.3 so as one-of case I will go ahead create OpenSBI v1.3.1 containing only four commits on-top of OpenSBI v1.3 Does this sound okay ? > > Otherwise I think we should stick with OpenSBI 1.3. Considering that > it fixes UEFI boot issues for the virt board (which would be the most > used) it seems like a best call to make. People using the other boards > ar