From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
To: Tao Ding <dingtao0430@163.com>, qemu-devel@nongnu.org
Cc: qemu-riscv@nongnu.org, pbonzini@redhat.com, palmer@dabbelt.com,
alistair.francis@wdc.com, liwei1518@gmail.com,
zhiwei_liu@linux.alibaba.com, chao.liu@processmission.com,
farosas@suse.de, lvivier@redhat.com,
pierrick.bouvier@oss.qualcomm.com, caojunze424@gmail.com
Subject: Re: [PATCH v2 4/7] hw/misc: add K230 decomp gzip
Date: Thu, 6 Aug 2026 08:47:58 -0300 [thread overview]
Message-ID: <083ce420-ca09-4968-b284-e161ba781561@oss.qualcomm.com> (raw)
In-Reply-To: <20260727155702.36484-5-dingtao0430@163.com>
Hi,
On 7/27/2026 12:56 PM, Tao Ding wrote:
> Decompression accelerator is mainly used to implement hardware GZIP decompression function.
> According to the k230 SDK, this hardware will be used during the uboot phase to decompress
> compressed files.
>
> Decomp_gzip does not have the ability to access the system bus.
> Therefore, SDMA is required for data transmission. A typical scenario is SDMA moving compressed
> data from DDR to SRAM, and Decomp_gzip reading data from SRAM. After decompression, decomp_gzip
> writes the data back to SRAM, and SDMA moves the data from SRAM to DDR.
>
> According to "K230 Technical Reference Manual v0.3.1" section 15.
> https://download.kendryte.com/developer/k230/HDK/K230%E7%A1%AC%E4%BB%B6%E6%96%87%E6%A1%A3/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf
>
> Signed-off-by: Tao Ding <dingtao0430@163.com>
> ---
LGTM. Minor comment down below:
> In patchv1, the reviewer identified some bugs, which have been fixed.
> bugs:
> Decomp gzip only support Dynamic Huffman format
> Bit 0 in 0x0 register is write only
> enhance:
> ues new reset interface
>
> MAINTAINERS | 2 +
> docs/system/riscv/k230.rst | 1 +
> hw/misc/Kconfig | 3 +
> hw/misc/k230_decomp_gzip.c | 508 +++++++++++++++++++++++++++++
> hw/misc/meson.build | 1 +
> hw/misc/trace-events | 4 +
> include/hw/misc/k230_decomp_gzip.h | 92 ++++++
> 7 files changed, 611 insertions(+)
> create mode 100644 hw/misc/k230_decomp_gzip.c
> create mode 100644 include/hw/misc/k230_decomp_gzip.h
>
[...]
> +
> +static void k230_decomp_gzip_handle_ack(void *opaque, int n, int level)
> +{
> + K230DecompGzipState *s = opaque;
> +
> + if (!level || !s->active) {
> + return;
> + }
> +
> + switch (n) {
> + case K230_DECOMP_GZIP_GPIO_DMA_WRITE_ACK:
> + {
> + uint32_t input_size = s->gzip_src_size & K230_DECOMP_GZIP_DMA_IN_MASK;
> + uint32_t chunk = MIN(K230_DECOMP_GZIP_BLOCK_SIZE,
> + input_size - s->total_requested);
> +
> + if (!k230_decomp_gzip_load_input(s, k230_decomp_gzip_input_addr(s),
> + chunk)) {
> + k230_decomp_gzip_finish(s, false);
> + return;
> + }
> + s->total_requested += chunk;
> + s->input.slot = (s->input.slot + 1) % K230_DECOMP_GZIP_INPUT_SLOTS;
> + break;
> + }
> + case K230_DECOMP_GZIP_GPIO_DMA_READ_ACK:
> + if (s->output.current_offset == 0) {
> + k230_decomp_gzip_finish(s, false);
> + return;
> + }
> + s->output.slot = (s->output.slot + 1) % K230_DECOMP_GZIP_OUTPUT_SLOTS;
> + s->output.current_offset = 0;
> + break;
> + default:
> + return;
For all other read/write callbacks I see qemu_log_mask() calls to notice when something
unexpected happens, which is a good practice.
Shouldn't you do the same here? Seems like you're silently ignoring a foreign interrupt.
Might as well do a qemu_log_mask() here too.
Thanks,
Daniel
> + }
> +
> + k230_decomp_gzip_kick(s);
> +}
> +
> +static void k230_decomp_gzip_start(K230DecompGzipState *s)
> +{
> + uint32_t input_size = s->gzip_src_size & K230_DECOMP_GZIP_DMA_IN_MASK;
> +
> + k230_decomp_gzip_reset_stream(s);
> + s->decomp_stat &= ~K230_DECOMP_GZIP_STAT_CRC_OK;
> + s->total_requested = 0;
> + s->total_produced = 0;
> + s->stream_end = false;
> + memset(&s->input, 0, sizeof(s->input));
> + memset(&s->output, 0, sizeof(s->output));
> +
> + if (!(s->gzip_src_size & K230_DECOMP_GZIP_CTRL_EN) ||
> + input_size == 0 || s->gzip_out_size == 0) {
> + k230_decomp_gzip_finish(s, false);
> + return;
> + }
> +
> + s->active = true;
> + k230_decomp_gzip_update_ctrl_en(s);
> + k230_decomp_gzip_kick(s);
> +}
> +
> +static uint64_t k230_decomp_gzip_read(void *opaque, hwaddr offset,
> + unsigned size)
> +{
> + K230DecompGzipState *s = opaque;
> + uint64_t value = 0;
> +
> + switch (offset) {
> + case K230_DECOMP_GZIP_DECOMP_START:
> + value = s->decomp_start & ~K230_DECOMP_GZIP_START; /* start bit is write only */
> + break;
> + case K230_DECOMP_GZIP_GZIP_SRC_SIZE:
> + value = s->gzip_src_size;
> + break;
> + case K230_DECOMP_GZIP_GZIP_OUT_SIZE:
> + value = s->gzip_out_size;
> + break;
> + case K230_DECOMP_GZIP_DECOMP_STAT:
> + value = s->decomp_stat;
> + break;
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: bad read offset 0x%" HWADDR_PRIx "\n",
> + TYPE_K230_DECOMP_GZIP, offset);
> + break;
> + }
> +
> + trace_k230_decomp_gzip_read(offset, size, value);
> + return value;
> +}
> +
> +static void k230_decomp_gzip_write(void *opaque, hwaddr offset,
> + uint64_t value, unsigned size)
> +{
> + K230DecompGzipState *s = opaque;
> +
> + trace_k230_decomp_gzip_write(offset, size, value);
> +
> + switch (offset) {
> + case K230_DECOMP_GZIP_DECOMP_START:
> + s->decomp_start = value;
> + if (value & K230_DECOMP_GZIP_START) {
> + k230_decomp_gzip_start(s);
> + }
> + break;
> + case K230_DECOMP_GZIP_GZIP_SRC_SIZE:
> + s->gzip_src_size = value;
> + k230_decomp_gzip_update_ctrl_en(s);
> + break;
> + case K230_DECOMP_GZIP_GZIP_OUT_SIZE:
> + s->gzip_out_size = value;
> + break;
> + case K230_DECOMP_GZIP_DECOMP_STAT:
> + break;
> + default:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: bad write offset 0x%" HWADDR_PRIx "\n",
> + TYPE_K230_DECOMP_GZIP, offset);
> + break;
> + }
> +}
> +
> +static const MemoryRegionOps k230_decomp_gzip_ops = {
> + .read = k230_decomp_gzip_read,
> + .write = k230_decomp_gzip_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid.min_access_size = 4,
> + .valid.max_access_size = 4,
> + .impl.min_access_size = 4,
> + .impl.max_access_size = 4,
> +};
> +
> +static const VMStateDescription vmstate_k230_decomp_gzip_slot = {
> + .name = "k230.decomp-gzip.slot",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT32(slot, K230DecompGzipSlotState),
> + VMSTATE_UINT32(current_offset, K230DecompGzipSlotState),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +static const VMStateDescription vmstate_k230_decomp_gzip = {
> + .name = "k230.decomp-gzip",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT32(decomp_start, K230DecompGzipState),
> + VMSTATE_UINT32(gzip_src_size, K230DecompGzipState),
> + VMSTATE_UINT32(gzip_out_size, K230DecompGzipState),
> + VMSTATE_UINT32(decomp_stat, K230DecompGzipState),
> + VMSTATE_STRUCT(input, K230DecompGzipState, 1,
> + vmstate_k230_decomp_gzip_slot,
> + K230DecompGzipSlotState),
> + VMSTATE_STRUCT(output, K230DecompGzipState, 1,
> + vmstate_k230_decomp_gzip_slot,
> + K230DecompGzipSlotState),
> + VMSTATE_UINT32(total_requested, K230DecompGzipState),
> + VMSTATE_UINT32(total_produced, K230DecompGzipState),
> + VMSTATE_BOOL(active, K230DecompGzipState),
> + VMSTATE_BOOL(in_kick, K230DecompGzipState),
> + VMSTATE_BOOL(zstream_inited, K230DecompGzipState),
> + VMSTATE_BOOL(stream_end, K230DecompGzipState),
> + VMSTATE_UINT8_ARRAY(input_buf, K230DecompGzipState,
> + K230_DECOMP_GZIP_BLOCK_SIZE),
> + VMSTATE_UINT8_ARRAY(output_buf, K230DecompGzipState,
> + K230_DECOMP_GZIP_BLOCK_SIZE),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +static void k230_decomp_gzip_reset_hold(Object *obj, ResetType type)
> +{
> + K230DecompGzipState *s = K230_DECOMP_GZIP(obj);
> +
> + k230_decomp_gzip_reset_stream(s);
> + memset(&s->zs, 0, sizeof(s->zs));
> + s->decomp_start = 0;
> + s->gzip_src_size = 0;
> + s->gzip_out_size = 0;
> + s->decomp_stat = 0;
> + memset(&s->input, 0, sizeof(s->input));
> + memset(&s->output, 0, sizeof(s->output));
> + s->total_requested = 0;
> + s->total_produced = 0;
> + s->active = false;
> + s->in_kick = false;
> + s->stream_end = false;
> +}
> +
> +static void k230_decomp_gzip_realize(DeviceState *dev, Error **errp)
> +{
> + K230DecompGzipState *s = K230_DECOMP_GZIP(dev);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> + memory_region_init_io(&s->iomem, OBJECT(dev), &k230_decomp_gzip_ops, s,
> + TYPE_K230_DECOMP_GZIP,
> + K230_DECOMP_GZIP_MMIO_SIZE);
> + sysbus_init_mmio(sbd, &s->iomem);
> + qdev_init_gpio_in(dev, k230_decomp_gzip_handle_ack,
> + K230_DECOMP_GZIP_NUM_GPIOS_IN);
> + qdev_init_gpio_out(dev, s->signal_out,
> + K230_DECOMP_GZIP_NUM_GPIOS_OUT);
> +}
> +
> +static const Property k230_decomp_gzip_properties[] = {
> + DEFINE_PROP_UINT64("sram-base", K230DecompGzipState, sram_base, 0),
> +};
> +
> +static void k230_decomp_gzip_class_init(ObjectClass *oc, const void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + ResettableClass *rc = RESETTABLE_CLASS(oc);
> +
> + dc->realize = k230_decomp_gzip_realize;
> + rc->phases.hold = k230_decomp_gzip_reset_hold;
> + device_class_set_props(dc, k230_decomp_gzip_properties);
> + dc->vmsd = &vmstate_k230_decomp_gzip;
> + dc->desc = "Kendryte K230 GZIP decompression engine";
> +}
> +
> +static const TypeInfo k230_decomp_gzip_info = {
> + .name = TYPE_K230_DECOMP_GZIP,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(K230DecompGzipState),
> + .class_init = k230_decomp_gzip_class_init,
> +};
> +
> +static void k230_decomp_gzip_register_types(void)
> +{
> + type_register_static(&k230_decomp_gzip_info);
> +}
> +
> +type_init(k230_decomp_gzip_register_types)
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 23265f6035..6f6bf3c85c 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -36,6 +36,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
> system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
> system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
> system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
> +system_ss.add(when: 'CONFIG_K230_DECOMP_GZIP', if_true: files('k230_decomp_gzip.c'))
>
> subdir('macio')
>
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index c9a868b3ef..16db4ba0cc 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -442,3 +442,7 @@ iommu_testdev_dma_read(uint64_t gva, uint32_t len) "gva=0x%" PRIx64 " len=%u"
> iommu_testdev_dma_verify(uint32_t expected, uint32_t actual) "expected=0x%x actual=0x%x"
> iommu_testdev_dma_result(uint32_t result) "DMA completed result=0x%x"
> iommu_testdev_dma_armed(bool armed) "armed=%d"
> +
> +# k230_decomp_gzip.c
> +k230_decomp_gzip_read(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP read: [0x%"PRIx64"] size %u -> 0x%"PRIx64
> +k230_decomp_gzip_write(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP write: [0x%"PRIx64"] size %u <- 0x%"PRIx64
> diff --git a/include/hw/misc/k230_decomp_gzip.h b/include/hw/misc/k230_decomp_gzip.h
> new file mode 100644
> index 0000000000..9911af0095
> --- /dev/null
> +++ b/include/hw/misc/k230_decomp_gzip.h
> @@ -0,0 +1,92 @@
> +/*
> + * K230 Decompress Engine
> + *
> + * Copyright (c) 2026 Tao Ding <dingtao0430@163.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_MISC_K230_DECOMP_GZIP_H
> +#define HW_MISC_K230_DECOMP_GZIP_H
> +
> +#include <zlib.h>
> +#include "hw/core/sysbus.h"
> +
> +#define TYPE_K230_DECOMP_GZIP "riscv.k230.decomp-gzip"
> +OBJECT_DECLARE_SIMPLE_TYPE(K230DecompGzipState, K230_DECOMP_GZIP)
> +
> +/* K230 DECOMP GZIP ACK input */
> +enum {
> + K230_DECOMP_GZIP_GPIO_DMA_WRITE_ACK,
> + K230_DECOMP_GZIP_GPIO_DMA_READ_ACK,
> + K230_DECOMP_GZIP_NUM_GPIOS_IN,
> +};
> +
> +/* K230 DECOMP GZIP REQ output */
> +enum {
> + K230_DECOMP_GZIP_GPIO_DECOMP_CTRL_EN,
> + K230_DECOMP_GZIP_GPIO_DMA_WRITE_REQ,
> + K230_DECOMP_GZIP_GPIO_DMA_READ_REQ,
> + K230_DECOMP_GZIP_NUM_GPIOS_OUT,
> +};
> +
> +#define K230_DECOMP_GZIP_MMIO_SIZE 0x4000
> +
> +/* K230 DECOMP GZIP Registers map */
> +/* Start decompression controller */
> +#define K230_DECOMP_GZIP_DECOMP_START 0x00
> +/* Source data length register */
> +#define K230_DECOMP_GZIP_GZIP_SRC_SIZE 0x04
> +/* Output data length register */
> +#define K230_DECOMP_GZIP_GZIP_OUT_SIZE 0x08
> +/* Decompress status register */
> +#define K230_DECOMP_GZIP_DECOMP_STAT 0x0c
> +
> +/* Start decompression controller */
> +#define K230_DECOMP_GZIP_START (1U << 0)
> +
> +#define K230_DECOMP_GZIP_CTRL_EN (1U << 31)
> +#define K230_DECOMP_GZIP_DMA_IN_MASK 0x7fffffffU
> +
> +#define K230_DECOMP_GZIP_STAT_CRC_OK (1U << 10)
> +#define K230_DECOMP_GZIP_STAT_STATE_MASK 0xfU
> +
> +#define K230_DECOMP_GZIP_BLOCK_SIZE 0x00020000
> +#define K230_DECOMP_GZIP_SRAM_IN_BASE 0x80000
> +#define K230_DECOMP_GZIP_SRAM_OUT_BASE 0
> +
> +typedef struct K230DecompGzipSlotState {
> + uint32_t slot; /* Slot index */
> + /*
> + * Data offset in current slot.
> + * First valid data in input buffer. Last valid data in output buffer.
> + */
> + uint32_t current_offset;
> +} K230DecompGzipSlotState;
> +
> +struct K230DecompGzipState {
> + SysBusDevice parent_obj;
> +
> + MemoryRegion iomem;
> + hwaddr sram_base;
> + qemu_irq signal_out[K230_DECOMP_GZIP_NUM_GPIOS_OUT];
> + uint32_t decomp_start;
> + uint32_t gzip_src_size;
> + uint32_t gzip_out_size;
> + uint32_t decomp_stat;
> + K230DecompGzipSlotState input; /* decomp gzip ring input */
> + K230DecompGzipSlotState output; /* decomp gzip ring output */
> + uint32_t total_requested;
> + uint32_t total_produced;
> + bool active;
> + bool in_kick;
> + bool zstream_inited;
> + bool stream_end;
> + /* Read from ring input. */
> + uint8_t input_buf[K230_DECOMP_GZIP_BLOCK_SIZE];
> + /* Write to ring output. */
> + uint8_t output_buf[K230_DECOMP_GZIP_BLOCK_SIZE];
> + z_stream zs;
> +};
> +
> +#endif
next prev parent reply other threads:[~2026-08-06 11:48 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 15:56 [PATCH v2 0/7] K230: add gsdma and decomp_gzip Tao Ding
2026-07-27 15:56 ` [PATCH v2 1/7] hw/dma: add K230 gsdma Tao Ding
2026-08-06 11:34 ` Daniel Henrique Barboza
2026-08-07 4:46 ` Chao Liu
2026-07-27 15:56 ` [PATCH v2 2/7] hw/riscv: k230: add gsdma in K230 board Tao Ding
2026-08-06 11:34 ` Daniel Henrique Barboza
2026-07-27 15:56 ` [PATCH v2 3/7] tests/qtest: add test for K230 gsdma Tao Ding
2026-08-06 11:36 ` Daniel Henrique Barboza
2026-07-27 15:56 ` [PATCH v2 4/7] hw/misc: add K230 decomp gzip Tao Ding
2026-08-06 11:47 ` Daniel Henrique Barboza [this message]
2026-07-27 15:57 ` [PATCH v2 5/7] hw/riscv: k230: add decomp gzip in K230 board Tao Ding
2026-08-06 11:48 ` Daniel Henrique Barboza
2026-07-27 15:57 ` [PATCH v2 6/7] tests/qtest: add test for K230 decomp gzip Tao Ding
2026-08-06 12:14 ` Daniel Henrique Barboza
2026-07-27 15:57 ` [PATCH v2 7/7] hw/riscv: k230: add a noc stub region in K230 board Tao Ding
2026-08-06 12:15 ` Daniel Henrique Barboza
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=083ce420-ca09-4968-b284-e161ba781561@oss.qualcomm.com \
--to=daniel.barboza@oss.qualcomm.com \
--cc=alistair.francis@wdc.com \
--cc=caojunze424@gmail.com \
--cc=chao.liu@processmission.com \
--cc=dingtao0430@163.com \
--cc=farosas@suse.de \
--cc=liwei1518@gmail.com \
--cc=lvivier@redhat.com \
--cc=palmer@dabbelt.com \
--cc=pbonzini@redhat.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
--cc=zhiwei_liu@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.