mirror of https://github.com/xqemu/xqemu.git
target-arm queue:
* target/arm: Fix cpu_get_tb_cpu_state() for non-SVE CPUs * hw/arm/exynos4210: fix Exynos4210 UART support * hw/arm/virt-acpi-build: Add a check for memory-less NUMA nodes * arm: Add BBC micro:bit machine * aspeed/i2c: Fix interrupt handling bugs * hw/arm/smmu-common: Fix the name of the iommu memory regions * hw/arm/smmuv3: fix eventq recording and IRQ triggerring * hw/intc/arm_gic: Document QEMU interface * hw/intc/arm_gic: Drop GIC_BASE_IRQ macro * hw/net/pcnet-pci: Convert away from old_mmio accessors * hw/timer/cmsdk-apb-dualtimer: Add missing 'break' statements * aspeed/timer: fix compile breakage with clang 3.4.2 * hw/arm/aspeed: change the FMC flash model of the AST2500 evb * hw/arm/aspeed: Minor code cleanups * target/arm: Start AArch32 CPUs with EL2 but not EL3 in Hyp mode -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJbqkTPAAoJEDwlJe0UNgzecVUQAKluPQa7o8owzAzbV4Gb2cvB ScRc3K8NYFPEomcxL7IN0x657jJERMS1x9ZgbD11IMP/QEodFZuCPQLej40AnVVx srXig4YOX27moh3RXoCT5iN70H2Nj21vnwzXbO26YS4PrY/AbPgwONUEsQ7py0xW YbbyBcJY9c+H3qUpCPOEBltCzdF3yBp6T+tV8YS+iRKcM1lz8iKPJF+02eFn3aPj 8rzBQpgJ14MxkwavAH/qrd0Vxq3YxZbrzRP+1QJLGepiUEmVhA6I5z2Zj8ZTg+zG ntJ7rYcTZ9G6KSILQKYiYCNKDT6w2i6+J7cl01KpbadoEROBQ4sH4udhxNtKLSer 4eTxEocfY44x83MNwaHL4J6anAqOZKO9H8i8Xu1LsU2HYfNHnbJo8cxfhF7tM/tX 4Tk9z6F19Epzd3jXsc5ozKkB9uh4JDT9dhGV7ModKzzhYd+VI0zIBrEwXfrAzZhT TV+i7kQfMWwoJ26Tda87PNWgiPQp3MhPXQF0jynbQGhxBEGjJpMjge6Uuac9TiHS VC+njlGFNQ7uTwBSnt2egfULlPHxSnTMg8X7ZkQUG4a7FCpTUc9IFa1c3qE7v6o2 a4juEv+E5n4RjvmqwgxUkYWhgbAShcKpVSqgk6chjcDde5iuMt04Y37w1yH+/x5a j1hFJObHHfu+SWuMlbmm =JT4P -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180925-1' into staging target-arm queue: * target/arm: Fix cpu_get_tb_cpu_state() for non-SVE CPUs * hw/arm/exynos4210: fix Exynos4210 UART support * hw/arm/virt-acpi-build: Add a check for memory-less NUMA nodes * arm: Add BBC micro:bit machine * aspeed/i2c: Fix interrupt handling bugs * hw/arm/smmu-common: Fix the name of the iommu memory regions * hw/arm/smmuv3: fix eventq recording and IRQ triggerring * hw/intc/arm_gic: Document QEMU interface * hw/intc/arm_gic: Drop GIC_BASE_IRQ macro * hw/net/pcnet-pci: Convert away from old_mmio accessors * hw/timer/cmsdk-apb-dualtimer: Add missing 'break' statements * aspeed/timer: fix compile breakage with clang 3.4.2 * hw/arm/aspeed: change the FMC flash model of the AST2500 evb * hw/arm/aspeed: Minor code cleanups * target/arm: Start AArch32 CPUs with EL2 but not EL3 in Hyp mode # gpg: Signature made Tue 25 Sep 2018 15:23:11 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180925-1: (21 commits) target/arm: Start AArch32 CPUs with EL2 but not EL3 in Hyp mode aspeed/smc: fix some alignment issues hw/arm/aspeed: Add an Aspeed machine class hw/arm/aspeed: change the FMC flash model of the AST2500 evb aspeed/timer: fix compile breakage with clang 3.4.2 hw/timer/cmsdk-apb-dualtimer: Add missing 'break' statements hw/net/pcnet-pci: Unify pcnet_ioport_read/write and pcnet_mmio_read/write hw/net/pcnet-pci: Convert away from old_mmio accessors hw/intc/arm_gic: Drop GIC_BASE_IRQ macro hw/intc/arm_gic: Document QEMU interface hw/arm/smmuv3: fix eventq recording and IRQ triggerring hw/arm/smmu-common: Fix the name of the iommu memory regions aspeed/i2c: Fix receive done interrupt handling aspeed/i2c: Handle receive command in separate function aspeed/i2c: interrupts should be cleared by software only arm: Add BBC micro:bit machine arm: Add Nordic Semiconductor nRF51 SoC MAINTAINERS: Add NRF51 entry hw/arm/virt-acpi-build: Add a check for memory-less NUMA nodes hw/arm/exynos4210: fix Exynos4210 UART support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
71fbecea0f
|
@ -671,6 +671,14 @@ F: include/hw/*/*aspeed*
|
|||
F: hw/net/ftgmac100.c
|
||||
F: include/hw/net/ftgmac100.h
|
||||
|
||||
NRF51
|
||||
M: Joel Stanley <joel@jms.id.au>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/nrf51_soc.c
|
||||
F: hw/arm/microbit.c
|
||||
F: include/hw/arm/nrf51_soc.h
|
||||
|
||||
CRIS Machines
|
||||
-------------
|
||||
Axis Dev88
|
||||
|
|
|
@ -101,6 +101,7 @@ CONFIG_STM32F2XX_SYSCFG=y
|
|||
CONFIG_STM32F2XX_ADC=y
|
||||
CONFIG_STM32F2XX_SPI=y
|
||||
CONFIG_STM32F205_SOC=y
|
||||
CONFIG_NRF51_SOC=y
|
||||
|
||||
CONFIG_CMSDK_APB_TIMER=y
|
||||
CONFIG_CMSDK_APB_DUALTIMER=y
|
||||
|
|
|
@ -37,3 +37,4 @@ obj-$(CONFIG_IOTKIT) += iotkit.o
|
|||
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
|
||||
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
|
||||
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
|
||||
obj-$(CONFIG_NRF51_SOC) += nrf51_soc.o microbit.o
|
||||
|
|
212
hw/arm/aspeed.c
212
hw/arm/aspeed.c
|
@ -15,6 +15,7 @@
|
|||
#include "cpu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/arm/aspeed.h"
|
||||
#include "hw/arm/aspeed_soc.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/i2c/smbus.h"
|
||||
|
@ -34,22 +35,6 @@ typedef struct AspeedBoardState {
|
|||
MemoryRegion max_ram;
|
||||
} AspeedBoardState;
|
||||
|
||||
typedef struct AspeedBoardConfig {
|
||||
const char *soc_name;
|
||||
uint32_t hw_strap1;
|
||||
const char *fmc_model;
|
||||
const char *spi_model;
|
||||
uint32_t num_cs;
|
||||
void (*i2c_init)(AspeedBoardState *bmc);
|
||||
} AspeedBoardConfig;
|
||||
|
||||
enum {
|
||||
PALMETTO_BMC,
|
||||
AST2500_EVB,
|
||||
ROMULUS_BMC,
|
||||
WITHERSPOON_BMC,
|
||||
};
|
||||
|
||||
/* Palmetto hardware value: 0x120CE416 */
|
||||
#define PALMETTO_BMC_HW_STRAP1 ( \
|
||||
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
|
||||
|
@ -88,46 +73,6 @@ enum {
|
|||
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
|
||||
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
|
||||
|
||||
static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
|
||||
static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
|
||||
static void romulus_bmc_i2c_init(AspeedBoardState *bmc);
|
||||
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
|
||||
|
||||
static const AspeedBoardConfig aspeed_boards[] = {
|
||||
[PALMETTO_BMC] = {
|
||||
.soc_name = "ast2400-a1",
|
||||
.hw_strap1 = PALMETTO_BMC_HW_STRAP1,
|
||||
.fmc_model = "n25q256a",
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = palmetto_bmc_i2c_init,
|
||||
},
|
||||
[AST2500_EVB] = {
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = AST2500_EVB_HW_STRAP1,
|
||||
.fmc_model = "n25q256a",
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = ast2500_evb_i2c_init,
|
||||
},
|
||||
[ROMULUS_BMC] = {
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = ROMULUS_BMC_HW_STRAP1,
|
||||
.fmc_model = "n25q256a",
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = romulus_bmc_i2c_init,
|
||||
},
|
||||
[WITHERSPOON_BMC] = {
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
|
||||
.fmc_model = "mx25l25635e",
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = witherspoon_bmc_i2c_init,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The max ram region is for firmwares that scan the address space
|
||||
* with load/store to guess how much RAM the SoC has.
|
||||
|
@ -313,30 +258,6 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
|
|||
object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort);
|
||||
}
|
||||
|
||||
static void palmetto_bmc_init(MachineState *machine)
|
||||
{
|
||||
aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
|
||||
}
|
||||
|
||||
static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
|
||||
mc->init = palmetto_bmc_init;
|
||||
mc->max_cpus = 1;
|
||||
mc->no_sdcard = 1;
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo palmetto_bmc_type = {
|
||||
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = palmetto_bmc_class_init,
|
||||
};
|
||||
|
||||
static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
@ -353,30 +274,6 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
|
|||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
|
||||
}
|
||||
|
||||
static void ast2500_evb_init(MachineState *machine)
|
||||
{
|
||||
aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
|
||||
}
|
||||
|
||||
static void ast2500_evb_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "Aspeed AST2500 EVB (ARM1176)";
|
||||
mc->init = ast2500_evb_init;
|
||||
mc->max_cpus = 1;
|
||||
mc->no_sdcard = 1;
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo ast2500_evb_type = {
|
||||
.name = MACHINE_TYPE_NAME("ast2500-evb"),
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = ast2500_evb_class_init,
|
||||
};
|
||||
|
||||
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
@ -386,30 +283,6 @@ static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
|
|||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
|
||||
}
|
||||
|
||||
static void romulus_bmc_init(MachineState *machine)
|
||||
{
|
||||
aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
|
||||
}
|
||||
|
||||
static void romulus_bmc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
|
||||
mc->init = romulus_bmc_init;
|
||||
mc->max_cpus = 1;
|
||||
mc->no_sdcard = 1;
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo romulus_bmc_type = {
|
||||
.name = MACHINE_TYPE_NAME("romulus-bmc"),
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = romulus_bmc_class_init,
|
||||
};
|
||||
|
||||
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
@ -433,36 +306,91 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
|
|||
0x60);
|
||||
}
|
||||
|
||||
static void witherspoon_bmc_init(MachineState *machine)
|
||||
static void aspeed_machine_init(MachineState *machine)
|
||||
{
|
||||
aspeed_board_init(machine, &aspeed_boards[WITHERSPOON_BMC]);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
|
||||
|
||||
aspeed_board_init(machine, amc->board);
|
||||
}
|
||||
|
||||
static void witherspoon_bmc_class_init(ObjectClass *oc, void *data)
|
||||
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
|
||||
const AspeedBoardConfig *board = data;
|
||||
|
||||
mc->desc = "OpenPOWER Witherspoon BMC (ARM1176)";
|
||||
mc->init = witherspoon_bmc_init;
|
||||
mc->desc = board->desc;
|
||||
mc->init = aspeed_machine_init;
|
||||
mc->max_cpus = 1;
|
||||
mc->no_sdcard = 1;
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
amc->board = board;
|
||||
}
|
||||
|
||||
static const TypeInfo witherspoon_bmc_type = {
|
||||
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
|
||||
static const TypeInfo aspeed_machine_type = {
|
||||
.name = TYPE_ASPEED_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = witherspoon_bmc_class_init,
|
||||
.instance_size = sizeof(AspeedMachine),
|
||||
.class_size = sizeof(AspeedMachineClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void aspeed_machine_init(void)
|
||||
static const AspeedBoardConfig aspeed_boards[] = {
|
||||
{
|
||||
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
|
||||
.desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)",
|
||||
.soc_name = "ast2400-a1",
|
||||
.hw_strap1 = PALMETTO_BMC_HW_STRAP1,
|
||||
.fmc_model = "n25q256a",
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = palmetto_bmc_i2c_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("ast2500-evb"),
|
||||
.desc = "Aspeed AST2500 EVB (ARM1176)",
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = AST2500_EVB_HW_STRAP1,
|
||||
.fmc_model = "w25q256",
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = ast2500_evb_i2c_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("romulus-bmc"),
|
||||
.desc = "OpenPOWER Romulus BMC (ARM1176)",
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = ROMULUS_BMC_HW_STRAP1,
|
||||
.fmc_model = "n25q256a",
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = romulus_bmc_i2c_init,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
|
||||
.desc = "OpenPOWER Witherspoon BMC (ARM1176)",
|
||||
.soc_name = "ast2500-a1",
|
||||
.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
|
||||
.fmc_model = "mx25l25635e",
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = witherspoon_bmc_i2c_init,
|
||||
},
|
||||
};
|
||||
|
||||
static void aspeed_machine_types(void)
|
||||
{
|
||||
type_register_static(&palmetto_bmc_type);
|
||||
type_register_static(&ast2500_evb_type);
|
||||
type_register_static(&romulus_bmc_type);
|
||||
type_register_static(&witherspoon_bmc_type);
|
||||
int i;
|
||||
|
||||
type_register_static(&aspeed_machine_type);
|
||||
for (i = 0; i < ARRAY_SIZE(aspeed_boards); ++i) {
|
||||
TypeInfo ti = {
|
||||
.name = aspeed_boards[i].name,
|
||||
.parent = TYPE_ASPEED_MACHINE,
|
||||
.class_init = aspeed_machine_class_init,
|
||||
.class_data = (void *)&aspeed_boards[i],
|
||||
};
|
||||
type_register(&ti);
|
||||
}
|
||||
}
|
||||
|
||||
type_init(aspeed_machine_init)
|
||||
type_init(aspeed_machine_types)
|
||||
|
|
|
@ -352,19 +352,19 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
|
|||
|
||||
/*** UARTs ***/
|
||||
exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
|
||||
EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
|
||||
EXYNOS4210_UART0_FIFO_SIZE, 0, serial_hd(0),
|
||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
|
||||
|
||||
exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
|
||||
EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
|
||||
EXYNOS4210_UART1_FIFO_SIZE, 1, serial_hd(1),
|
||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
|
||||
|
||||
exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
|
||||
EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
|
||||
EXYNOS4210_UART2_FIFO_SIZE, 2, serial_hd(2),
|
||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
|
||||
|
||||
exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
|
||||
EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
|
||||
EXYNOS4210_UART3_FIFO_SIZE, 3, serial_hd(3),
|
||||
s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
|
||||
|
||||
/*** SD/MMC host controllers ***/
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* BBC micro:bit machine
|
||||
* http://tech.microbit.org/hardware/
|
||||
*
|
||||
* Copyright 2018 Joel Stanley <joel@jms.id.au>
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
#include "hw/arm/nrf51_soc.h"
|
||||
|
||||
typedef struct {
|
||||
MachineState parent;
|
||||
|
||||
NRF51State nrf51;
|
||||
} MicrobitMachineState;
|
||||
|
||||
#define TYPE_MICROBIT_MACHINE MACHINE_TYPE_NAME("microbit")
|
||||
|
||||
#define MICROBIT_MACHINE(obj) \
|
||||
OBJECT_CHECK(MicrobitMachineState, obj, TYPE_MICROBIT_MACHINE)
|
||||
|
||||
static void microbit_init(MachineState *machine)
|
||||
{
|
||||
MicrobitMachineState *s = MICROBIT_MACHINE(machine);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
Object *soc = OBJECT(&s->nrf51);
|
||||
|
||||
sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51),
|
||||
TYPE_NRF51_SOC);
|
||||
object_property_set_link(soc, OBJECT(system_memory), "memory",
|
||||
&error_fatal);
|
||||
object_property_set_bool(soc, true, "realized", &error_fatal);
|
||||
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
|
||||
NRF51_SOC(soc)->flash_size);
|
||||
}
|
||||
|
||||
static void microbit_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "BBC micro:bit";
|
||||
mc->init = microbit_init;
|
||||
mc->max_cpus = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo microbit_info = {
|
||||
.name = TYPE_MICROBIT_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(MicrobitMachineState),
|
||||
.class_init = microbit_machine_class_init,
|
||||
};
|
||||
|
||||
static void microbit_machine_init(void)
|
||||
{
|
||||
type_register_static(µbit_info);
|
||||
}
|
||||
|
||||
type_init(microbit_machine_init);
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Nordic Semiconductor nRF51 SoC
|
||||
* http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
|
||||
*
|
||||
* Copyright 2018 Joel Stanley <joel@jms.id.au>
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/devices.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
|
||||
#include "hw/arm/nrf51_soc.h"
|
||||
|
||||
#define IOMEM_BASE 0x40000000
|
||||
#define IOMEM_SIZE 0x20000000
|
||||
|
||||
#define FICR_BASE 0x10000000
|
||||
#define FICR_SIZE 0x000000fc
|
||||
|
||||
#define FLASH_BASE 0x00000000
|
||||
#define SRAM_BASE 0x20000000
|
||||
|
||||
#define PRIVATE_BASE 0xF0000000
|
||||
#define PRIVATE_SIZE 0x10000000
|
||||
|
||||
/*
|
||||
* The size and base is for the NRF51822 part. If other parts
|
||||
* are supported in the future, add a sub-class of NRF51SoC for
|
||||
* the specific variants
|
||||
*/
|
||||
#define NRF51822_FLASH_SIZE (256 * 1024)
|
||||
#define NRF51822_SRAM_SIZE (16 * 1024)
|
||||
|
||||
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
{
|
||||
NRF51State *s = NRF51_SOC(dev_soc);
|
||||
Error *err = NULL;
|
||||
|
||||
if (!s->board_memory) {
|
||||
error_setg(errp, "memory property was not set");
|
||||
return;
|
||||
}
|
||||
|
||||
object_property_set_link(OBJECT(&s->cpu), OBJECT(&s->container), "memory",
|
||||
&err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
|
||||
|
||||
memory_region_init_rom(&s->flash, OBJECT(s), "nrf51.flash", s->flash_size,
|
||||
&err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
|
||||
|
||||
memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
|
||||
|
||||
create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
|
||||
create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
|
||||
create_unimplemented_device("nrf51_soc.private",
|
||||
PRIVATE_BASE, PRIVATE_SIZE);
|
||||
}
|
||||
|
||||
static void nrf51_soc_init(Object *obj)
|
||||
{
|
||||
NRF51State *s = NRF51_SOC(obj);
|
||||
|
||||
memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX);
|
||||
|
||||
sysbus_init_child_obj(OBJECT(s), "armv6m", OBJECT(&s->cpu), sizeof(s->cpu),
|
||||
TYPE_ARMV7M);
|
||||
qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type",
|
||||
ARM_CPU_TYPE_NAME("cortex-m0"));
|
||||
qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32);
|
||||
}
|
||||
|
||||
static Property nrf51_soc_properties[] = {
|
||||
DEFINE_PROP_LINK("memory", NRF51State, board_memory, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_UINT32("sram-size", NRF51State, sram_size, NRF51822_SRAM_SIZE),
|
||||
DEFINE_PROP_UINT32("flash-size", NRF51State, flash_size,
|
||||
NRF51822_FLASH_SIZE),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void nrf51_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = nrf51_soc_realize;
|
||||
dc->props = nrf51_soc_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo nrf51_soc_info = {
|
||||
.name = TYPE_NRF51_SOC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(NRF51State),
|
||||
.instance_init = nrf51_soc_init,
|
||||
.class_init = nrf51_soc_class_init,
|
||||
};
|
||||
|
||||
static void nrf51_soc_types(void)
|
||||
{
|
||||
type_register_static(&nrf51_soc_info);
|
||||
}
|
||||
type_init(nrf51_soc_types)
|
|
@ -311,6 +311,7 @@ static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
|
|||
SMMUState *s = opaque;
|
||||
SMMUPciBus *sbus = g_hash_table_lookup(s->smmu_pcibus_by_busptr, bus);
|
||||
SMMUDevice *sdev;
|
||||
static unsigned int index;
|
||||
|
||||
if (!sbus) {
|
||||
sbus = g_malloc0(sizeof(SMMUPciBus) +
|
||||
|
@ -321,9 +322,8 @@ static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
|
|||
|
||||
sdev = sbus->pbdev[devfn];
|
||||
if (!sdev) {
|
||||
char *name = g_strdup_printf("%s-%d-%d",
|
||||
s->mrtypename,
|
||||
pci_bus_num(bus), devfn);
|
||||
char *name = g_strdup_printf("%s-%d-%d", s->mrtypename, devfn, index++);
|
||||
|
||||
sdev = sbus->pbdev[devfn] = g_new0(SMMUDevice, 1);
|
||||
|
||||
sdev->smmu = s;
|
||||
|
|
|
@ -442,17 +442,17 @@ typedef struct SMMUEventInfo {
|
|||
|
||||
#define EVT_Q_OVERFLOW (1 << 31)
|
||||
|
||||
#define EVT_SET_TYPE(x, v) deposit32((x)->word[0], 0 , 8 , v)
|
||||
#define EVT_SET_SSV(x, v) deposit32((x)->word[0], 11, 1 , v)
|
||||
#define EVT_SET_SSID(x, v) deposit32((x)->word[0], 12, 20, v)
|
||||
#define EVT_SET_SID(x, v) ((x)->word[1] = v)
|
||||
#define EVT_SET_STAG(x, v) deposit32((x)->word[2], 0 , 16, v)
|
||||
#define EVT_SET_STALL(x, v) deposit32((x)->word[2], 31, 1 , v)
|
||||
#define EVT_SET_PNU(x, v) deposit32((x)->word[3], 1 , 1 , v)
|
||||
#define EVT_SET_IND(x, v) deposit32((x)->word[3], 2 , 1 , v)
|
||||
#define EVT_SET_RNW(x, v) deposit32((x)->word[3], 3 , 1 , v)
|
||||
#define EVT_SET_S2(x, v) deposit32((x)->word[3], 7 , 1 , v)
|
||||
#define EVT_SET_CLASS(x, v) deposit32((x)->word[3], 8 , 2 , v)
|
||||
#define EVT_SET_TYPE(x, v) ((x)->word[0] = deposit32((x)->word[0], 0 , 8 , v))
|
||||
#define EVT_SET_SSV(x, v) ((x)->word[0] = deposit32((x)->word[0], 11, 1 , v))
|
||||
#define EVT_SET_SSID(x, v) ((x)->word[0] = deposit32((x)->word[0], 12, 20, v))
|
||||
#define EVT_SET_SID(x, v) ((x)->word[1] = v)
|
||||
#define EVT_SET_STAG(x, v) ((x)->word[2] = deposit32((x)->word[2], 0 , 16, v))
|
||||
#define EVT_SET_STALL(x, v) ((x)->word[2] = deposit32((x)->word[2], 31, 1 , v))
|
||||
#define EVT_SET_PNU(x, v) ((x)->word[3] = deposit32((x)->word[3], 1 , 1 , v))
|
||||
#define EVT_SET_IND(x, v) ((x)->word[3] = deposit32((x)->word[3], 2 , 1 , v))
|
||||
#define EVT_SET_RNW(x, v) ((x)->word[3] = deposit32((x)->word[3], 3 , 1 , v))
|
||||
#define EVT_SET_S2(x, v) ((x)->word[3] = deposit32((x)->word[3], 7 , 1 , v))
|
||||
#define EVT_SET_CLASS(x, v) ((x)->word[3] = deposit32((x)->word[3], 8 , 2 , v))
|
||||
#define EVT_SET_ADDR(x, addr) \
|
||||
do { \
|
||||
(x)->word[5] = (uint32_t)(addr >> 32); \
|
||||
|
@ -460,8 +460,8 @@ typedef struct SMMUEventInfo {
|
|||
} while (0)
|
||||
#define EVT_SET_ADDR2(x, addr) \
|
||||
do { \
|
||||
deposit32((x)->word[7], 3, 29, addr >> 16); \
|
||||
deposit32((x)->word[7], 0, 16, addr & 0xffff);\
|
||||
(x)->word[7] = deposit32((x)->word[7], 3, 29, addr >> 16); \
|
||||
(x)->word[7] = deposit32((x)->word[7], 0, 16, addr & 0xffff);\
|
||||
} while (0)
|
||||
|
||||
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
|
||||
|
|
|
@ -136,7 +136,7 @@ static MemTxResult smmuv3_write_eventq(SMMUv3State *s, Evt *evt)
|
|||
return r;
|
||||
}
|
||||
|
||||
if (smmuv3_q_empty(q)) {
|
||||
if (!smmuv3_q_empty(q)) {
|
||||
smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0);
|
||||
}
|
||||
return MEMTX_OK;
|
||||
|
|
|
@ -562,10 +562,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
|
||||
mem_base = vms->memmap[VIRT_MEM].base;
|
||||
for (i = 0; i < nb_numa_nodes; ++i) {
|
||||
numamem = acpi_data_push(table_data, sizeof(*numamem));
|
||||
build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i,
|
||||
MEM_AFFINITY_ENABLED);
|
||||
mem_base += numa_info[i].node_mem;
|
||||
if (numa_info[i].node_mem > 0) {
|
||||
numamem = acpi_data_push(table_data, sizeof(*numamem));
|
||||
build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i,
|
||||
MEM_AFFINITY_ENABLED);
|
||||
mem_base += numa_info[i].node_mem;
|
||||
}
|
||||
}
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + srat_start),
|
||||
|
|
|
@ -52,6 +52,13 @@
|
|||
#define I2CD_AC_TIMING_REG2 0x08 /* Clock and AC Timing Control #1 */
|
||||
#define I2CD_INTR_CTRL_REG 0x0c /* I2CD Interrupt Control */
|
||||
#define I2CD_INTR_STS_REG 0x10 /* I2CD Interrupt Status */
|
||||
|
||||
#define I2CD_INTR_SLAVE_ADDR_MATCH (0x1 << 31) /* 0: addr1 1: addr2 */
|
||||
#define I2CD_INTR_SLAVE_ADDR_RX_PENDING (0x1 << 30)
|
||||
/* bits[19-16] Reserved */
|
||||
|
||||
/* All bits below are cleared by writing 1 */
|
||||
#define I2CD_INTR_SLAVE_INACTIVE_TIMEOUT (0x1 << 15)
|
||||
#define I2CD_INTR_SDA_DL_TIMEOUT (0x1 << 14)
|
||||
#define I2CD_INTR_BUS_RECOVER_DONE (0x1 << 13)
|
||||
#define I2CD_INTR_SMBUS_ALERT (0x1 << 12) /* Bus [0-3] only */
|
||||
|
@ -59,7 +66,7 @@
|
|||
#define I2CD_INTR_SMBUS_DEV_ALERT_ADDR (0x1 << 10) /* Removed */
|
||||
#define I2CD_INTR_SMBUS_DEF_ADDR (0x1 << 9) /* Removed */
|
||||
#define I2CD_INTR_GCALL_ADDR (0x1 << 8) /* Removed */
|
||||
#define I2CD_INTR_SLAVE_MATCH (0x1 << 7) /* use RX_DONE */
|
||||
#define I2CD_INTR_SLAVE_ADDR_RX_MATCH (0x1 << 7) /* use RX_DONE */
|
||||
#define I2CD_INTR_SCL_TIMEOUT (0x1 << 6)
|
||||
#define I2CD_INTR_ABNORMAL (0x1 << 5)
|
||||
#define I2CD_INTR_NORMAL_STOP (0x1 << 4)
|
||||
|
@ -180,6 +187,26 @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus)
|
|||
return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK;
|
||||
}
|
||||
|
||||
static void aspeed_i2c_handle_rx_cmd(AspeedI2CBus *bus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
aspeed_i2c_set_state(bus, I2CD_MRXD);
|
||||
ret = i2c_recv(bus->bus);
|
||||
if (ret < 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
|
||||
ret = 0xff;
|
||||
} else {
|
||||
bus->intr_status |= I2CD_INTR_RX_DONE;
|
||||
}
|
||||
bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
|
||||
if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
|
||||
i2c_nack(bus->bus);
|
||||
}
|
||||
bus->cmd &= ~(I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST);
|
||||
aspeed_i2c_set_state(bus, I2CD_MACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The state machine needs some refinement. It is only used to track
|
||||
* invalid STOP commands for the moment.
|
||||
|
@ -188,7 +215,6 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
|
|||
{
|
||||
bus->cmd &= ~0xFFFF;
|
||||
bus->cmd |= value & 0xFFFF;
|
||||
bus->intr_status = 0;
|
||||
|
||||
if (bus->cmd & I2CD_M_START_CMD) {
|
||||
uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
|
||||
|
@ -226,23 +252,9 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
|
|||
aspeed_i2c_set_state(bus, I2CD_MACTIVE);
|
||||
}
|
||||
|
||||
if (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) {
|
||||
int ret;
|
||||
|
||||
aspeed_i2c_set_state(bus, I2CD_MRXD);
|
||||
ret = i2c_recv(bus->bus);
|
||||
if (ret < 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__);
|
||||
ret = 0xff;
|
||||
} else {
|
||||
bus->intr_status |= I2CD_INTR_RX_DONE;
|
||||
}
|
||||
bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
|
||||
if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
|
||||
i2c_nack(bus->bus);
|
||||
}
|
||||
bus->cmd &= ~(I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST);
|
||||
aspeed_i2c_set_state(bus, I2CD_MACTIVE);
|
||||
if ((bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) &&
|
||||
!(bus->intr_status & I2CD_INTR_RX_DONE)) {
|
||||
aspeed_i2c_handle_rx_cmd(bus);
|
||||
}
|
||||
|
||||
if (bus->cmd & I2CD_M_STOP_CMD) {
|
||||
|
@ -263,6 +275,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
|
|||
uint64_t value, unsigned size)
|
||||
{
|
||||
AspeedI2CBus *bus = opaque;
|
||||
bool handle_rx;
|
||||
|
||||
switch (offset) {
|
||||
case I2CD_FUN_CTRL_REG:
|
||||
|
@ -283,9 +296,17 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
|
|||
bus->intr_ctrl = value & 0x7FFF;
|
||||
break;
|
||||
case I2CD_INTR_STS_REG:
|
||||
handle_rx = (bus->intr_status & I2CD_INTR_RX_DONE) &&
|
||||
(value & I2CD_INTR_RX_DONE);
|
||||
bus->intr_status &= ~(value & 0x7FFF);
|
||||
bus->controller->intr_status &= ~(1 << bus->id);
|
||||
qemu_irq_lower(bus->controller->irq);
|
||||
if (!bus->intr_status) {
|
||||
bus->controller->intr_status &= ~(1 << bus->id);
|
||||
qemu_irq_lower(bus->controller->irq);
|
||||
}
|
||||
if (handle_rx && (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST))) {
|
||||
aspeed_i2c_handle_rx_cmd(bus);
|
||||
aspeed_i2c_bus_raise_interrupt(bus);
|
||||
}
|
||||
break;
|
||||
case I2CD_DEV_ADDR_REG:
|
||||
qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
|
||||
|
|
|
@ -955,7 +955,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
res = 0;
|
||||
if (!(s->security_extn && !attrs.secure) && gic_has_groups(s)) {
|
||||
/* Every byte offset holds 8 group status bits */
|
||||
irq = (offset - 0x080) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x080) * 8;
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -974,7 +974,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
irq = (offset - 0x100) * 8;
|
||||
else
|
||||
irq = (offset - 0x180) * 8;
|
||||
irq += GIC_BASE_IRQ;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
res = 0;
|
||||
|
@ -994,7 +993,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
irq = (offset - 0x200) * 8;
|
||||
else
|
||||
irq = (offset - 0x280) * 8;
|
||||
irq += GIC_BASE_IRQ;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
res = 0;
|
||||
|
@ -1019,7 +1017,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
goto bad_reg;
|
||||
}
|
||||
|
||||
irq += GIC_BASE_IRQ;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
res = 0;
|
||||
|
@ -1036,7 +1033,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
}
|
||||
} else if (offset < 0x800) {
|
||||
/* Interrupt Priority. */
|
||||
irq = (offset - 0x400) + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x400);
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
res = gic_dist_get_priority(s, cpu, irq, attrs);
|
||||
|
@ -1046,7 +1043,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
/* For uniprocessor GICs these RAZ/WI */
|
||||
res = 0;
|
||||
} else {
|
||||
irq = (offset - 0x800) + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x800);
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -1060,7 +1057,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
|||
}
|
||||
} else if (offset < 0xf00) {
|
||||
/* Interrupt Configuration. */
|
||||
irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0xc00) * 4;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
res = 0;
|
||||
|
@ -1183,7 +1180,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
*/
|
||||
if (!(s->security_extn && !attrs.secure) && gic_has_groups(s)) {
|
||||
/* Every byte offset holds 8 group status bits */
|
||||
irq = (offset - 0x80) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x80) * 8;
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -1204,7 +1201,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0x180) {
|
||||
/* Interrupt Set Enable. */
|
||||
irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x100) * 8;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
if (irq < GIC_NR_SGIS) {
|
||||
|
@ -1239,7 +1236,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0x200) {
|
||||
/* Interrupt Clear Enable. */
|
||||
irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x180) * 8;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
if (irq < GIC_NR_SGIS) {
|
||||
|
@ -1264,7 +1261,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0x280) {
|
||||
/* Interrupt Set Pending. */
|
||||
irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x200) * 8;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
if (irq < GIC_NR_SGIS) {
|
||||
|
@ -1283,7 +1280,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0x300) {
|
||||
/* Interrupt Clear Pending. */
|
||||
irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x280) * 8;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
if (irq < GIC_NR_SGIS) {
|
||||
|
@ -1309,7 +1306,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
goto bad_reg;
|
||||
}
|
||||
|
||||
irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x300) * 8;
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -1333,7 +1330,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
goto bad_reg;
|
||||
}
|
||||
|
||||
irq = (offset - 0x380) * 8 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x380) * 8;
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -1353,7 +1350,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0x800) {
|
||||
/* Interrupt Priority. */
|
||||
irq = (offset - 0x400) + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x400);
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
gic_dist_set_priority(s, cpu, irq, value, attrs);
|
||||
|
@ -1362,7 +1359,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
* annoying exception of the 11MPCore's GIC.
|
||||
*/
|
||||
if (s->num_cpu != 1 || s->revision == REV_11MPCORE) {
|
||||
irq = (offset - 0x800) + GIC_BASE_IRQ;
|
||||
irq = (offset - 0x800);
|
||||
if (irq >= s->num_irq) {
|
||||
goto bad_reg;
|
||||
}
|
||||
|
@ -1375,7 +1372,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
|
|||
}
|
||||
} else if (offset < 0xf00) {
|
||||
/* Interrupt Configuration. */
|
||||
irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
|
||||
irq = (offset - 0xc00) * 4;
|
||||
if (irq >= s->num_irq)
|
||||
goto bad_reg;
|
||||
if (irq < GIC_NR_SGIS)
|
||||
|
|
|
@ -191,7 +191,6 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
|
|||
s->num_cpu, GIC_NCPU);
|
||||
return;
|
||||
}
|
||||
s->num_irq += GIC_BASE_IRQ;
|
||||
if (s->num_irq > GIC_MAXIRQ) {
|
||||
error_setg(errp,
|
||||
"requested %u interrupt lines exceeds GIC maximum %d",
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
|
||||
|
||||
#define GIC_BASE_IRQ 0
|
||||
|
||||
#define GIC_DIST_SET_ENABLED(irq, cm) (s->irq_state[irq].enabled |= (cm))
|
||||
#define GIC_DIST_CLEAR_ENABLED(irq, cm) (s->irq_state[irq].enabled &= ~(cm))
|
||||
#define GIC_DIST_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
|
||||
|
|
|
@ -139,94 +139,6 @@ static const MemoryRegionOps pcnet_io_ops = {
|
|||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void pcnet_mmio_writeb(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
|
||||
trace_pcnet_mmio_writeb(opaque, addr, val);
|
||||
if (!(addr & 0x10))
|
||||
pcnet_aprom_writeb(d, addr & 0x0f, val);
|
||||
}
|
||||
|
||||
static uint32_t pcnet_mmio_readb(void *opaque, hwaddr addr)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
uint32_t val = -1;
|
||||
|
||||
if (!(addr & 0x10))
|
||||
val = pcnet_aprom_readb(d, addr & 0x0f);
|
||||
trace_pcnet_mmio_readb(opaque, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pcnet_mmio_writew(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
|
||||
trace_pcnet_mmio_writew(opaque, addr, val);
|
||||
if (addr & 0x10)
|
||||
pcnet_ioport_writew(d, addr & 0x0f, val);
|
||||
else {
|
||||
addr &= 0x0f;
|
||||
pcnet_aprom_writeb(d, addr, val & 0xff);
|
||||
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pcnet_mmio_readw(void *opaque, hwaddr addr)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
uint32_t val = -1;
|
||||
|
||||
if (addr & 0x10)
|
||||
val = pcnet_ioport_readw(d, addr & 0x0f);
|
||||
else {
|
||||
addr &= 0x0f;
|
||||
val = pcnet_aprom_readb(d, addr+1);
|
||||
val <<= 8;
|
||||
val |= pcnet_aprom_readb(d, addr);
|
||||
}
|
||||
trace_pcnet_mmio_readw(opaque, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pcnet_mmio_writel(void *opaque, hwaddr addr, uint32_t val)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
|
||||
trace_pcnet_mmio_writel(opaque, addr, val);
|
||||
if (addr & 0x10)
|
||||
pcnet_ioport_writel(d, addr & 0x0f, val);
|
||||
else {
|
||||
addr &= 0x0f;
|
||||
pcnet_aprom_writeb(d, addr, val & 0xff);
|
||||
pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
|
||||
pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
|
||||
pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pcnet_mmio_readl(void *opaque, hwaddr addr)
|
||||
{
|
||||
PCNetState *d = opaque;
|
||||
uint32_t val;
|
||||
|
||||
if (addr & 0x10)
|
||||
val = pcnet_ioport_readl(d, addr & 0x0f);
|
||||
else {
|
||||
addr &= 0x0f;
|
||||
val = pcnet_aprom_readb(d, addr+3);
|
||||
val <<= 8;
|
||||
val |= pcnet_aprom_readb(d, addr+2);
|
||||
val <<= 8;
|
||||
val |= pcnet_aprom_readb(d, addr+1);
|
||||
val <<= 8;
|
||||
val |= pcnet_aprom_readb(d, addr);
|
||||
}
|
||||
trace_pcnet_mmio_readl(opaque, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pci_pcnet = {
|
||||
.name = "pcnet",
|
||||
.version_id = 3,
|
||||
|
@ -241,10 +153,12 @@ static const VMStateDescription vmstate_pci_pcnet = {
|
|||
/* PCI interface */
|
||||
|
||||
static const MemoryRegionOps pcnet_mmio_ops = {
|
||||
.old_mmio = {
|
||||
.read = { pcnet_mmio_readb, pcnet_mmio_readw, pcnet_mmio_readl },
|
||||
.write = { pcnet_mmio_writeb, pcnet_mmio_writew, pcnet_mmio_writel },
|
||||
},
|
||||
.read = pcnet_ioport_read,
|
||||
.write = pcnet_ioport_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 4,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 4,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
|
|
|
@ -61,12 +61,6 @@ pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) "opaque=%p addr=0x
|
|||
pcnet_aprom_readb(void *opaque, uint32_t addr, uint32_t val) "opaque=%p addr=0x%08x val=0x%02x"
|
||||
pcnet_ioport_read(void *opaque, uint64_t addr, unsigned size) "opaque=%p addr=0x%"PRIx64" size=%d"
|
||||
pcnet_ioport_write(void *opaque, uint64_t addr, uint64_t data, unsigned size) "opaque=%p addr=0x%"PRIx64" data=0x%"PRIx64" size=%d"
|
||||
pcnet_mmio_writeb(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
pcnet_mmio_writew(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
pcnet_mmio_writel(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
pcnet_mmio_readb(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
pcnet_mmio_readw(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
pcnet_mmio_readl(void *opaque, uint64_t addr, uint32_t val) "opaque=%p addr=0x%"PRIx64" val=0x%x"
|
||||
|
||||
# hw/net/net_rx_pkt.c
|
||||
net_rx_pkt_parsed(bool ip4, bool ip6, bool udp, bool tcp, size_t l3o, size_t l4o, size_t l5o) "RX packet parsed: ip4: %d, ip6: %d, udp: %d, tcp: %d, l3 offset: %zu, l4 offset: %zu, l5 offset: %zu"
|
||||
|
|
|
@ -388,8 +388,8 @@ static uint64_t aspeed_smc_flash_default_read(void *opaque, hwaddr addr,
|
|||
static void aspeed_smc_flash_default_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: To 0x%" HWADDR_PRIx " of size %u: 0x%"
|
||||
PRIx64 "\n", __func__, addr, size, data);
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: To 0x%" HWADDR_PRIx " of size %u: 0x%"
|
||||
PRIx64 "\n", __func__, addr, size, data);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_smc_flash_default_ops = {
|
||||
|
@ -529,7 +529,7 @@ static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
|
|||
*/
|
||||
if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
|
||||
for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
|
||||
ssi_transfer(fl->controller->spi, 0xFF);
|
||||
ssi_transfer(fl->controller->spi, 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -567,7 +567,7 @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
|
|||
}
|
||||
|
||||
static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
unsigned size)
|
||||
unsigned size)
|
||||
{
|
||||
AspeedSMCFlash *fl = opaque;
|
||||
AspeedSMCState *s = fl->controller;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/timer/aspeed_timer.h"
|
||||
#include "hw/misc/aspeed_scu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/timer.h"
|
||||
|
|
|
@ -296,9 +296,11 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
|
|||
case A_TIMERITCR:
|
||||
s->timeritcr = value & R_TIMERITCR_VALID_MASK;
|
||||
cmsdk_apb_dualtimer_update(s);
|
||||
break;
|
||||
case A_TIMERITOP:
|
||||
s->timeritop = value & R_TIMERITOP_VALID_MASK;
|
||||
cmsdk_apb_dualtimer_update(s);
|
||||
break;
|
||||
default:
|
||||
bad_offset:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Aspeed Machines
|
||||
*
|
||||
* Copyright 2018 IBM Corp.
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef ARM_ASPEED_H
|
||||
#define ARM_ASPEED_H
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
typedef struct AspeedBoardState AspeedBoardState;
|
||||
|
||||
typedef struct AspeedBoardConfig {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
const char *soc_name;
|
||||
uint32_t hw_strap1;
|
||||
const char *fmc_model;
|
||||
const char *spi_model;
|
||||
uint32_t num_cs;
|
||||
void (*i2c_init)(AspeedBoardState *bmc);
|
||||
} AspeedBoardConfig;
|
||||
|
||||
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
|
||||
#define ASPEED_MACHINE(obj) \
|
||||
OBJECT_CHECK(AspeedMachine, (obj), TYPE_ASPEED_MACHINE)
|
||||
|
||||
typedef struct AspeedMachine {
|
||||
MachineState parent_obj;
|
||||
} AspeedMachine;
|
||||
|
||||
#define ASPEED_MACHINE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedMachineClass, (klass), TYPE_ASPEED_MACHINE)
|
||||
#define ASPEED_MACHINE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedMachineClass, (obj), TYPE_ASPEED_MACHINE)
|
||||
|
||||
typedef struct AspeedMachineClass {
|
||||
MachineClass parent_obj;
|
||||
const AspeedBoardConfig *board;
|
||||
} AspeedMachineClass;
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Nordic Semiconductor nRF51 SoC
|
||||
*
|
||||
* Copyright 2018 Joel Stanley <joel@jms.id.au>
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef NRF51_SOC_H
|
||||
#define NRF51_SOC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/arm/armv7m.h"
|
||||
|
||||
#define TYPE_NRF51_SOC "nrf51-soc"
|
||||
#define NRF51_SOC(obj) \
|
||||
OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
|
||||
|
||||
typedef struct NRF51State {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
ARMv7MState cpu;
|
||||
|
||||
MemoryRegion iomem;
|
||||
MemoryRegion sram;
|
||||
MemoryRegion flash;
|
||||
|
||||
uint32_t sram_size;
|
||||
uint32_t flash_size;
|
||||
|
||||
MemoryRegion *board_memory;
|
||||
|
||||
MemoryRegion container;
|
||||
|
||||
} NRF51State;
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,49 @@
|
|||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* QEMU interface:
|
||||
* + QOM property "num-cpu": number of CPUs to support
|
||||
* + QOM property "num-irq": number of IRQs (including both SPIs and PPIs)
|
||||
* + QOM property "revision": GIC version (1 or 2), or 0 for the 11MPCore GIC
|
||||
* + QOM property "has-security-extensions": set true if the GIC should
|
||||
* implement the security extensions
|
||||
* + QOM property "has-virtualization-extensions": set true if the GIC should
|
||||
* implement the virtualization extensions
|
||||
* + unnamed GPIO inputs: (where P is number of SPIs, i.e. num-irq - 32)
|
||||
* [0..P-1] SPIs
|
||||
* [P..P+31] PPIs for CPU 0
|
||||
* [P+32..P+63] PPIs for CPU 1
|
||||
* ...
|
||||
* + sysbus IRQs: (in order; number will vary depending on number of cores)
|
||||
* - IRQ for CPU 0
|
||||
* - IRQ for CPU 1
|
||||
* ...
|
||||
* - FIQ for CPU 0
|
||||
* - FIQ for CPU 1
|
||||
* ...
|
||||
* - VIRQ for CPU 0 (exists even if virt extensions not present)
|
||||
* - VIRQ for CPU 1 (exists even if virt extensions not present)
|
||||
* ...
|
||||
* - VFIQ for CPU 0 (exists even if virt extensions not present)
|
||||
* - VFIQ for CPU 1 (exists even if virt extensions not present)
|
||||
* ...
|
||||
* - maintenance IRQ for CPU i/f 0 (only if virt extensions present)
|
||||
* - maintenance IRQ for CPU i/f 1 (only if virt extensions present)
|
||||
* + sysbus MMIO regions: (in order; numbers will vary depending on
|
||||
* whether virtualization extensions are present and on number of cores)
|
||||
* - distributor registers (GICD*)
|
||||
* - CPU interface for the accessing core (GICC*)
|
||||
* - virtual interface control registers (GICH*) (only if virt extns present)
|
||||
* - virtual CPU interface for the accessing core (GICV*) (only if virt)
|
||||
* - CPU 0 CPU interface registers
|
||||
* - CPU 1 CPU interface registers
|
||||
* ...
|
||||
* - CPU 0 virtual interface control registers (only if virt extns present)
|
||||
* - CPU 1 virtual interface control registers (only if virt extns present)
|
||||
* ...
|
||||
*/
|
||||
|
||||
#ifndef HW_ARM_GIC_H
|
||||
#define HW_ARM_GIC_H
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
#define ASPEED_TIMER_H
|
||||
|
||||
#include "qemu/timer.h"
|
||||
|
||||
typedef struct AspeedSCUState AspeedSCUState;
|
||||
#include "hw/misc/aspeed_scu.h"
|
||||
|
||||
#define ASPEED_TIMER(obj) \
|
||||
OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
|
||||
|
|
|
@ -199,8 +199,18 @@ static void arm_cpu_reset(CPUState *s)
|
|||
env->cp15.c15_cpar = 1;
|
||||
}
|
||||
#else
|
||||
/* SVC mode with interrupts disabled. */
|
||||
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||
|
||||
/*
|
||||
* If the highest available EL is EL2, AArch32 will start in Hyp
|
||||
* mode; otherwise it starts in SVC. Note that if we start in
|
||||
* AArch64 then these values in the uncached_cpsr will be ignored.
|
||||
*/
|
||||
if (arm_feature(env, ARM_FEATURE_EL2) &&
|
||||
!arm_feature(env, ARM_FEATURE_EL3)) {
|
||||
env->uncached_cpsr = ARM_CPU_MODE_HYP;
|
||||
} else {
|
||||
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||
}
|
||||
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
|
|
|
@ -12587,36 +12587,39 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
uint32_t flags;
|
||||
|
||||
if (is_a64(env)) {
|
||||
int sve_el = sve_exception_el(env);
|
||||
uint32_t zcr_len;
|
||||
|
||||
*pc = env->pc;
|
||||
flags = ARM_TBFLAG_AARCH64_STATE_MASK;
|
||||
/* Get control bits for tagged addresses */
|
||||
flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
|
||||
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
|
||||
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
|
||||
|
||||
/* If SVE is disabled, but FP is enabled,
|
||||
then the effective len is 0. */
|
||||
if (sve_el != 0 && fp_el == 0) {
|
||||
zcr_len = 0;
|
||||
} else {
|
||||
int current_el = arm_current_el(env);
|
||||
ARMCPU *cpu = arm_env_get_cpu(env);
|
||||
if (arm_feature(env, ARM_FEATURE_SVE)) {
|
||||
int sve_el = sve_exception_el(env);
|
||||
uint32_t zcr_len;
|
||||
|
||||
zcr_len = cpu->sve_max_vq - 1;
|
||||
if (current_el <= 1) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
|
||||
}
|
||||
if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
|
||||
}
|
||||
if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
|
||||
/* If SVE is disabled, but FP is enabled,
|
||||
* then the effective len is 0.
|
||||
*/
|
||||
if (sve_el != 0 && fp_el == 0) {
|
||||
zcr_len = 0;
|
||||
} else {
|
||||
int current_el = arm_current_el(env);
|
||||
ARMCPU *cpu = arm_env_get_cpu(env);
|
||||
|
||||
zcr_len = cpu->sve_max_vq - 1;
|
||||
if (current_el <= 1) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
|
||||
}
|
||||
if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
|
||||
}
|
||||
if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
|
||||
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
|
||||
}
|
||||
}
|
||||
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
|
||||
flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
|
||||
}
|
||||
flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
|
||||
} else {
|
||||
*pc = env->regs[15];
|
||||
flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
|
||||
|
|
Loading…
Reference in New Issue