mirror of https://github.com/xemu-project/xemu.git
target-arm queue:
* Add dummy Aspeed AST2600 Display Port MCU (DPMCU) * Add missing FEAT_TLBIOS instructions * arm_gicv3_its: Various bug fixes and cleanups * kudo-bmc: Add more devices -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmHYdlgZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3jCrEACrXQDOaSCDU0qVaGbrmjj8 17tHLxSFY9OGBxnXPC+urWVZGGnKm8bcZe/QDzvKuZXRPvrc9yT4GFV3ebulxy8g CEHW/pZRKKzmPigzlED5q8ytYuu+hzH0a9WZu9T967UQnJJYujbDWM74gkCbJNUD Bj/B0CJpkjhdmWhTChwuIz6BNDKCyU1AEyUnfb32ySUqumU2z6Z4BsiW47/SLXtz dPQcLNvx8bVIWUmrrtRvkirKVpAdMArsgQ/IzsD3cM4eDixEnyTJQ5TaF8h1pCVb PcedZeYfEjF26jOcfafbygzqv0H6BPZ+56vNRWvuK78UMJW/RiixBPtuJ9Ftcg78 ceJ8z0xegl9bG2Qmy/niWPeF6l9C0OlS/UHNsXv7d/N4F/0nCayDFuTLphMpmuWl w17ROiUQe5ZnQQKGTagbdHM3TUtLZmoLoKjEO/PUfbWB0nPWNiEdvtFQ6uEUDtuD SkstFoSSgypgRqbn5hbPgMo3YrNfS7YT93o0/18OZ/oe3RFaJc3UShjOnzGa7Dof 2YlMTXh1Oo4K7JVZwWd06vcBvkVmYi5WclMYDNvAO6AzNtGcVhpyuRMzYwnSfPeN Arq825950QBDoBDNY0uE8E09l9OyqNtwo4UQa1Vx1gV13tiRfEEzyxGInyVMIPe7 zLeODsU/9POGJGZqOwK2gg== =wPug -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20220107' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * Add dummy Aspeed AST2600 Display Port MCU (DPMCU) * Add missing FEAT_TLBIOS instructions * arm_gicv3_its: Various bug fixes and cleanups * kudo-bmc: Add more devices # gpg: Signature made Fri 07 Jan 2022 09:20:24 AM PST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] * tag 'pull-target-arm-20220107' of https://git.linaro.org/people/pmaydell/qemu-arm: hw/arm: kudo add lm75s on bus 13 hw/arm: add i2c muxes to kudo-bmc hw/arm: attach MMC to kudo-bmc hw/arm: Add kudo i2c eeproms. hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries hw/intc/arm_gicv3_its: Fix various off-by-one errors hw/intc/arm_gicv3_its: Use FIELD macros for CTEs hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size hw/intc/arm_gicv3_its: Use FIELD macros for DTEs hw/intc/arm_gicv3_its: Correct handling of MAPI hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop hw/intc/arm_gicv3_its: Remove maxids union from TableDesc hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase target/arm: Add missing FEAT_TLBIOS instructions Add dummy Aspeed AST2600 Display Port MCU (DPMCU) Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
c87507a8cf
|
@ -19,9 +19,11 @@
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
|
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
|
||||||
|
#define ASPEED_SOC_DPMCU_SIZE 0x00040000
|
||||||
|
|
||||||
static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
||||||
[ASPEED_DEV_SRAM] = 0x10000000,
|
[ASPEED_DEV_SRAM] = 0x10000000,
|
||||||
|
[ASPEED_DEV_DPMCU] = 0x18000000,
|
||||||
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
|
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
|
||||||
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
[ASPEED_DEV_IOMEM] = 0x1E600000,
|
||||||
[ASPEED_DEV_PWM] = 0x1E610000,
|
[ASPEED_DEV_PWM] = 0x1E610000,
|
||||||
|
@ -44,6 +46,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
||||||
[ASPEED_DEV_SCU] = 0x1E6E2000,
|
[ASPEED_DEV_SCU] = 0x1E6E2000,
|
||||||
[ASPEED_DEV_XDMA] = 0x1E6E7000,
|
[ASPEED_DEV_XDMA] = 0x1E6E7000,
|
||||||
[ASPEED_DEV_ADC] = 0x1E6E9000,
|
[ASPEED_DEV_ADC] = 0x1E6E9000,
|
||||||
|
[ASPEED_DEV_DP] = 0x1E6EB000,
|
||||||
[ASPEED_DEV_VIDEO] = 0x1E700000,
|
[ASPEED_DEV_VIDEO] = 0x1E700000,
|
||||||
[ASPEED_DEV_SDHCI] = 0x1E740000,
|
[ASPEED_DEV_SDHCI] = 0x1E740000,
|
||||||
[ASPEED_DEV_EMMC] = 0x1E750000,
|
[ASPEED_DEV_EMMC] = 0x1E750000,
|
||||||
|
@ -104,6 +107,7 @@ static const int aspeed_soc_ast2600_irqmap[] = {
|
||||||
[ASPEED_DEV_ETH3] = 32,
|
[ASPEED_DEV_ETH3] = 32,
|
||||||
[ASPEED_DEV_ETH4] = 33,
|
[ASPEED_DEV_ETH4] = 33,
|
||||||
[ASPEED_DEV_KCS] = 138, /* 138 -> 142 */
|
[ASPEED_DEV_KCS] = 138, /* 138 -> 142 */
|
||||||
|
[ASPEED_DEV_DP] = 62,
|
||||||
};
|
};
|
||||||
|
|
||||||
static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl)
|
static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl)
|
||||||
|
@ -298,6 +302,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
||||||
memory_region_add_subregion(get_system_memory(),
|
memory_region_add_subregion(get_system_memory(),
|
||||||
sc->memmap[ASPEED_DEV_SRAM], &s->sram);
|
sc->memmap[ASPEED_DEV_SRAM], &s->sram);
|
||||||
|
|
||||||
|
/* DPMCU */
|
||||||
|
create_unimplemented_device("aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU],
|
||||||
|
ASPEED_SOC_DPMCU_SIZE);
|
||||||
|
|
||||||
/* SCU */
|
/* SCU */
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
|
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -328,6 +328,31 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kudo_bmc_i2c_init(NPCM7xxState *soc)
|
||||||
|
{
|
||||||
|
I2CSlave *i2c_mux;
|
||||||
|
|
||||||
|
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75);
|
||||||
|
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77);
|
||||||
|
|
||||||
|
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77);
|
||||||
|
|
||||||
|
at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */
|
||||||
|
|
||||||
|
i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13),
|
||||||
|
TYPE_PCA9548, 0x77);
|
||||||
|
|
||||||
|
/* tmp105 is compatible with the lm75 */
|
||||||
|
i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x48);
|
||||||
|
i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 3), "tmp105", 0x49);
|
||||||
|
i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48);
|
||||||
|
i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49);
|
||||||
|
|
||||||
|
at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */
|
||||||
|
|
||||||
|
/* TODO: Add remaining i2c devices. */
|
||||||
|
}
|
||||||
|
|
||||||
static void npcm750_evb_init(MachineState *machine)
|
static void npcm750_evb_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
NPCM7xxState *soc;
|
NPCM7xxState *soc;
|
||||||
|
@ -391,6 +416,8 @@ static void kudo_bmc_init(MachineState *machine)
|
||||||
npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
|
npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
|
||||||
drive_get(IF_MTD, 3, 0));
|
drive_get(IF_MTD, 3, 0));
|
||||||
|
|
||||||
|
kudo_bmc_i2c_init(soc);
|
||||||
|
sdhci_attach_drive(&soc->mmc.sdhci, 0);
|
||||||
npcm7xx_load_kernel(machine, soc);
|
npcm7xx_load_kernel(machine, soc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
bool valid_l2t;
|
bool valid_l2t;
|
||||||
uint32_t l2t_id;
|
uint32_t l2t_id;
|
||||||
uint32_t max_l2_entries;
|
uint32_t num_l2_entries;
|
||||||
|
|
||||||
if (s->ct.indirect) {
|
if (s->ct.indirect) {
|
||||||
l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
|
l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
|
||||||
|
@ -88,12 +88,12 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
|
||||||
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
||||||
|
|
||||||
if (valid_l2t) {
|
if (valid_l2t) {
|
||||||
max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
|
num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
|
||||||
|
|
||||||
l2t_addr = value & ((1ULL << 51) - 1);
|
l2t_addr = value & ((1ULL << 51) - 1);
|
||||||
|
|
||||||
*cte = address_space_ldq_le(as, l2t_addr +
|
*cte = address_space_ldq_le(as, l2t_addr +
|
||||||
((icid % max_l2_entries) * GITS_CTE_SIZE),
|
((icid % num_l2_entries) * GITS_CTE_SIZE),
|
||||||
MEMTXATTRS_UNSPECIFIED, res);
|
MEMTXATTRS_UNSPECIFIED, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
|
||||||
MEMTXATTRS_UNSPECIFIED, res);
|
MEMTXATTRS_UNSPECIFIED, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
|
return FIELD_EX64(*cte, CTE, VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
|
static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
|
||||||
|
@ -114,7 +114,7 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
|
||||||
uint64_t itt_addr;
|
uint64_t itt_addr;
|
||||||
MemTxResult res = MEMTX_OK;
|
MemTxResult res = MEMTX_OK;
|
||||||
|
|
||||||
itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
|
itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
|
||||||
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
|
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
|
||||||
|
|
||||||
address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
|
address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
|
||||||
|
@ -141,7 +141,7 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
|
||||||
bool status = false;
|
bool status = false;
|
||||||
IteEntry ite = {};
|
IteEntry ite = {};
|
||||||
|
|
||||||
itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
|
itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
|
||||||
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
|
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
|
||||||
|
|
||||||
ite.itel = address_space_ldq_le(as, itt_addr +
|
ite.itel = address_space_ldq_le(as, itt_addr +
|
||||||
|
@ -156,12 +156,11 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
|
||||||
MEMTXATTRS_UNSPECIFIED, res);
|
MEMTXATTRS_UNSPECIFIED, res);
|
||||||
|
|
||||||
if (*res == MEMTX_OK) {
|
if (*res == MEMTX_OK) {
|
||||||
if (ite.itel & TABLE_ENTRY_VALID_MASK) {
|
if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
|
||||||
if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
|
int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
|
||||||
GITS_TYPE_PHYSICAL) {
|
if (inttype == ITE_INTTYPE_PHYSICAL) {
|
||||||
*pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
|
*pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
|
||||||
ITE_ENTRY_INTID_SHIFT;
|
*icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
|
||||||
*icid = ite.iteh & ITE_ENTRY_ICID_MASK;
|
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +176,7 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
bool valid_l2t;
|
bool valid_l2t;
|
||||||
uint32_t l2t_id;
|
uint32_t l2t_id;
|
||||||
uint32_t max_l2_entries;
|
uint32_t num_l2_entries;
|
||||||
|
|
||||||
if (s->dt.indirect) {
|
if (s->dt.indirect) {
|
||||||
l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
|
l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
|
||||||
|
@ -191,12 +190,12 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
|
||||||
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
||||||
|
|
||||||
if (valid_l2t) {
|
if (valid_l2t) {
|
||||||
max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
|
num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
|
||||||
|
|
||||||
l2t_addr = value & ((1ULL << 51) - 1);
|
l2t_addr = value & ((1ULL << 51) - 1);
|
||||||
|
|
||||||
value = address_space_ldq_le(as, l2t_addr +
|
value = address_space_ldq_le(as, l2t_addr +
|
||||||
((devid % max_l2_entries) * GITS_DTE_SIZE),
|
((devid % num_l2_entries) * GITS_DTE_SIZE),
|
||||||
MEMTXATTRS_UNSPECIFIED, res);
|
MEMTXATTRS_UNSPECIFIED, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,10 +255,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
if (res != MEMTX_OK) {
|
if (res != MEMTX_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
dte_valid = dte & TABLE_ENTRY_VALID_MASK;
|
dte_valid = FIELD_EX64(dte, DTE, VALID);
|
||||||
|
|
||||||
if (dte_valid) {
|
if (dte_valid) {
|
||||||
max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
|
max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
|
||||||
|
|
||||||
ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
|
ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
|
||||||
|
|
||||||
|
@ -287,10 +286,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
* In this implementation, in case of guest errors we ignore the
|
* In this implementation, in case of guest errors we ignore the
|
||||||
* command and move onto the next command in the queue.
|
* command and move onto the next command in the queue.
|
||||||
*/
|
*/
|
||||||
if (devid > s->dt.maxids.max_devids) {
|
if (devid >= s->dt.num_ids) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: invalid command attributes: devid %d>%d",
|
"%s: invalid command attributes: devid %d>=%d",
|
||||||
__func__, devid, s->dt.maxids.max_devids);
|
__func__, devid, s->dt.num_ids);
|
||||||
|
|
||||||
} else if (!dte_valid || !ite_valid || !cte_valid) {
|
} else if (!dte_valid || !ite_valid || !cte_valid) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
@ -309,9 +308,9 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
* Current implementation only supports rdbase == procnum
|
* Current implementation only supports rdbase == procnum
|
||||||
* Hence rdbase physical address is ignored
|
* Hence rdbase physical address is ignored
|
||||||
*/
|
*/
|
||||||
rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
|
rdbase = FIELD_EX64(cte, CTE, RDBASE);
|
||||||
|
|
||||||
if (rdbase > s->gicv3->num_cpu) {
|
if (rdbase >= s->gicv3->num_cpu) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,8 +341,6 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
MemTxResult res = MEMTX_OK;
|
MemTxResult res = MEMTX_OK;
|
||||||
uint16_t icid = 0;
|
uint16_t icid = 0;
|
||||||
uint64_t dte = 0;
|
uint64_t dte = 0;
|
||||||
IteEntry ite;
|
|
||||||
uint32_t int_spurious = INTID_SPURIOUS;
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
|
devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
|
||||||
|
@ -357,7 +354,9 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
|
|
||||||
eventid = (value & EVENTID_MASK);
|
eventid = (value & EVENTID_MASK);
|
||||||
|
|
||||||
if (!ignore_pInt) {
|
if (ignore_pInt) {
|
||||||
|
pIntid = eventid;
|
||||||
|
} else {
|
||||||
pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
|
pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,18 +375,14 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
if (res != MEMTX_OK) {
|
if (res != MEMTX_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
dte_valid = dte & TABLE_ENTRY_VALID_MASK;
|
dte_valid = FIELD_EX64(dte, DTE, VALID);
|
||||||
|
max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
|
||||||
|
max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
|
||||||
|
|
||||||
max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
|
if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids)
|
||||||
|
|
||||||
if (!ignore_pInt) {
|
|
||||||
max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
|
|
||||||
|| !dte_valid || (eventid > max_eventid) ||
|
|| !dte_valid || (eventid > max_eventid) ||
|
||||||
(!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
|
(((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
|
||||||
(pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
|
(pIntid != INTID_SPURIOUS))) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: invalid command attributes "
|
"%s: invalid command attributes "
|
||||||
"devid %d or icid %d or eventid %d or pIntid %d or"
|
"devid %d or icid %d or eventid %d or pIntid %d or"
|
||||||
|
@ -400,16 +395,12 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
/* add ite entry to interrupt translation table */
|
/* add ite entry to interrupt translation table */
|
||||||
ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
|
IteEntry ite = {};
|
||||||
(GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
|
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
|
||||||
|
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
|
||||||
if (ignore_pInt) {
|
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
|
||||||
ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
|
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
|
||||||
} else {
|
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
|
||||||
ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
|
|
||||||
}
|
|
||||||
ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
|
|
||||||
ite.iteh = icid;
|
|
||||||
|
|
||||||
result = update_ite(s, eventid, dte, ite);
|
result = update_ite(s, eventid, dte, ite);
|
||||||
}
|
}
|
||||||
|
@ -425,7 +416,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
|
||||||
uint64_t l2t_addr;
|
uint64_t l2t_addr;
|
||||||
bool valid_l2t;
|
bool valid_l2t;
|
||||||
uint32_t l2t_id;
|
uint32_t l2t_id;
|
||||||
uint32_t max_l2_entries;
|
uint32_t num_l2_entries;
|
||||||
uint64_t cte = 0;
|
uint64_t cte = 0;
|
||||||
MemTxResult res = MEMTX_OK;
|
MemTxResult res = MEMTX_OK;
|
||||||
|
|
||||||
|
@ -435,7 +426,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
/* add mapping entry to collection table */
|
/* add mapping entry to collection table */
|
||||||
cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
|
cte = FIELD_DP64(cte, CTE, VALID, 1);
|
||||||
|
cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -458,12 +450,12 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
|
||||||
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
||||||
|
|
||||||
if (valid_l2t) {
|
if (valid_l2t) {
|
||||||
max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
|
num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
|
||||||
|
|
||||||
l2t_addr = value & ((1ULL << 51) - 1);
|
l2t_addr = value & ((1ULL << 51) - 1);
|
||||||
|
|
||||||
address_space_stq_le(as, l2t_addr +
|
address_space_stq_le(as, l2t_addr +
|
||||||
((icid % max_l2_entries) * GITS_CTE_SIZE),
|
((icid % num_l2_entries) * GITS_CTE_SIZE),
|
||||||
cte, MEMTXATTRS_UNSPECIFIED, &res);
|
cte, MEMTXATTRS_UNSPECIFIED, &res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -505,7 +497,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
|
||||||
|
|
||||||
valid = (value & CMD_FIELD_VALID_MASK);
|
valid = (value & CMD_FIELD_VALID_MASK);
|
||||||
|
|
||||||
if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
|
if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"ITS MAPC: invalid collection table attributes "
|
"ITS MAPC: invalid collection table attributes "
|
||||||
"icid %d rdbase %" PRIu64 "\n", icid, rdbase);
|
"icid %d rdbase %" PRIu64 "\n", icid, rdbase);
|
||||||
|
@ -529,16 +521,16 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
|
||||||
uint64_t l2t_addr;
|
uint64_t l2t_addr;
|
||||||
bool valid_l2t;
|
bool valid_l2t;
|
||||||
uint32_t l2t_id;
|
uint32_t l2t_id;
|
||||||
uint32_t max_l2_entries;
|
uint32_t num_l2_entries;
|
||||||
uint64_t dte = 0;
|
uint64_t dte = 0;
|
||||||
MemTxResult res = MEMTX_OK;
|
MemTxResult res = MEMTX_OK;
|
||||||
|
|
||||||
if (s->dt.valid) {
|
if (s->dt.valid) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
/* add mapping entry to device table */
|
/* add mapping entry to device table */
|
||||||
dte = (valid & TABLE_ENTRY_VALID_MASK) |
|
dte = FIELD_DP64(dte, DTE, VALID, 1);
|
||||||
((size & SIZE_MASK) << 1U) |
|
dte = FIELD_DP64(dte, DTE, SIZE, size);
|
||||||
(itt_addr << GITS_DTE_ITTADDR_SHIFT);
|
dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -564,12 +556,12 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
|
||||||
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
|
||||||
|
|
||||||
if (valid_l2t) {
|
if (valid_l2t) {
|
||||||
max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
|
num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
|
||||||
|
|
||||||
l2t_addr = value & ((1ULL << 51) - 1);
|
l2t_addr = value & ((1ULL << 51) - 1);
|
||||||
|
|
||||||
address_space_stq_le(as, l2t_addr +
|
address_space_stq_le(as, l2t_addr +
|
||||||
((devid % max_l2_entries) * GITS_DTE_SIZE),
|
((devid % num_l2_entries) * GITS_DTE_SIZE),
|
||||||
dte, MEMTXATTRS_UNSPECIFIED, &res);
|
dte, MEMTXATTRS_UNSPECIFIED, &res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -618,7 +610,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
|
||||||
|
|
||||||
valid = (value & CMD_FIELD_VALID_MASK);
|
valid = (value & CMD_FIELD_VALID_MASK);
|
||||||
|
|
||||||
if ((devid > s->dt.maxids.max_devids) ||
|
if ((devid >= s->dt.num_ids) ||
|
||||||
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
|
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"ITS MAPD: invalid device table attributes "
|
"ITS MAPD: invalid device table attributes "
|
||||||
|
@ -651,13 +643,13 @@ static void process_cmdq(GICv3ITSState *s)
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
|
wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
|
||||||
|
|
||||||
if (wr_offset > s->cq.max_entries) {
|
if (wr_offset >= s->cq.num_entries) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: invalid write offset "
|
"%s: invalid write offset "
|
||||||
"%d\n", __func__, wr_offset);
|
"%d\n", __func__, wr_offset);
|
||||||
|
@ -666,7 +658,7 @@ static void process_cmdq(GICv3ITSState *s)
|
||||||
|
|
||||||
rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
|
rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
|
||||||
|
|
||||||
if (rd_offset > s->cq.max_entries) {
|
if (rd_offset >= s->cq.num_entries) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: invalid read offset "
|
"%s: invalid read offset "
|
||||||
"%d\n", __func__, rd_offset);
|
"%d\n", __func__, rd_offset);
|
||||||
|
@ -729,7 +721,7 @@ static void process_cmdq(GICv3ITSState *s)
|
||||||
}
|
}
|
||||||
if (result) {
|
if (result) {
|
||||||
rd_offset++;
|
rd_offset++;
|
||||||
rd_offset %= s->cq.max_entries;
|
rd_offset %= s->cq.num_entries;
|
||||||
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
|
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
@ -758,6 +750,9 @@ static void extract_table_params(GICv3ITSState *s)
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
|
TableDesc *td;
|
||||||
|
int idbits;
|
||||||
|
|
||||||
value = s->baser[i];
|
value = s->baser[i];
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
@ -789,73 +784,53 @@ static void extract_table_params(GICv3ITSState *s)
|
||||||
type = FIELD_EX64(value, GITS_BASER, TYPE);
|
type = FIELD_EX64(value, GITS_BASER, TYPE);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case GITS_BASER_TYPE_DEVICE:
|
case GITS_BASER_TYPE_DEVICE:
|
||||||
memset(&s->dt, 0 , sizeof(s->dt));
|
td = &s->dt;
|
||||||
s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
|
idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
|
||||||
|
|
||||||
if (!s->dt.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->dt.page_sz = page_sz;
|
|
||||||
s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
|
|
||||||
s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
|
|
||||||
|
|
||||||
if (!s->dt.indirect) {
|
|
||||||
s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
|
|
||||||
} else {
|
|
||||||
s->dt.max_entries = (((num_pages * page_sz) /
|
|
||||||
L1TABLE_ENTRY_SIZE) *
|
|
||||||
(page_sz / s->dt.entry_sz));
|
|
||||||
}
|
|
||||||
|
|
||||||
s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
|
|
||||||
DEVBITS) + 1));
|
|
||||||
|
|
||||||
s->dt.base_addr = baser_base_addr(value, page_sz);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GITS_BASER_TYPE_COLLECTION:
|
case GITS_BASER_TYPE_COLLECTION:
|
||||||
memset(&s->ct, 0 , sizeof(s->ct));
|
td = &s->ct;
|
||||||
s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GITS_TYPER.HCC is 0 for this implementation
|
|
||||||
* hence writes are discarded if ct.valid is 0
|
|
||||||
*/
|
|
||||||
if (!s->ct.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->ct.page_sz = page_sz;
|
|
||||||
s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
|
|
||||||
s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
|
|
||||||
|
|
||||||
if (!s->ct.indirect) {
|
|
||||||
s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
|
|
||||||
} else {
|
|
||||||
s->ct.max_entries = (((num_pages * page_sz) /
|
|
||||||
L1TABLE_ENTRY_SIZE) *
|
|
||||||
(page_sz / s->ct.entry_sz));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
|
if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
|
||||||
s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
|
idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
|
||||||
GITS_TYPER, CIDBITS) + 1));
|
|
||||||
} else {
|
} else {
|
||||||
/* 16-bit CollectionId supported when CIL == 0 */
|
/* 16-bit CollectionId supported when CIL == 0 */
|
||||||
s->ct.maxids.max_collids = (1UL << 16);
|
idbits = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->ct.base_addr = baser_base_addr(value, page_sz);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
/*
|
||||||
|
* GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
|
||||||
|
* ensures we will only see type values corresponding to
|
||||||
|
* the values set up in gicv3_its_reset().
|
||||||
|
*/
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(td, 0, sizeof(*td));
|
||||||
|
td->valid = FIELD_EX64(value, GITS_BASER, VALID);
|
||||||
|
/*
|
||||||
|
* If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
|
||||||
|
* interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
|
||||||
|
* do not have a special case where the GITS_BASER<n>.Valid bit is 0
|
||||||
|
* for the register corresponding to the Collection table but we
|
||||||
|
* still have to process interrupts using non-memory-backed
|
||||||
|
* Collection table entries.)
|
||||||
|
*/
|
||||||
|
if (!td->valid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
td->page_sz = page_sz;
|
||||||
|
td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
|
||||||
|
td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
|
||||||
|
td->base_addr = baser_base_addr(value, page_sz);
|
||||||
|
if (!td->indirect) {
|
||||||
|
td->num_entries = (num_pages * page_sz) / td->entry_sz;
|
||||||
|
} else {
|
||||||
|
td->num_entries = (((num_pages * page_sz) /
|
||||||
|
L1TABLE_ENTRY_SIZE) *
|
||||||
|
(page_sz / td->entry_sz));
|
||||||
|
}
|
||||||
|
td->num_ids = 1ULL << idbits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,7 +845,7 @@ static void extract_cmdq_params(GICv3ITSState *s)
|
||||||
s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
|
s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
|
||||||
|
|
||||||
if (s->cq.valid) {
|
if (s->cq.valid) {
|
||||||
s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
|
s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
|
||||||
GITS_CMDQ_ENTRY_SIZE;
|
GITS_CMDQ_ENTRY_SIZE;
|
||||||
s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
|
s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
|
||||||
s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
|
s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
|
||||||
|
@ -887,7 +862,7 @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
|
||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case GITS_TRANSLATER:
|
case GITS_TRANSLATER:
|
||||||
if (s->ctlr & ITS_CTLR_ENABLED) {
|
if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
|
||||||
devid = attrs.requester_id;
|
devid = attrs.requester_id;
|
||||||
result = process_its_cmd(s, data, devid, NONE);
|
result = process_its_cmd(s, data, devid, NONE);
|
||||||
}
|
}
|
||||||
|
@ -912,13 +887,13 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case GITS_CTLR:
|
case GITS_CTLR:
|
||||||
if (value & R_GITS_CTLR_ENABLED_MASK) {
|
if (value & R_GITS_CTLR_ENABLED_MASK) {
|
||||||
s->ctlr |= ITS_CTLR_ENABLED;
|
s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
|
||||||
extract_table_params(s);
|
extract_table_params(s);
|
||||||
extract_cmdq_params(s);
|
extract_cmdq_params(s);
|
||||||
s->creadr = 0;
|
s->creadr = 0;
|
||||||
process_cmdq(s);
|
process_cmdq(s);
|
||||||
} else {
|
} else {
|
||||||
s->ctlr &= ~ITS_CTLR_ENABLED;
|
s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GITS_CBASER:
|
case GITS_CBASER:
|
||||||
|
@ -926,7 +901,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
|
||||||
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
||||||
* already enabled
|
* already enabled
|
||||||
*/
|
*/
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
s->cbaser = deposit64(s->cbaser, 0, 32, value);
|
s->cbaser = deposit64(s->cbaser, 0, 32, value);
|
||||||
s->creadr = 0;
|
s->creadr = 0;
|
||||||
s->cwriter = s->creadr;
|
s->cwriter = s->creadr;
|
||||||
|
@ -937,7 +912,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
|
||||||
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
||||||
* already enabled
|
* already enabled
|
||||||
*/
|
*/
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
s->cbaser = deposit64(s->cbaser, 32, 32, value);
|
s->cbaser = deposit64(s->cbaser, 32, 32, value);
|
||||||
s->creadr = 0;
|
s->creadr = 0;
|
||||||
s->cwriter = s->creadr;
|
s->cwriter = s->creadr;
|
||||||
|
@ -979,7 +954,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
|
||||||
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
|
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
|
||||||
* already enabled
|
* already enabled
|
||||||
*/
|
*/
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
index = (offset - GITS_BASER) / 8;
|
index = (offset - GITS_BASER) / 8;
|
||||||
|
|
||||||
if (offset & 7) {
|
if (offset & 7) {
|
||||||
|
@ -1076,7 +1051,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
|
||||||
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
|
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
|
||||||
* already enabled
|
* already enabled
|
||||||
*/
|
*/
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
index = (offset - GITS_BASER) / 8;
|
index = (offset - GITS_BASER) / 8;
|
||||||
s->baser[index] &= GITS_BASER_RO_MASK;
|
s->baser[index] &= GITS_BASER_RO_MASK;
|
||||||
s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
|
s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
|
||||||
|
@ -1087,7 +1062,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
|
||||||
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
|
||||||
* already enabled
|
* already enabled
|
||||||
*/
|
*/
|
||||||
if (!(s->ctlr & ITS_CTLR_ENABLED)) {
|
if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
|
||||||
s->cbaser = value;
|
s->cbaser = value;
|
||||||
s->creadr = 0;
|
s->creadr = 0;
|
||||||
s->cwriter = s->creadr;
|
s->cwriter = s->creadr;
|
||||||
|
@ -1254,8 +1229,7 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
|
||||||
"gicv3-its-sysmem");
|
"gicv3-its-sysmem");
|
||||||
|
|
||||||
/* set the ITS default features supported */
|
/* set the ITS default features supported */
|
||||||
s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
|
s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
|
||||||
GITS_TYPE_PHYSICAL);
|
|
||||||
s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
|
s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
|
||||||
ITS_ITT_ENTRY_SIZE - 1);
|
ITS_ITT_ENTRY_SIZE - 1);
|
||||||
s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
|
s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
|
||||||
|
@ -1298,7 +1272,7 @@ static void gicv3_its_reset(DeviceState *dev)
|
||||||
|
|
||||||
static void gicv3_its_post_load(GICv3ITSState *s)
|
static void gicv3_its_post_load(GICv3ITSState *s)
|
||||||
{
|
{
|
||||||
if (s->ctlr & ITS_CTLR_ENABLED) {
|
if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
|
||||||
extract_table_params(s);
|
extract_table_params(s);
|
||||||
extract_cmdq_params(s);
|
extract_cmdq_params(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,8 +289,6 @@ FIELD(GITS_TYPER, CIL, 36, 1)
|
||||||
|
|
||||||
#define GITS_IDREGS 0xFFD0
|
#define GITS_IDREGS 0xFFD0
|
||||||
|
|
||||||
#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */
|
|
||||||
|
|
||||||
#define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \
|
#define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \
|
||||||
R_GITS_BASER_TYPE_MASK)
|
R_GITS_BASER_TYPE_MASK)
|
||||||
|
|
||||||
|
@ -356,28 +354,30 @@ FIELD(MAPC, RDBASE, 16, 32)
|
||||||
#define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK
|
#define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK
|
||||||
#define TABLE_ENTRY_VALID_MASK (1ULL << 0)
|
#define TABLE_ENTRY_VALID_MASK (1ULL << 0)
|
||||||
|
|
||||||
/**
|
|
||||||
* Default features advertised by this version of ITS
|
|
||||||
*/
|
|
||||||
/* Physical LPIs supported */
|
|
||||||
#define GITS_TYPE_PHYSICAL (1U << 0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 12 bytes Interrupt translation Table Entry size
|
* 12 bytes Interrupt translation Table Entry size
|
||||||
* as per Table 5.3 in GICv3 spec
|
* as per Table 5.3 in GICv3 spec
|
||||||
* ITE Lower 8 Bytes
|
* ITE Lower 8 Bytes
|
||||||
* Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
|
* Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
|
||||||
* Values: | 1023 | IntNum | IntType | Valid |
|
* Values: | Doorbell | IntNum | IntType | Valid |
|
||||||
* ITE Higher 4 Bytes
|
* ITE Higher 4 Bytes
|
||||||
* Bits: | 31 ... 16 | 15 ...0 |
|
* Bits: | 31 ... 16 | 15 ...0 |
|
||||||
* Values: | vPEID | ICID |
|
* Values: | vPEID | ICID |
|
||||||
|
* (When Doorbell is unused, as it always is in GICv3, it is 1023)
|
||||||
*/
|
*/
|
||||||
#define ITS_ITT_ENTRY_SIZE 0xC
|
#define ITS_ITT_ENTRY_SIZE 0xC
|
||||||
#define ITE_ENTRY_INTTYPE_SHIFT 1
|
|
||||||
#define ITE_ENTRY_INTID_SHIFT 2
|
FIELD(ITE_L, VALID, 0, 1)
|
||||||
#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24)
|
FIELD(ITE_L, INTTYPE, 1, 1)
|
||||||
#define ITE_ENTRY_INTSP_SHIFT 26
|
FIELD(ITE_L, INTID, 2, 24)
|
||||||
#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16)
|
FIELD(ITE_L, DOORBELL, 26, 24)
|
||||||
|
|
||||||
|
FIELD(ITE_H, ICID, 0, 16)
|
||||||
|
FIELD(ITE_H, VPEID, 16, 16)
|
||||||
|
|
||||||
|
/* Possible values for ITE_L INTTYPE */
|
||||||
|
#define ITE_INTTYPE_VIRTUAL 0
|
||||||
|
#define ITE_INTTYPE_PHYSICAL 1
|
||||||
|
|
||||||
/* 16 bits EventId */
|
/* 16 bits EventId */
|
||||||
#define ITS_IDBITS GICD_TYPER_IDBITS
|
#define ITS_IDBITS GICD_TYPER_IDBITS
|
||||||
|
@ -393,16 +393,18 @@ FIELD(MAPC, RDBASE, 16, 32)
|
||||||
* Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
|
* Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
|
||||||
*/
|
*/
|
||||||
#define GITS_DTE_SIZE (0x8ULL)
|
#define GITS_DTE_SIZE (0x8ULL)
|
||||||
#define GITS_DTE_ITTADDR_SHIFT 6
|
|
||||||
#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
|
FIELD(DTE, VALID, 0, 1)
|
||||||
ITTADDR_LENGTH)
|
FIELD(DTE, SIZE, 1, 5)
|
||||||
|
FIELD(DTE, ITTADDR, 6, 44)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 8 bytes Collection Table Entry size
|
* 8 bytes Collection Table Entry size
|
||||||
* Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
|
* Valid = 1 bit, RDBase = 16 bits
|
||||||
*/
|
*/
|
||||||
#define GITS_CTE_SIZE (0x8ULL)
|
#define GITS_CTE_SIZE (0x8ULL)
|
||||||
#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
|
FIELD(CTE, VALID, 0, 1)
|
||||||
|
FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH)
|
||||||
|
|
||||||
/* Special interrupt IDs */
|
/* Special interrupt IDs */
|
||||||
#define INTID_SECURE 1020
|
#define INTID_SECURE 1020
|
||||||
|
|
|
@ -139,6 +139,8 @@ enum {
|
||||||
ASPEED_DEV_EMMC,
|
ASPEED_DEV_EMMC,
|
||||||
ASPEED_DEV_KCS,
|
ASPEED_DEV_KCS,
|
||||||
ASPEED_DEV_HACE,
|
ASPEED_DEV_HACE,
|
||||||
|
ASPEED_DEV_DPMCU,
|
||||||
|
ASPEED_DEV_DP,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ASPEED_SOC_H */
|
#endif /* ASPEED_SOC_H */
|
||||||
|
|
|
@ -46,17 +46,14 @@ typedef struct {
|
||||||
bool indirect;
|
bool indirect;
|
||||||
uint16_t entry_sz;
|
uint16_t entry_sz;
|
||||||
uint32_t page_sz;
|
uint32_t page_sz;
|
||||||
uint32_t max_entries;
|
uint32_t num_entries;
|
||||||
union {
|
uint32_t num_ids;
|
||||||
uint32_t max_devids;
|
|
||||||
uint32_t max_collids;
|
|
||||||
} maxids;
|
|
||||||
uint64_t base_addr;
|
uint64_t base_addr;
|
||||||
} TableDesc;
|
} TableDesc;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool valid;
|
bool valid;
|
||||||
uint32_t max_entries;
|
uint32_t num_entries;
|
||||||
uint64_t base_addr;
|
uint64_t base_addr;
|
||||||
} CmdQDesc;
|
} CmdQDesc;
|
||||||
|
|
||||||
|
|
|
@ -6964,18 +6964,42 @@ static const ARMCPRegInfo tlbios_reginfo[] = {
|
||||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
|
||||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
.writefn = tlbi_aa64_vmalle1is_write },
|
.writefn = tlbi_aa64_vmalle1is_write },
|
||||||
|
{ .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1,
|
||||||
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae1is_write },
|
||||||
{ .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
|
{ .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
|
||||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
.writefn = tlbi_aa64_vmalle1is_write },
|
.writefn = tlbi_aa64_vmalle1is_write },
|
||||||
|
{ .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3,
|
||||||
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae1is_write },
|
||||||
|
{ .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5,
|
||||||
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae1is_write },
|
||||||
|
{ .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7,
|
||||||
|
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae1is_write },
|
||||||
{ .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
|
{ .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
|
||||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
|
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
|
||||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||||
.writefn = tlbi_aa64_alle2is_write },
|
.writefn = tlbi_aa64_alle2is_write },
|
||||||
|
{ .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1,
|
||||||
|
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae2is_write },
|
||||||
{ .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
|
{ .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
|
||||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
|
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
|
||||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||||
.writefn = tlbi_aa64_alle1is_write },
|
.writefn = tlbi_aa64_alle1is_write },
|
||||||
|
{ .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5,
|
||||||
|
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae2is_write },
|
||||||
{ .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
|
{ .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
|
||||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
|
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
|
||||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||||
|
@ -6996,6 +7020,14 @@ static const ARMCPRegInfo tlbios_reginfo[] = {
|
||||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
|
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
|
||||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||||
.writefn = tlbi_aa64_alle3is_write },
|
.writefn = tlbi_aa64_alle3is_write },
|
||||||
|
{ .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1,
|
||||||
|
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae3is_write },
|
||||||
|
{ .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
|
||||||
|
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||||
|
.writefn = tlbi_aa64_vae3is_write },
|
||||||
REGINFO_SENTINEL
|
REGINFO_SENTINEL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue