target-arm queue:

* remove "bag of random stuff" hw/devices.h header
  * implement FPU for Cortex-M and enable it for Cortex-M4 and -M33
  * hw/dma: Compile the bcm2835_dma device as common object
  * configure: Remove --source-path option
  * hw/ssi/xilinx_spips: Avoid variable length array
  * hw/arm/smmuv3: Remove SMMUNotifierNode
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAlzHLVEZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3u4IEACgXvwJEEQaSGXHYlk52q5s
 JB2ZqbiwnbCo3MYo0XVu96O5jPdzGTBWumDsfmpZXDiOwlEP39QIhI3vIN35dCDn
 BIvby+NJdct4Un4Ln2yT6kdoTPjfCuwWWiekxsfiwXPUwXHciCoiS8QvuvutiKjF
 zi3ONV2hU+E0J9sqGfgOkCfpTrusNULms4H8KecqTquVrukvsn8AhCWRrbHOSiLw
 4V9MZq0Wqgl7VaObmsIEJcvj8lTKddiBndsqgLsrjLZsvmVnw2ycADggHIEkxzO9
 +U4gkhYbLydjHt5RYKh5QQSXaEavXPylBOzlliLXwUQzQNgNL7kaZr4JeB2RW2/V
 VAk2vCT1jU+7IqmTOvGk/CSVzLZipphCmYqHtwvOHdL5ngdnvdCiyjNMwq1Ha3aI
 W3L/QJ6eURNKm27w4as5X9iwE+/rE7CKMIwEBn2A6im8yP8Zy4Z/CfLsrYQH557Y
 ckbBWrtCKyJI26xNOgIuFt+wA2ge1c58j3nXltlXDgWsErg7GR9+NacxQUByUhV/
 Pf6KYX88zA0PBDPnuGsKkNbRl0rP/ndP66eol0q+KJxTPxyHDD4wJ4nX71JekGR1
 P79z9C7agNIUledP0QkMcN+hvb7JAv+PNkjv1Rq+6UD2bQxuGdtzqcGrDtje3w8z
 BQIb6EyNyBiVfeu3C3u3wQ==
 =jQTu
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190429' into staging

target-arm queue:
 * remove "bag of random stuff" hw/devices.h header
 * implement FPU for Cortex-M and enable it for Cortex-M4 and -M33
 * hw/dma: Compile the bcm2835_dma device as common object
 * configure: Remove --source-path option
 * hw/ssi/xilinx_spips: Avoid variable length array
 * hw/arm/smmuv3: Remove SMMUNotifierNode

# gpg: Signature made Mon 29 Apr 2019 17:58:57 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20190429: (42 commits)
  hw/devices: Move SMSC 91C111 declaration into a new header
  hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string
  hw/net/ne2000-isa: Add guards to the header
  hw/devices: Move LAN9118 declarations into a new header
  hw/devices: Move TI touchscreen declarations into a new header
  hw/devices: Move Gamepad declarations into a new header
  hw/devices: Move CBus declarations into a new header
  hw/devices: Move Blizzard declarations into a new header
  hw/devices: Move TC6393XB declarations into a new header
  hw/display/tc6393xb: Remove unused functions
  hw/arm/nseries: Use TYPE_TMP105 instead of hardcoded string
  hw/arm/aspeed: Use TYPE_TMP105/TYPE_PCA9552 instead of hardcoded string
  hw/dma: Compile the bcm2835_dma device as common object
  target/arm: Enable FPU for Cortex-M4 and Cortex-M33
  target/arm: Implement VLLDM for v7M CPUs with an FPU
  target/arm: Implement VLSTM for v7M CPUs with an FPU
  target/arm: Implement M-profile lazy FP state preservation
  target/arm: Add lazy-FP-stacking support to v7m_stack_write()
  target/arm: New function armv7m_nvic_set_pending_lazyfp()
  target/arm: New helper function arm_v7m_mmu_idx_all()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-04-29 18:05:56 +01:00
commit 82b2865e0d
50 changed files with 1595 additions and 235 deletions

View File

@ -663,10 +663,14 @@ M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Odd Fixes
F: hw/arm/nseries.c
F: hw/display/blizzard.c
F: hw/input/lm832x.c
F: hw/input/tsc2005.c
F: hw/misc/cbus.c
F: hw/timer/twl92230.c
F: include/hw/display/blizzard.h
F: include/hw/input/tsc2xxx.h
F: include/hw/misc/cbus.h
Palm
M: Andrzej Zaborowski <balrogg@gmail.com>
@ -675,6 +679,7 @@ L: qemu-arm@nongnu.org
S: Odd Fixes
F: hw/arm/palm.c
F: hw/input/tsc210x.c
F: include/hw/input/tsc2xxx.h
Raspberry Pi
M: Peter Maydell <peter.maydell@linaro.org>
@ -714,6 +719,7 @@ F: hw/misc/mst_fpga.c
F: hw/misc/max111x.c
F: include/hw/arm/pxa.h
F: include/hw/arm/sharpsl.h
F: include/hw/display/tc6393xb.h
SABRELITE / i.MX6
M: Peter Maydell <peter.maydell@linaro.org>
@ -740,6 +746,7 @@ M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/stellaris*
F: include/hw/input/gamepad.h
Versatile Express
M: Peter Maydell <peter.maydell@linaro.org>

10
configure vendored
View File

@ -278,6 +278,8 @@ ld_has() {
# default parameters
source_path=$(dirname "$0")
# make source path absolute
source_path=$(cd "$source_path"; pwd)
cpu=""
iasl="iasl"
interp_prefix="/usr/gnemul/qemu-%M"
@ -520,8 +522,6 @@ for opt do
;;
--cxx=*) CXX="$optarg"
;;
--source-path=*) source_path="$optarg"
;;
--cpu=*) cpu="$optarg"
;;
--extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
@ -600,9 +600,6 @@ if test "$debug_info" = "yes"; then
LDFLAGS="-g $LDFLAGS"
fi
# make source path absolute
source_path=$(cd "$source_path"; pwd)
# running configure in the source tree?
# we know that's the case if configure is there.
if test -f "./configure"; then
@ -946,8 +943,6 @@ for opt do
;;
--interp-prefix=*) interp_prefix="$optarg"
;;
--source-path=*)
;;
--cross-prefix=*)
;;
--cc=*)
@ -1651,7 +1646,6 @@ $(echo Available targets: $default_target_list | \
--target-list-exclude=LIST exclude a set of targets from the default target-list
Advanced options (experts only):
--source-path=PATH path of source code [$source_path]
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
--cc=CC use C compiler CC [$cc]
--iasl=IASL use ACPI compiler IASL [$iasl]

View File

@ -19,6 +19,8 @@
#include "hw/arm/aspeed_soc.h"
#include "hw/boards.h"
#include "hw/i2c/smbus_eeprom.h"
#include "hw/misc/pca9552.h"
#include "hw/misc/tmp105.h"
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "hw/loader.h"
@ -267,7 +269,8 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
eeprom_buf);
/* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7),
TYPE_TMP105, 0x4d);
/* The AST2500 EVB does not have an RTC. Let's pretend that one is
* plugged on the I2C bus header */
@ -288,13 +291,15 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
AspeedSoCState *soc = &bmc->soc;
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
0x60);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
/* The Witherspoon expects a TMP275 but a TMP105 is compatible */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp105", 0x4a);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), TYPE_TMP105,
0x4a);
/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
* good enough */
@ -302,7 +307,7 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
eeprom_buf);
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "pca9552",
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
0x60);
}

View File

@ -32,6 +32,7 @@
#include "hw/arm/arm.h"
#include "exec/address-spaces.h"
#include "hw/arm/exynos4210.h"
#include "hw/net/lan9118.h"
#include "hw/boards.h"
#undef DEBUG
@ -92,7 +93,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
/* This should be a 9215 but the 9118 is close enough */
if (nd_table[0].used) {
qemu_check_nic_model(&nd_table[0], "lan9118");
dev = qdev_create(NULL, "lan9118");
dev = qdev_create(NULL, TYPE_LAN9118);
qdev_set_nic_properties(dev, &nd_table[0]);
qdev_prop_set_uint32(dev, "mode_16bit", 1);
qdev_init_nofail(dev);

View File

@ -40,7 +40,7 @@
#include "hw/arm/pxa.h"
#include "net/net.h"
#include "hw/block/flash.h"
#include "hw/devices.h"
#include "hw/net/smc91c111.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"

View File

@ -12,10 +12,10 @@
#include "qemu-common.h"
#include "cpu.h"
#include "hw/sysbus.h"
#include "hw/devices.h"
#include "hw/boards.h"
#include "hw/arm/arm.h"
#include "hw/misc/arm_integrator_debug.h"
#include "hw/net/smc91c111.h"
#include "net/net.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"

View File

@ -22,7 +22,7 @@
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "net/net.h"
#include "hw/devices.h"
#include "hw/net/lan9118.h"
#include "hw/char/serial.h"
#include "sysemu/qtest.h"

View File

@ -18,7 +18,7 @@
#include "hw/arm/pxa.h"
#include "hw/arm/arm.h"
#include "net/net.h"
#include "hw/devices.h"
#include "hw/net/smc91c111.h"
#include "hw/boards.h"
#include "hw/block/flash.h"
#include "hw/sysbus.h"

View File

@ -56,6 +56,7 @@
#include "hw/arm/armsse.h"
#include "hw/dma/pl080.h"
#include "hw/ssi/pl022.h"
#include "hw/net/lan9118.h"
#include "net/net.h"
#include "hw/core/split-irq.h"
@ -244,7 +245,7 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
* except that it doesn't support the checksum-offload feature.
*/
qemu_check_nic_model(nd, "lan9118");
mms->lan9118 = qdev_create(NULL, "lan9118");
mms->lan9118 = qdev_create(NULL, TYPE_LAN9118);
qdev_set_nic_properties(mms->lan9118, nd);
qdev_init_nofail(mms->lan9118);

View File

@ -36,7 +36,7 @@
#include "hw/timer/cmsdk-apb-timer.h"
#include "hw/timer/cmsdk-apb-dualtimer.h"
#include "hw/misc/mps2-scc.h"
#include "hw/devices.h"
#include "hw/net/lan9118.h"
#include "net/net.h"
typedef enum MPS2FPGAType {

View File

@ -30,7 +30,10 @@
#include "ui/console.h"
#include "hw/boards.h"
#include "hw/i2c/i2c.h"
#include "hw/devices.h"
#include "hw/display/blizzard.h"
#include "hw/input/tsc2xxx.h"
#include "hw/misc/cbus.h"
#include "hw/misc/tmp105.h"
#include "hw/block/flash.h"
#include "hw/hw.h"
#include "hw/bt.h"
@ -218,7 +221,7 @@ static void n8x0_i2c_setup(struct n800_s *s)
qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
/* Attach a TMP105 PM chip (A0 wired to ground) */
dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR);
qdev_connect_gpio_out(dev, 0, tmp_irq);
}

View File

@ -26,7 +26,7 @@
#include "hw/arm/omap.h"
#include "hw/boards.h"
#include "hw/arm/arm.h"
#include "hw/devices.h"
#include "hw/input/tsc2xxx.h"
#include "hw/loader.h"
#include "exec/address-spaces.h"
#include "cpu.h"

View File

@ -14,7 +14,8 @@
#include "hw/sysbus.h"
#include "hw/arm/arm.h"
#include "hw/arm/primecell.h"
#include "hw/devices.h"
#include "hw/net/lan9118.h"
#include "hw/net/smc91c111.h"
#include "hw/pci/pci.h"
#include "net/net.h"
#include "sysemu/sysemu.h"

View File

@ -412,10 +412,10 @@ inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
/* Unmap all notifiers of all mr's */
void smmu_inv_notifiers_all(SMMUState *s)
{
SMMUNotifierNode *node;
SMMUDevice *sdev;
QLIST_FOREACH(node, &s->notifiers_list, next) {
smmu_inv_notifiers_mr(&node->sdev->iommu);
QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
smmu_inv_notifiers_mr(&sdev->iommu);
}
}

View File

@ -828,10 +828,10 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
/* invalidate an asid/iova tuple in all mr's */
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
{
SMMUNotifierNode *node;
SMMUDevice *sdev;
QLIST_FOREACH(node, &s->notifiers_list, next) {
IOMMUMemoryRegion *mr = &node->sdev->iommu;
QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
IOMMUMemoryRegion *mr = &sdev->iommu;
IOMMUNotifier *n;
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
@ -1472,8 +1472,6 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
SMMUDevice *sdev = container_of(iommu, SMMUDevice, iommu);
SMMUv3State *s3 = sdev->smmu;
SMMUState *s = &(s3->smmu_state);
SMMUNotifierNode *node = NULL;
SMMUNotifierNode *next_node = NULL;
if (new & IOMMU_NOTIFIER_MAP) {
int bus_num = pci_bus_num(sdev->bus);
@ -1485,22 +1483,10 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
if (old == IOMMU_NOTIFIER_NONE) {
trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
node = g_malloc0(sizeof(*node));
node->sdev = sdev;
QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
return;
}
/* update notifier node with new flags */
QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
if (node->sdev == sdev) {
if (new == IOMMU_NOTIFIER_NONE) {
trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
QLIST_REMOVE(node, next);
g_free(node);
}
return;
}
QLIST_INSERT_HEAD(&s->devices_with_notifiers, sdev, next);
} else if (new == IOMMU_NOTIFIER_NONE) {
trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
QLIST_REMOVE(sdev, next);
}
}

View File

@ -12,7 +12,6 @@
#include "hw/sysbus.h"
#include "hw/ssi/ssi.h"
#include "hw/arm/arm.h"
#include "hw/devices.h"
#include "qemu/timer.h"
#include "hw/i2c/i2c.h"
#include "net/net.h"
@ -22,6 +21,7 @@
#include "sysemu/sysemu.h"
#include "hw/arm/armv7m.h"
#include "hw/char/pl011.h"
#include "hw/input/gamepad.h"
#include "hw/watchdog/cmsdk-apb-watchdog.h"
#include "hw/misc/unimp.h"
#include "cpu.h"

View File

@ -16,10 +16,10 @@
#include "hw/hw.h"
#include "hw/arm/pxa.h"
#include "hw/arm/arm.h"
#include "hw/devices.h"
#include "hw/arm/sharpsl.h"
#include "hw/pcmcia.h"
#include "hw/boards.h"
#include "hw/display/tc6393xb.h"
#include "hw/i2c/i2c.h"
#include "hw/ssi/ssi.h"
#include "hw/sysbus.h"

View File

@ -13,7 +13,7 @@
#include "cpu.h"
#include "hw/sysbus.h"
#include "hw/arm/arm.h"
#include "hw/devices.h"
#include "hw/net/smc91c111.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/pci/pci.h"

View File

@ -28,7 +28,7 @@
#include "hw/sysbus.h"
#include "hw/arm/arm.h"
#include "hw/arm/primecell.h"
#include "hw/devices.h"
#include "hw/net/lan9118.h"
#include "hw/i2c/i2c.h"
#include "net/net.h"
#include "sysemu/sysemu.h"

View File

@ -21,7 +21,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "ui/console.h"
#include "hw/devices.h"
#include "hw/display/blizzard.h"
#include "ui/pixel_ops.h"
typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);

View File

@ -14,7 +14,7 @@
#include "qapi/error.h"
#include "qemu/host-utils.h"
#include "hw/hw.h"
#include "hw/devices.h"
#include "hw/display/tc6393xb.h"
#include "hw/block/flash.h"
#include "ui/console.h"
#include "ui/pixel_ops.h"
@ -137,11 +137,6 @@ struct TC6393xbState {
blanked : 1;
};
qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
{
return s->gpio_in;
}
static void tc6393xb_gpio_set(void *opaque, int line, int level)
{
// TC6393xbState *s = opaque;
@ -154,17 +149,6 @@ static void tc6393xb_gpio_set(void *opaque, int line, int level)
// FIXME: how does the chip reflect the GPIO input level change?
}
void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
qemu_irq handler)
{
if (line >= TC6393XB_GPIOS) {
fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line);
return;
}
s->handler[line] = handler;
}
static void tc6393xb_gpio_handler_update(TC6393xbState *s)
{
uint32_t level, diff;

View File

@ -14,4 +14,4 @@ common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
obj-$(CONFIG_RASPI) += bcm2835_dma.o
common-obj-$(CONFIG_RASPI) += bcm2835_dma.o

View File

@ -8,7 +8,7 @@
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/devices.h"
#include "hw/input/gamepad.h"
#include "ui/console.h"
typedef struct {

View File

@ -23,7 +23,7 @@
#include "hw/hw.h"
#include "qemu/timer.h"
#include "ui/console.h"
#include "hw/devices.h"
#include "hw/input/tsc2xxx.h"
#include "trace.h"
#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - (p ? 12 : 10)))

View File

@ -24,8 +24,8 @@
#include "audio/audio.h"
#include "qemu/timer.h"
#include "ui/console.h"
#include "hw/arm/omap.h" /* For I2SCodec and uWireSlave */
#include "hw/devices.h"
#include "hw/arm/omap.h" /* For I2SCodec */
#include "hw/input/tsc2xxx.h"
#define TSC_DATA_REGISTERS_PAGE 0x0
#define TSC_CONTROL_REGISTERS_PAGE 0x1

View File

@ -655,6 +655,102 @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
do_armv7m_nvic_set_pending(opaque, irq, secure, true);
}
void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
{
/*
* Pend an exception during lazy FP stacking. This differs
* from the usual exception pending because the logic for
* whether we should escalate depends on the saved context
* in the FPCCR register, not on the current state of the CPU/NVIC.
*/
NVICState *s = (NVICState *)opaque;
bool banked = exc_is_banked(irq);
VecInfo *vec;
bool targets_secure;
bool escalate = false;
/*
* We will only look at bits in fpccr if this is a banked exception
* (in which case 'secure' tells us whether it is the S or NS version).
* All the bits for the non-banked exceptions are in fpccr_s.
*/
uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S];
uint32_t fpccr = s->cpu->env.v7m.fpccr[secure];
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
assert(!secure || banked);
vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
targets_secure = banked ? secure : exc_targets_secure(s, irq);
switch (irq) {
case ARMV7M_EXCP_DEBUG:
if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) {
/* Ignore DebugMonitor exception */
return;
}
break;
case ARMV7M_EXCP_MEM:
escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK);
break;
case ARMV7M_EXCP_USAGE:
escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK);
break;
case ARMV7M_EXCP_BUS:
escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK);
break;
case ARMV7M_EXCP_SECURE:
escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK);
break;
default:
g_assert_not_reached();
}
if (escalate) {
/*
* Escalate to HardFault: faults that initially targeted Secure
* continue to do so, even if HF normally targets NonSecure.
*/
irq = ARMV7M_EXCP_HARD;
if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
(targets_secure ||
!(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) {
vec = &s->sec_vectors[irq];
} else {
vec = &s->vectors[irq];
}
}
if (!vec->enabled ||
nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) {
if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) {
/*
* We want to escalate to HardFault but the context the
* FP state belongs to prevents the exception pre-empting.
*/
cpu_abort(&s->cpu->parent_obj,
"Lockup: can't escalate to HardFault during "
"lazy FP register stacking\n");
}
}
if (escalate) {
s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
}
if (!vec->pending) {
vec->pending = 1;
/*
* We do not call nvic_irq_update(), because we know our caller
* is going to handle causing us to take the exception by
* raising EXCP_LAZYFP, so raising the IRQ line would be
* pointless extra work. We just need to recompute the
* priorities so that armv7m_nvic_can_take_pending_exception()
* returns the right answer.
*/
nvic_recompute_state(s);
}
}
/* Make pending IRQ active. */
void armv7m_nvic_acknowledge_irq(void *opaque)
{
@ -746,6 +842,40 @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
return ret;
}
bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
{
/*
* Return whether an exception is "ready", i.e. it is enabled and is
* configured at a priority which would allow it to interrupt the
* current execution priority.
*
* irq and secure have the same semantics as for armv7m_nvic_set_pending():
* for non-banked exceptions secure is always false; for banked exceptions
* it indicates which of the exceptions is required.
*/
NVICState *s = (NVICState *)opaque;
bool banked = exc_is_banked(irq);
VecInfo *vec;
int running = nvic_exec_prio(s);
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
assert(!secure || banked);
/*
* HardFault is an odd special case: we always check against -1,
* even if we're secure and HardFault has priority -3; we never
* need to check for enabled state.
*/
if (irq == ARMV7M_EXCP_HARD) {
return running > -1;
}
vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
return vec->enabled &&
exc_group_prio(s, vec->prio, secure) < running;
}
/* callback when external interrupt line is changed */
static void set_irq_level(void *opaque, int n, int level)
{
@ -1077,6 +1207,16 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
}
case 0xd84: /* CSSELR */
return cpu->env.v7m.csselr[attrs.secure];
case 0xd88: /* CPACR */
if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
return 0;
}
return cpu->env.v7m.cpacr[attrs.secure];
case 0xd8c: /* NSACR */
if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
return 0;
}
return cpu->env.v7m.nsacr;
/* TODO: Implement debug registers. */
case 0xd90: /* MPU_TYPE */
/* Unified MPU; if the MPU is not present this value is zero */
@ -1222,6 +1362,49 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
return 0;
}
return cpu->env.v7m.sfar;
case 0xf34: /* FPCCR */
if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
return 0;
}
if (attrs.secure) {
return cpu->env.v7m.fpccr[M_REG_S];
} else {
/*
* NS can read LSPEN, CLRONRET and MONRDY. It can read
* BFRDY and HFRDY if AIRCR.BFHFNMINS != 0;
* other non-banked bits RAZ.
* TODO: MONRDY should RAZ/WI if DEMCR.SDME is set.
*/
uint32_t value = cpu->env.v7m.fpccr[M_REG_S];
uint32_t mask = R_V7M_FPCCR_LSPEN_MASK |
R_V7M_FPCCR_CLRONRET_MASK |
R_V7M_FPCCR_MONRDY_MASK;
if (s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
mask |= R_V7M_FPCCR_BFRDY_MASK | R_V7M_FPCCR_HFRDY_MASK;
}
value &= mask;
value |= cpu->env.v7m.fpccr[M_REG_NS];
return value;
}
case 0xf38: /* FPCAR */
if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
return 0;
}
return cpu->env.v7m.fpcar[attrs.secure];
case 0xf3c: /* FPDSCR */
if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
return 0;
}
return cpu->env.v7m.fpdscr[attrs.secure];
case 0xf40: /* MVFR0 */
return cpu->isar.mvfr0;
case 0xf44: /* MVFR1 */
return cpu->isar.mvfr1;
case 0xf48: /* MVFR2 */
return cpu->isar.mvfr2;
default:
bad_offset:
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
@ -1469,6 +1652,18 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
}
break;
case 0xd88: /* CPACR */
if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
/* We implement only the Floating Point extension's CP10/CP11 */
cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
}
break;
case 0xd8c: /* NSACR */
if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
/* We implement only the Floating Point extension's CP10/CP11 */
cpu->env.v7m.nsacr = value & (3 << 10);
}
break;
case 0xd90: /* MPU_TYPE */
return; /* RO */
case 0xd94: /* MPU_CTRL */
@ -1697,6 +1892,72 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
}
break;
}
case 0xf34: /* FPCCR */
if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
/* Not all bits here are banked. */
uint32_t fpccr_s;
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
/* Don't allow setting of bits not present in v7M */
value &= (R_V7M_FPCCR_LSPACT_MASK |
R_V7M_FPCCR_USER_MASK |
R_V7M_FPCCR_THREAD_MASK |
R_V7M_FPCCR_HFRDY_MASK |
R_V7M_FPCCR_MMRDY_MASK |
R_V7M_FPCCR_BFRDY_MASK |
R_V7M_FPCCR_MONRDY_MASK |
R_V7M_FPCCR_LSPEN_MASK |
R_V7M_FPCCR_ASPEN_MASK);
}
value &= ~R_V7M_FPCCR_RES0_MASK;
if (!attrs.secure) {
/* Some non-banked bits are configurably writable by NS */
fpccr_s = cpu->env.v7m.fpccr[M_REG_S];
if (!(fpccr_s & R_V7M_FPCCR_LSPENS_MASK)) {
uint32_t lspen = FIELD_EX32(value, V7M_FPCCR, LSPEN);
fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, LSPEN, lspen);
}
if (!(fpccr_s & R_V7M_FPCCR_CLRONRETS_MASK)) {
uint32_t cor = FIELD_EX32(value, V7M_FPCCR, CLRONRET);
fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, CLRONRET, cor);
}
if ((s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
uint32_t hfrdy = FIELD_EX32(value, V7M_FPCCR, HFRDY);
uint32_t bfrdy = FIELD_EX32(value, V7M_FPCCR, BFRDY);
fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
}
/* TODO MONRDY should RAZ/WI if DEMCR.SDME is set */
{
uint32_t monrdy = FIELD_EX32(value, V7M_FPCCR, MONRDY);
fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, MONRDY, monrdy);
}
/*
* All other non-banked bits are RAZ/WI from NS; write
* just the banked bits to fpccr[M_REG_NS].
*/
value &= R_V7M_FPCCR_BANKED_MASK;
cpu->env.v7m.fpccr[M_REG_NS] = value;
} else {
fpccr_s = value;
}
cpu->env.v7m.fpccr[M_REG_S] = fpccr_s;
}
break;
case 0xf38: /* FPCAR */
if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
value &= ~7;
cpu->env.v7m.fpcar[attrs.secure] = value;
}
break;
case 0xf3c: /* FPDSCR */
if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
value &= 0x07c00000;
cpu->env.v7m.fpdscr[attrs.secure] = value;
}
break;
case 0xf50: /* ICIALLU */
case 0xf58: /* ICIMVAU */
case 0xf5c: /* DCIMVAC */

View File

@ -23,7 +23,7 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/devices.h"
#include "hw/misc/cbus.h"
#include "sysemu/sysemu.h"
//#define DEBUG

View File

@ -14,7 +14,7 @@
#include "hw/sysbus.h"
#include "net/net.h"
#include "net/eth.h"
#include "hw/devices.h"
#include "hw/net/lan9118.h"
#include "sysemu/sysemu.h"
#include "hw/ptimer.h"
#include "qemu/log.h"
@ -175,7 +175,6 @@ static const VMStateDescription vmstate_lan9118_packet = {
}
};
#define TYPE_LAN9118 "lan9118"
#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
typedef struct {

View File

@ -10,7 +10,7 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "net/net.h"
#include "hw/devices.h"
#include "hw/net/smc91c111.h"
#include "qemu/log.h"
/* For crc32 */
#include <zlib.h>

View File

@ -429,12 +429,14 @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
static inline void stripe8(uint8_t *x, int num, bool dir)
{
uint8_t r[num];
memset(r, 0, sizeof(uint8_t) * num);
uint8_t r[MAX_NUM_BUSSES];
int idx[2] = {0, 0};
int bit[2] = {0, 7};
int d = dir;
assert(num <= MAX_NUM_BUSSES);
memset(r, 0, sizeof(uint8_t) * num);
for (idx[0] = 0; idx[0] < num; ++idx[0]) {
for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;

View File

@ -20,6 +20,7 @@
#include "exec/memory.h"
# define hw_omap_h "omap.h"
#include "hw/irq.h"
#include "hw/input/tsc2xxx.h"
#include "target/arm/cpu-qom.h"
#include "qemu/log.h"
@ -679,11 +680,6 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
struct uWireSlave {
uint16_t (*receive)(void *opaque);
void (*send)(void *opaque, uint16_t data);
void *opaque;
};
struct omap_uwire_s;
void omap_uwire_attach(struct omap_uwire_s *s,
uWireSlave *slave, int chipselect);

View File

@ -80,13 +80,9 @@ typedef struct SMMUDevice {
AddressSpace as;
uint32_t cfg_cache_hits;
uint32_t cfg_cache_misses;
QLIST_ENTRY(SMMUDevice) next;
} SMMUDevice;
typedef struct SMMUNotifierNode {
SMMUDevice *sdev;
QLIST_ENTRY(SMMUNotifierNode) next;
} SMMUNotifierNode;
typedef struct SMMUPciBus {
PCIBus *bus;
SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
@ -108,7 +104,7 @@ typedef struct SMMUState {
GHashTable *iotlb;
SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
PCIBus *pci_bus;
QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
uint8_t bus_num;
PCIBus *primary_bus;
} SMMUState;

View File

@ -1,62 +0,0 @@
#ifndef QEMU_DEVICES_H
#define QEMU_DEVICES_H
/* Devices that have nowhere better to go. */
#include "hw/hw.h"
#include "ui/console.h"
/* smc91c111.c */
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
/* lan9118.c */
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
/* tsc210x.c */
uWireSlave *tsc2102_init(qemu_irq pint);
uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
I2SCodec *tsc210x_codec(uWireSlave *chip);
uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
void tsc210x_set_transform(uWireSlave *chip,
MouseTransformInfo *info);
void tsc210x_key_event(uWireSlave *chip, int key, int down);
/* tsc2005.c */
void *tsc2005_init(qemu_irq pintdav);
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
/* stellaris_input.c */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
/* blizzard.c */
void *s1d13745_init(qemu_irq gpio_int);
void s1d13745_write(void *opaque, int dc, uint16_t value);
void s1d13745_write_block(void *opaque, int dc,
void *buf, size_t len, int pitch);
uint16_t s1d13745_read(void *opaque, int dc);
/* cbus.c */
typedef struct {
qemu_irq clk;
qemu_irq dat;
qemu_irq sel;
} CBus;
CBus *cbus_init(qemu_irq dat_out);
void cbus_attach(CBus *bus, void *slave_opaque);
void *retu_init(qemu_irq irq, int vilma);
void *tahvo_init(qemu_irq irq, int betty);
void retu_key_event(void *retu, int state);
/* tc6393xb.c */
typedef struct TC6393xbState TC6393xbState;
TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
uint32_t base, qemu_irq irq);
void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
qemu_irq handler);
qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
#endif

View File

@ -0,0 +1,22 @@
/*
* Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
*
* Copyright (C) 2008 Nokia Corporation
* Written by Andrzej Zaborowski
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_DISPLAY_BLIZZARD_H
#define HW_DISPLAY_BLIZZARD_H
#include "hw/irq.h"
void *s1d13745_init(qemu_irq gpio_int);
void s1d13745_write(void *opaque, int dc, uint16_t value);
void s1d13745_write_block(void *opaque, int dc,
void *buf, size_t len, int pitch);
uint16_t s1d13745_read(void *opaque, int dc);
#endif

View File

@ -0,0 +1,24 @@
/*
* Toshiba TC6393XB I/O Controller.
* Found in Sharp Zaurus SL-6000 (tosa) or some
* Toshiba e-Series PDAs.
*
* Copyright (c) 2007 Hervé Poussineau
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_DISPLAY_TC6393XB_H
#define HW_DISPLAY_TC6393XB_H
#include "exec/memory.h"
#include "hw/irq.h"
typedef struct TC6393xbState TC6393xbState;
TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
uint32_t base, qemu_irq irq);
qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
#endif

View File

@ -0,0 +1,19 @@
/*
* Gamepad style buttons connected to IRQ/GPIO lines
*
* Copyright (c) 2007 CodeSourcery.
* Written by Paul Brook
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_INPUT_GAMEPAD_H
#define HW_INPUT_GAMEPAD_H
#include "hw/irq.h"
/* stellaris_input.c */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
#endif

View File

@ -0,0 +1,36 @@
/*
* TI touchscreen controller
*
* Copyright (c) 2006 Andrzej Zaborowski
* Copyright (C) 2008 Nokia Corporation
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_INPUT_TSC2XXX_H
#define HW_INPUT_TSC2XXX_H
#include "hw/irq.h"
#include "ui/console.h"
typedef struct uWireSlave {
uint16_t (*receive)(void *opaque);
void (*send)(void *opaque, uint16_t data);
void *opaque;
} uWireSlave;
/* tsc210x.c */
uWireSlave *tsc2102_init(qemu_irq pint);
uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
I2SCodec *tsc210x_codec(uWireSlave *chip);
uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
void tsc210x_key_event(uWireSlave *chip, int key, int down);
/* tsc2005.c */
void *tsc2005_init(qemu_irq pintdav);
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
#endif

32
include/hw/misc/cbus.h Normal file
View File

@ -0,0 +1,32 @@
/*
* CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
* Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
* Based on reverse-engineering of a linux driver.
*
* Copyright (C) 2008 Nokia Corporation
* Written by Andrzej Zaborowski
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_MISC_CBUS_H
#define HW_MISC_CBUS_H
#include "hw/irq.h"
typedef struct {
qemu_irq clk;
qemu_irq dat;
qemu_irq sel;
} CBus;
CBus *cbus_init(qemu_irq dat_out);
void cbus_attach(CBus *bus, void *slave_opaque);
void *retu_init(qemu_irq irq, int vilma);
void *tahvo_init(qemu_irq irq, int betty);
void retu_key_event(void *retu, int state);
#endif

21
include/hw/net/lan9118.h Normal file
View File

@ -0,0 +1,21 @@
/*
* SMSC LAN9118 Ethernet interface emulation
*
* Copyright (c) 2009 CodeSourcery, LLC.
* Written by Paul Brook
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_NET_LAN9118_H
#define HW_NET_LAN9118_H
#include "hw/irq.h"
#include "net/net.h"
#define TYPE_LAN9118 "lan9118"
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
#endif

View File

@ -6,6 +6,10 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_NET_NE2K_ISA_H
#define HW_NET_NE2K_ISA_H
#include "hw/hw.h"
#include "hw/qdev.h"
#include "hw/isa/isa.h"
@ -31,3 +35,5 @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
}
return d;
}
#endif

View File

@ -0,0 +1,19 @@
/*
* SMSC 91C111 Ethernet interface emulation
*
* Copyright (c) 2005 CodeSourcery, LLC.
* Written by Paul Brook
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_NET_SMC91C111_H
#define HW_NET_SMC91C111_H
#include "hw/irq.h"
#include "net/net.h"
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
#endif

View File

@ -99,7 +99,6 @@ typedef struct RAMBlock RAMBlock;
typedef struct Range Range;
typedef struct SHPCDevice SHPCDevice;
typedef struct SSIBus SSIBus;
typedef struct uWireSlave uWireSlave;
typedef struct VirtIODevice VirtIODevice;
typedef struct Visitor Visitor;
typedef void SaveStateHandler(QEMUFile *f, void *opaque);

View File

@ -281,6 +281,11 @@ static void arm_cpu_reset(CPUState *s)
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
}
if (arm_feature(env, ARM_FEATURE_VFP)) {
env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
}
/* Unlike A/R profile, M profile defines the reset LR value */
env->regs[14] = 0xffffffff;
@ -1029,6 +1034,13 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
set_feature(env, ARM_FEATURE_THUMB_DSP);
}
/*
* We rely on no XScale CPU having VFP so we can use the same bits in the
* TB flags field for VECSTRIDE and XSCALE_CPAR.
*/
assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
arm_feature(env, ARM_FEATURE_XSCALE)));
if (arm_feature(env, ARM_FEATURE_V7) &&
!arm_feature(env, ARM_FEATURE_M) &&
!arm_feature(env, ARM_FEATURE_PMSA)) {
@ -1481,8 +1493,12 @@ static void cortex_m4_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_M);
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
set_feature(&cpu->env, ARM_FEATURE_VFP4);
cpu->midr = 0x410fc240; /* r0p0 */
cpu->pmsav7_dregion = 8;
cpu->isar.mvfr0 = 0x10110021;
cpu->isar.mvfr1 = 0x11000011;
cpu->isar.mvfr2 = 0x00000000;
cpu->id_pfr0 = 0x00000030;
cpu->id_pfr1 = 0x00000200;
cpu->id_dfr0 = 0x00100000;
@ -1509,9 +1525,13 @@ static void cortex_m33_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
set_feature(&cpu->env, ARM_FEATURE_VFP4);
cpu->midr = 0x410fd213; /* r0p3 */
cpu->pmsav7_dregion = 16;
cpu->sau_sregion = 8;
cpu->isar.mvfr0 = 0x10110021;
cpu->isar.mvfr1 = 0x11000011;
cpu->isar.mvfr2 = 0x00000040;
cpu->id_pfr0 = 0x00000030;
cpu->id_pfr1 = 0x00000210;
cpu->id_dfr0 = 0x00200000;

View File

@ -57,6 +57,9 @@
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
#define ARMV7M_EXCP_RESET 1
@ -533,6 +536,11 @@ typedef struct CPUARMState {
uint32_t scr[M_REG_NUM_BANKS];
uint32_t msplim[M_REG_NUM_BANKS];
uint32_t psplim[M_REG_NUM_BANKS];
uint32_t fpcar[M_REG_NUM_BANKS];
uint32_t fpccr[M_REG_NUM_BANKS];
uint32_t fpdscr[M_REG_NUM_BANKS];
uint32_t cpacr[M_REG_NUM_BANKS];
uint32_t nsacr;
} v7m;
/* Information associated with an exception about to be taken:
@ -1576,6 +1584,35 @@ FIELD(V7M_CSSELR, LEVEL, 1, 3)
*/
FIELD(V7M_CSSELR, INDEX, 0, 4)
/* v7M FPCCR bits */
FIELD(V7M_FPCCR, LSPACT, 0, 1)
FIELD(V7M_FPCCR, USER, 1, 1)
FIELD(V7M_FPCCR, S, 2, 1)
FIELD(V7M_FPCCR, THREAD, 3, 1)
FIELD(V7M_FPCCR, HFRDY, 4, 1)
FIELD(V7M_FPCCR, MMRDY, 5, 1)
FIELD(V7M_FPCCR, BFRDY, 6, 1)
FIELD(V7M_FPCCR, SFRDY, 7, 1)
FIELD(V7M_FPCCR, MONRDY, 8, 1)
FIELD(V7M_FPCCR, SPLIMVIOL, 9, 1)
FIELD(V7M_FPCCR, UFRDY, 10, 1)
FIELD(V7M_FPCCR, RES0, 11, 15)
FIELD(V7M_FPCCR, TS, 26, 1)
FIELD(V7M_FPCCR, CLRONRETS, 27, 1)
FIELD(V7M_FPCCR, CLRONRET, 28, 1)
FIELD(V7M_FPCCR, LSPENS, 29, 1)
FIELD(V7M_FPCCR, LSPEN, 30, 1)
FIELD(V7M_FPCCR, ASPEN, 31, 1)
/* These bits are banked. Others are non-banked and live in the M_REG_S bank */
#define R_V7M_FPCCR_BANKED_MASK \
(R_V7M_FPCCR_LSPACT_MASK | \
R_V7M_FPCCR_USER_MASK | \
R_V7M_FPCCR_THREAD_MASK | \
R_V7M_FPCCR_MMRDY_MASK | \
R_V7M_FPCCR_SPLIMVIOL_MASK | \
R_V7M_FPCCR_UFRDY_MASK | \
R_V7M_FPCCR_ASPEN_MASK)
/*
* System register ID fields.
*/
@ -1974,6 +2011,18 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
* a different exception).
*/
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
/**
* armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
* @opaque: the NVIC
* @irq: the exception number to mark pending
* @secure: false for non-banked exceptions or for the nonsecure
* version of a banked exception, true for the secure version of a banked
* exception.
*
* Similar to armv7m_nvic_set_pending(), but specifically for exceptions
* generated in the course of lazy stacking of FP registers.
*/
void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
/**
* armv7m_nvic_get_pending_irq_info: return highest priority pending
* exception, and whether it targets Secure state
@ -2010,6 +2059,20 @@ void armv7m_nvic_acknowledge_irq(void *opaque);
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
*/
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
/**
* armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
* @opaque: the NVIC
* @irq: the exception number to mark pending
* @secure: false for non-banked exceptions or for the nonsecure
* version of a banked exception, true for the secure version of a banked
* exception.
*
* Return whether an exception is "ready", i.e. whether the exception is
* enabled and is configured at a priority which would allow it to
* interrupt the current execution priority. This controls whether the
* RDY bit for it in the FPCCR is set.
*/
bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure);
/**
* armv7m_nvic_raw_execution_priority: return the raw execution priority
* @opaque: the NVIC
@ -2863,6 +2926,13 @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
}
}
/*
* Return the MMU index for a v7M CPU with all relevant information
* manually specified.
*/
ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
bool secstate, bool priv, bool negpri);
/* Return the MMU index for a v7M CPU in the specified security and
* privilege state.
*/
@ -3090,18 +3160,27 @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
FIELD(TBFLAG_A32, THUMB, 0, 1)
FIELD(TBFLAG_A32, VECLEN, 1, 3)
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
FIELD(TBFLAG_A32, VFPEN, 7, 1)
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
/* We store the bottom two bits of the CPAR as TB flags and handle
* checks on the other bits at runtime
/*
* We store the bottom two bits of the CPAR as TB flags and handle
* checks on the other bits at runtime. This shares the same bits as
* VECSTRIDE, which is OK as no XScale CPU has VFP.
*/
FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
/* Indicates whether cp register reads and writes by guest code should access
FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
/*
* Indicates whether cp register reads and writes by guest code should access
* the secure or nonsecure bank of banked registers; note that this is not
* the same thing as the current security state of the processor!
*/
FIELD(TBFLAG_A32, NS, 19, 1)
FIELD(TBFLAG_A32, NS, 6, 1)
FIELD(TBFLAG_A32, VFPEN, 7, 1)
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
/* For M profile only, set if FPCCR.LSPACT is set */
FIELD(TBFLAG_A32, LSPACT, 18, 1)
/* For M profile only, set if we must create a new FP context */
FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
/* For M profile only, set if FPCCR.S does not match current security state */
FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
/* For M profile only, Handler (ie not Thread) mode */
FIELD(TBFLAG_A32, HANDLER, 21, 1)
/* For M profile only, whether we should generate stack-limit checks */

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,11 @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
DEF_HELPER_2(v7m_vlstm, void, env, i32)
DEF_HELPER_2(v7m_vlldm, void, env, i32)
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)

View File

@ -305,6 +305,21 @@ static const VMStateDescription vmstate_m_v8m = {
}
};
static const VMStateDescription vmstate_m_fp = {
.name = "cpu/m/fp",
.version_id = 1,
.minimum_version_id = 1,
.needed = vfp_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(env.v7m.fpcar, ARMCPU, M_REG_NUM_BANKS),
VMSTATE_UINT32_ARRAY(env.v7m.fpccr, ARMCPU, M_REG_NUM_BANKS),
VMSTATE_UINT32_ARRAY(env.v7m.fpdscr, ARMCPU, M_REG_NUM_BANKS),
VMSTATE_UINT32_ARRAY(env.v7m.cpacr, ARMCPU, M_REG_NUM_BANKS),
VMSTATE_UINT32(env.v7m.nsacr, ARMCPU),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_m = {
.name = "cpu/m",
.version_id = 4,
@ -330,6 +345,7 @@ static const VMStateDescription vmstate_m = {
&vmstate_m_scr,
&vmstate_m_other_sp,
&vmstate_m_v8m,
&vmstate_m_fp,
NULL
}
};

View File

@ -3399,8 +3399,14 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
* for attempts to execute invalid vfp/neon encodings with FP disabled.
*/
if (s->fp_excp_el) {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
if (arm_dc_feature(s, ARM_FEATURE_M)) {
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
s->fp_excp_el);
} else {
gen_exception_insn(s, 4, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false),
s->fp_excp_el);
}
return 0;
}
@ -3415,6 +3421,73 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
}
}
if (arm_dc_feature(s, ARM_FEATURE_M)) {
/* Handle M-profile lazy FP state mechanics */
/* Trigger lazy-state preservation if necessary */
if (s->v7m_lspact) {
/*
* Lazy state saving affects external memory and also the NVIC,
* so we must mark it as an IO operation for icount.
*/
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
gen_helper_v7m_preserve_fp_state(cpu_env);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_end();
}
/*
* If the preserve_fp_state helper doesn't throw an exception
* then it will clear LSPACT; we don't need to repeat this for
* any further FP insns in this TB.
*/
s->v7m_lspact = false;
}
/* Update ownership of FP context: set FPCCR.S to match current state */
if (s->v8m_fpccr_s_wrong) {
TCGv_i32 tmp;
tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
if (s->v8m_secure) {
tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
} else {
tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
}
store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
/* Don't need to do this for any further FP insns in this TB */
s->v8m_fpccr_s_wrong = false;
}
if (s->v7m_new_fp_ctxt_needed) {
/*
* Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
* and the FPSCR.
*/
TCGv_i32 control, fpscr;
uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
gen_helper_vfp_set_fpscr(cpu_env, fpscr);
tcg_temp_free_i32(fpscr);
/*
* We don't need to arrange to end the TB, because the only
* parts of FPSCR which we cache in the TB flags are the VECLEN
* and VECSTRIDE, and those don't exist for M-profile.
*/
if (s->v8m_secure) {
bits |= R_V7M_CONTROL_SFPA_MASK;
}
control = load_cpu_field(v7m.control[M_REG_S]);
tcg_gen_ori_i32(control, control, bits);
store_cpu_field(control, v7m.control[M_REG_S]);
/* Don't need to do this for any further FP insns in this TB */
s->v7m_new_fp_ctxt_needed = false;
}
}
if (extract32(insn, 28, 4) == 0xf) {
/*
* Encodings with T=1 (Thumb) or unconditional (ARM):
@ -3513,12 +3586,27 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
}
}
} else { /* !dp */
bool is_sysreg;
if ((insn & 0x6f) != 0x00)
return 1;
rn = VFP_SREG_N(insn);
is_sysreg = extract32(insn, 21, 1);
if (arm_dc_feature(s, ARM_FEATURE_M)) {
/*
* The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
* Writes to R15 are UNPREDICTABLE; we choose to undef.
*/
if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
return 1;
}
}
if (insn & ARM_CP_RW_BIT) {
/* vfp->arm */
if (insn & (1 << 21)) {
if (is_sysreg) {
/* system register */
rn >>= 1;
@ -3585,7 +3673,7 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
}
} else {
/* arm->vfp */
if (insn & (1 << 21)) {
if (is_sysreg) {
rn >>= 1;
/* system register */
switch (rn) {
@ -11707,10 +11795,19 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
case 6: case 7: case 14: case 15:
/* Coprocessor. */
if (arm_dc_feature(s, ARM_FEATURE_M)) {
/* We don't currently implement M profile FP support,
* so this entire space should give a NOCP fault, with
* the exception of the v8M VLLDM and VLSTM insns, which
* must be NOPs in Secure state and UNDEF in Nonsecure state.
/* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
if (extract32(insn, 24, 2) == 3) {
goto illegal_op; /* op0 = 0b11 : unallocated */
}
/*
* Decode VLLDM and VLSTM first: these are nonstandard because:
* * if there is no FPU then these insns must NOP in
* Secure state and UNDEF in Nonsecure state
* * if there is an FPU then these insns do not have
* the usual behaviour that disas_vfp_insn() provides of
* being controlled by CPACR/NSACR enable bits or the
* lazy-stacking logic.
*/
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
(insn & 0xffa00f00) == 0xec200a00) {
@ -11721,9 +11818,31 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
if (!s->v8m_secure || (insn & 0x0040f0ff)) {
goto illegal_op;
}
/* Just NOP since FP support is not implemented */
if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
TCGv_i32 fptr = load_reg(s, rn);
if (extract32(insn, 20, 1)) {
gen_helper_v7m_vlldm(cpu_env, fptr);
} else {
gen_helper_v7m_vlstm(cpu_env, fptr);
}
tcg_temp_free_i32(fptr);
/* End the TB, because we have updated FP control bits */
s->base.is_jmp = DISAS_UPDATE;
}
break;
}
if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
((insn >> 8) & 0xe) == 10) {
/* FP, and the CPU supports it */
if (disas_vfp_insn(s, insn)) {
goto illegal_op;
}
break;
}
/* All other insns: NOCP */
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
default_exception_el(s));
@ -13291,12 +13410,21 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
dc->vec_stride = 0;
} else {
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
dc->c15_cpar = 0;
}
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
regime_is_secure(env, dc->mmu_idx);
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
dc->v7m_new_fp_ctxt_needed =
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
dc->cp_regs = cpu->cp_regs;
dc->features = env->features;

View File

@ -40,6 +40,9 @@ typedef struct DisasContext {
bool v7m_handler_mode;
bool v8m_secure; /* true if v8M and we're in Secure mode */
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
bool v7m_lspact; /* FPCCR.LSPACT set */
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
* so that top level loop can generate correct syndrome information.
*/

View File

@ -105,6 +105,14 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
val &= ~FPCR_FZ16;
}
if (arm_feature(env, ARM_FEATURE_M)) {
/*
* M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
* and also for the trapped-exception-handling bits IxE.
*/
val &= 0xf7c0009f;
}
/*
* We don't implement trapped exception handling, so the
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)