On 6/2/25 02:30, Hao Wu wrote:
> The NPCM8xx GCR device can be accessed with 64-bit memory operations.
> This patch supports that.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Hao Wu <wuhaotsh@google.com>
> ---
> hw/misc/npcm_gcr.c | 94 +++++++++++++++++++++++++++++++++-----------
> hw/misc/trace-events | 4 +-
> 2 files changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/hw/misc/npcm_gcr.c b/hw/misc/npcm_gcr.c
> index 820b730606..654e048048 100644
> --- a/hw/misc/npcm_gcr.c
> +++ b/hw/misc/npcm_gcr.c
> @@ -201,6 +201,7 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size)
> uint32_t reg = offset / sizeof(uint32_t);
> NPCMGCRState *s = opaque;
> NPCMGCRClass *c = NPCM_GCR_GET_CLASS(s);
> + uint64_t value;
>
> if (reg >= c->nr_regs) {
> qemu_log_mask(LOG_GUEST_ERROR,
> @@ -209,9 +210,21 @@ static uint64_t npcm_gcr_read(void *opaque, hwaddr offset, unsigned size)
> return 0;
> }
>
> - trace_npcm_gcr_read(offset, s->regs[reg]);
> + switch (size) {
> + case 4:
> + value = s->regs[reg];
> + break;
> +
> + case 8:
Should we assert(!(reg & 1)) in case someone want to enable unaligned
accesses?
> + value = deposit64(s->regs[reg], 32, 32, s->regs[reg + 1]);
> + break;
> +
> + default:
> + g_assert_not_reached();
> + }
>
> - return s->regs[reg];
> + trace_npcm_gcr_read(offset, value);
> + return value;
> }
>
> static void npcm_gcr_write(void *opaque, hwaddr offset,
> @@ -231,29 +244,65 @@ static void npcm_gcr_write(void *opaque, hwaddr offset,
> return;
> }
>
> - switch (reg) {
> - case NPCM7XX_GCR_PDID:
> - case NPCM7XX_GCR_PWRON:
> - case NPCM7XX_GCR_INTSR:
> - qemu_log_mask(LOG_GUEST_ERROR,
> - "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
> - __func__, offset);
> - return;
> -
> - case NPCM7XX_GCR_RESSR:
> - case NPCM7XX_GCR_CP2BST:
> - /* Write 1 to clear */
> - value = s->regs[reg] & ~value;
> + switch (size) {
> + case 4:
> + switch (reg) {
> + case NPCM7XX_GCR_PDID:
> + case NPCM7XX_GCR_PWRON:
> + case NPCM7XX_GCR_INTSR:
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
> + __func__, offset);
> + return;
> +
> + case NPCM7XX_GCR_RESSR:
> + case NPCM7XX_GCR_CP2BST:
> + /* Write 1 to clear */
> + value = s->regs[reg] & ~value;
> + break;
> +
> + case NPCM7XX_GCR_RLOCKR1:
> + case NPCM7XX_GCR_MDLR:
> + /* Write 1 to set */
> + value |= s->regs[reg];
> + break;
> + };
> + s->regs[reg] = value;
> break;
>
> - case NPCM7XX_GCR_RLOCKR1:
> - case NPCM7XX_GCR_MDLR:
> - /* Write 1 to set */
> - value |= s->regs[reg];
> + case 8:
Ditto.
> + s->regs[reg] = value;
> + s->regs[reg + 1] = extract64(v, 32, 32);
> break;
> - };
>
> - s->regs[reg] = value;
> + default:
> + g_assert_not_reached();
> + }
> +}
> +
> +static bool npcm_gcr_check_mem_op(void *opaque, hwaddr offset,
> + unsigned size, bool is_write,
> + MemTxAttrs attrs)
> +{
> + NPCMGCRClass *c = NPCM_GCR_GET_CLASS(opaque);
> +
> + if (offset >= c->nr_regs * sizeof(uint32_t)) {
> + return false;
> + }
> +
> + switch (size) {
> + case 4:
> + return true;
> + case 8:
> + if (offset >= NPCM8XX_GCR_SCRPAD_00 * sizeof(uint32_t) &&
> + offset < (NPCM8XX_GCR_NR_REGS - 1) * sizeof(uint32_t)) {
> + return true;
> + } else {
> + return false;
> + }
> + default:
> + return false;
> + }
> }
>
> static const struct MemoryRegionOps npcm_gcr_ops = {
> @@ -262,7 +311,8 @@ static const struct MemoryRegionOps npcm_gcr_ops = {
> .endianness = DEVICE_LITTLE_ENDIAN,
> .valid = {
> .min_access_size = 4,
> - .max_access_size = 4,
> + .max_access_size = 8,
> + .accepts = npcm_gcr_check_mem_op,
> .unaligned = false,
> },
> };
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index 0f7204a237..f25dbd6030 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -135,8 +135,8 @@ npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " valu
> npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
>
> # npcm_gcr.c
> -npcm_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
> -npcm_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
> +npcm_gcr_read(uint64_t offset, uint64_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx64
> +npcm_gcr_write(uint64_t offset, uint64_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx64
>
> # npcm7xx_mft.c
> npcm7xx_mft_read(const char *name, uint64_t offset, uint16_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx16