Files
QEMU-S5L8950X/hw/riscv/aia.c
T
Yaya48 cf256aa081 Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
2026-08-31 02:15:30 +02:00

95 lines
3.2 KiB
C

/*
* QEMU RISC-V Advanced Interrupt Architecture (AIA)
*
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "system/kvm.h"
#include "hw/intc/riscv_aplic.h"
#include "hw/intc/riscv_imsic.h"
#include "aia.h"
uint32_t imsic_num_bits(uint32_t count)
{
uint32_t ret = 0;
while (BIT(ret) < count) {
ret++;
}
return ret;
}
DeviceState *riscv_create_aia(bool msimode, int aia_guests,
uint32_t m_imsic_stride,
uint16_t num_sources,
const MemMapEntry *aplic_m,
const MemMapEntry *aplic_s,
const MemMapEntry *imsic_m,
const MemMapEntry *imsic_s,
int socket, int base_hartid, int hart_count,
uint32_t num_msis, uint32_t num_prio_bits)
{
int i;
hwaddr addr = 0;
uint32_t guest_bits;
DeviceState *aplic_s_dev = NULL;
DeviceState *aplic_m_dev = NULL;
/* The RISC-V Advanced Interrupt Architecture, Chapter 1.2. Limits */
g_assert(num_sources <= 1023);
if (msimode) {
if (!kvm_enabled()) {
/* Per-socket M-level IMSICs */
addr = imsic_m->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
for (i = 0; i < hart_count; i++) {
riscv_imsic_create(addr + i * m_imsic_stride,
base_hartid + i, true, 1,
num_msis);
}
}
/* Per-socket S-level IMSICs */
guest_bits = imsic_num_bits(aia_guests + 1);
addr = imsic_s->base + socket * (1U << IMSIC_MMIO_GROUP_MIN_SHIFT);
for (i = 0; i < hart_count; i++) {
riscv_imsic_create(addr + i * IMSIC_HART_SIZE(guest_bits),
base_hartid + i, false, 1 + aia_guests,
num_msis);
}
}
if (!kvm_enabled()) {
/* Per-socket M-level APLIC */
aplic_m_dev = riscv_aplic_create(aplic_m->base +
socket * aplic_m->size,
aplic_m->size,
(msimode) ? 0 : base_hartid,
(msimode) ? 0 : hart_count,
num_sources,
num_prio_bits,
msimode, true, NULL);
}
/* Per-socket S-level APLIC */
aplic_s_dev = riscv_aplic_create(aplic_s->base +
socket * aplic_s->size,
aplic_s->size,
(msimode) ? 0 : base_hartid,
(msimode) ? 0 : hart_count,
num_sources,
num_prio_bits,
msimode, false, aplic_m_dev);
if (kvm_enabled() && msimode) {
riscv_aplic_set_kvm_msicfgaddr(RISCV_APLIC(aplic_s_dev), addr);
}
return kvm_enabled() ? aplic_s_dev : aplic_m_dev;
}