1
Second pull request of the week; mostly RTH's support for some
1
First pullreq for arm of the 4.1 series, since I'm back from
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
2
holiday now. This is mostly my M-profile FPU series and Philippe's
3
devices.h cleanup. I have a pile of other patchsets to work through
4
in my to-review folder, but 42 patches is definitely quite
5
big enough to send now...
3
6
4
thanks
7
thanks
5
-- PMM
8
-- PMM
6
9
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
10
The following changes since commit 413a99a92c13ec408dcf2adaa87918dc81e890c8:
8
11
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
12
Add Nios II semihosting support. (2019-04-29 16:09:51 +0100)
10
13
11
are available in the Git repository at:
14
are available in the Git repository at:
12
15
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190429
14
17
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
18
for you to fetch changes up to 437cc27ddfded3bbab6afd5ac1761e0e195edba7:
16
19
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
20
hw/devices: Move SMSC 91C111 declaration into a new header (2019-04-29 17:57:21 +0100)
18
21
19
----------------------------------------------------------------
22
----------------------------------------------------------------
20
target-arm queue:
23
target-arm queue:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
24
* remove "bag of random stuff" hw/devices.h header
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
25
* implement FPU for Cortex-M and enable it for Cortex-M4 and -M33
23
that uses it
26
* hw/dma: Compile the bcm2835_dma device as common object
24
* decodetree: Propagate return value from translate subroutines
27
* configure: Remove --source-path option
25
* xlnx-zynqmp: Implement the RTC device
28
* hw/ssi/xilinx_spips: Avoid variable length array
29
* hw/arm/smmuv3: Remove SMMUNotifierNode
26
30
27
----------------------------------------------------------------
31
----------------------------------------------------------------
28
Alistair Francis (3):
32
Eric Auger (1):
29
xlnx-zynqmp-rtc: Initial commit
33
hw/arm/smmuv3: Remove SMMUNotifierNode
30
xlnx-zynqmp-rtc: Add basic time support
31
xlnx-zynqmp: Connect the RTC device
32
34
33
Peter Maydell (19):
35
Peter Maydell (28):
34
loader: Add new load_ramdisk_as()
36
hw/ssi/xilinx_spips: Avoid variable length array
35
hw/arm/boot: Honour CPU's address space for image loads
37
configure: Remove --source-path option
36
hw/arm/armv7m: Honour CPU's address space for image loads
38
target/arm: Make sure M-profile FPSCR RES0 bits are not settable
37
target/arm: Define an IDAU interface
39
hw/intc/armv7m_nvic: Allow reading of M-profile MVFR* registers
38
armv7m: Forward idau property to CPU object
40
target/arm: Implement dummy versions of M-profile FP-related registers
39
target/arm: Define init-svtor property for the reset secure VTOR value
41
target/arm: Disable most VFP sysregs for M-profile
40
armv7m: Forward init-svtor property to CPU object
42
target/arm: Honour M-profile FP enable bits
41
target/arm: Add Cortex-M33
43
target/arm: Decode FP instructions for M profile
42
hw/misc/unimp: Move struct to header file
44
target/arm: Clear CONTROL_S.SFPA in SG insn if FPU present
43
include/hw/or-irq.h: Add missing include guard
45
target/arm: Handle SFPA and FPCA bits in reads and writes of CONTROL
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
46
target/arm/helper: don't return early for STKOF faults during stacking
45
hw/core/split-irq: Device that splits IRQ lines
47
target/arm: Handle floating point registers in exception entry
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
48
target/arm: Implement v7m_update_fpccr()
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
49
target/arm: Clear CONTROL.SFPA in BXNS and BLXNS
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
50
target/arm: Clean excReturn bits when tail chaining
49
hw/misc/iotkit-secctl: Add handling for PPCs
51
target/arm: Allow for floating point in callee stack integrity check
50
hw/misc/iotkit-secctl: Add remaining simple registers
52
target/arm: Handle floating point registers in exception return
51
hw/arm/iotkit: Model Arm IOT Kit
53
target/arm: Move NS TBFLAG from bit 19 to bit 6
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
54
target/arm: Overlap VECSTRIDE and XSCALE_CPAR TB flags
55
target/arm: Set FPCCR.S when executing M-profile floating point insns
56
target/arm: Activate M-profile floating point context when FPCCR.ASPEN is set
57
target/arm: New helper function arm_v7m_mmu_idx_all()
58
target/arm: New function armv7m_nvic_set_pending_lazyfp()
59
target/arm: Add lazy-FP-stacking support to v7m_stack_write()
60
target/arm: Implement M-profile lazy FP state preservation
61
target/arm: Implement VLSTM for v7M CPUs with an FPU
62
target/arm: Implement VLLDM for v7M CPUs with an FPU
63
target/arm: Enable FPU for Cortex-M4 and Cortex-M33
53
64
54
Richard Henderson (17):
65
Philippe Mathieu-Daudé (13):
55
decodetree: Propagate return value from translate subroutines
66
hw/dma: Compile the bcm2835_dma device as common object
56
target/arm: Add ARM_FEATURE_V8_RDM
67
hw/arm/aspeed: Use TYPE_TMP105/TYPE_PCA9552 instead of hardcoded string
57
target/arm: Refactor disas_simd_indexed decode
68
hw/arm/nseries: Use TYPE_TMP105 instead of hardcoded string
58
target/arm: Refactor disas_simd_indexed size checks
69
hw/display/tc6393xb: Remove unused functions
59
target/arm: Decode aa64 armv8.1 scalar three same extra
70
hw/devices: Move TC6393XB declarations into a new header
60
target/arm: Decode aa64 armv8.1 three same extra
71
hw/devices: Move Blizzard declarations into a new header
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
72
hw/devices: Move CBus declarations into a new header
62
target/arm: Decode aa32 armv8.1 three same
73
hw/devices: Move Gamepad declarations into a new header
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
74
hw/devices: Move TI touchscreen declarations into a new header
64
target/arm: Enable ARM_FEATURE_V8_RDM
75
hw/devices: Move LAN9118 declarations into a new header
65
target/arm: Add ARM_FEATURE_V8_FCMA
76
hw/net/ne2000-isa: Add guards to the header
66
target/arm: Decode aa64 armv8.3 fcadd
77
hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string
67
target/arm: Decode aa64 armv8.3 fcmla
78
hw/devices: Move SMSC 91C111 declaration into a new header
68
target/arm: Decode aa32 armv8.3 3-same
69
target/arm: Decode aa32 armv8.3 2-reg-index
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
71
target/arm: Enable ARM_FEATURE_V8_FCMA
72
79
73
hw/arm/Makefile.objs | 2 +
80
configure | 10 +-
74
hw/core/Makefile.objs | 1 +
81
hw/dma/Makefile.objs | 2 +-
75
hw/misc/Makefile.objs | 4 +
82
include/hw/arm/omap.h | 6 +-
76
hw/timer/Makefile.objs | 1 +
83
include/hw/arm/smmu-common.h | 8 +-
77
target/arm/Makefile.objs | 2 +-
84
include/hw/devices.h | 62 ---
78
include/hw/arm/armv7m.h | 5 +
85
include/hw/display/blizzard.h | 22 ++
79
include/hw/arm/iotkit.h | 109 ++++++
86
include/hw/display/tc6393xb.h | 24 ++
80
include/hw/arm/xlnx-zynqmp.h | 2 +
87
include/hw/input/gamepad.h | 19 +
81
include/hw/core/split-irq.h | 57 +++
88
include/hw/input/tsc2xxx.h | 36 ++
82
include/hw/irq.h | 4 +-
89
include/hw/misc/cbus.h | 32 ++
83
include/hw/loader.h | 12 +-
90
include/hw/net/lan9118.h | 21 +
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
91
include/hw/net/ne2000-isa.h | 6 +
85
include/hw/misc/mps2-fpgaio.h | 43 +++
92
include/hw/net/smc91c111.h | 19 +
86
include/hw/misc/tz-ppc.h | 101 ++++++
93
include/qemu/typedefs.h | 1 -
87
include/hw/misc/unimp.h | 10 +
94
target/arm/cpu.h | 95 ++++-
88
include/hw/or-irq.h | 5 +
95
target/arm/helper.h | 5 +
89
include/hw/qdev-core.h | 30 +-
96
target/arm/translate.h | 3 +
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
97
hw/arm/aspeed.c | 13 +-
91
target/arm/cpu.h | 8 +
98
hw/arm/exynos4_boards.c | 3 +-
92
target/arm/helper.h | 31 ++
99
hw/arm/gumstix.c | 2 +-
93
target/arm/idau.h | 61 ++++
100
hw/arm/integratorcp.c | 2 +-
94
hw/arm/armv7m.c | 35 +-
101
hw/arm/kzm.c | 2 +-
95
hw/arm/boot.c | 119 ++++---
102
hw/arm/mainstone.c | 2 +-
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
103
hw/arm/mps2-tz.c | 3 +-
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
104
hw/arm/mps2.c | 2 +-
98
hw/arm/xlnx-zynqmp.c | 14 +
105
hw/arm/nseries.c | 7 +-
99
hw/core/loader.c | 8 +-
106
hw/arm/palm.c | 2 +-
100
hw/core/qdev.c | 8 +-
107
hw/arm/realview.c | 3 +-
101
hw/core/split-irq.c | 89 +++++
108
hw/arm/smmu-common.c | 6 +-
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
109
hw/arm/smmuv3.c | 28 +-
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
110
hw/arm/stellaris.c | 2 +-
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
111
hw/arm/tosa.c | 2 +-
105
hw/misc/unimp.c | 10 -
112
hw/arm/versatilepb.c | 2 +-
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
113
hw/arm/vexpress.c | 2 +-
107
linux-user/elfload.c | 2 +
114
hw/display/blizzard.c | 2 +-
108
target/arm/cpu.c | 66 +++-
115
hw/display/tc6393xb.c | 18 +-
109
target/arm/cpu64.c | 2 +
116
hw/input/stellaris_input.c | 2 +-
110
target/arm/helper.c | 28 +-
117
hw/input/tsc2005.c | 2 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
118
hw/input/tsc210x.c | 4 +-
112
target/arm/translate.c | 275 +++++++++++++--
119
hw/intc/armv7m_nvic.c | 261 +++++++++++++
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
120
hw/misc/cbus.c | 2 +-
114
default-configs/arm-softmmu.mak | 5 +
121
hw/net/lan9118.c | 3 +-
115
hw/misc/trace-events | 24 ++
122
hw/net/smc91c111.c | 2 +-
116
hw/timer/trace-events | 3 +
123
hw/ssi/xilinx_spips.c | 6 +-
117
scripts/decodetree.py | 5 +-
124
target/arm/cpu.c | 20 +
118
45 files changed, 4668 insertions(+), 200 deletions(-)
125
target/arm/helper.c | 873 +++++++++++++++++++++++++++++++++++++++---
119
create mode 100644 include/hw/arm/iotkit.h
126
target/arm/machine.c | 16 +
120
create mode 100644 include/hw/core/split-irq.h
127
target/arm/translate.c | 150 +++++++-
121
create mode 100644 include/hw/misc/iotkit-secctl.h
128
target/arm/vfp_helper.c | 8 +
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
129
MAINTAINERS | 7 +
123
create mode 100644 include/hw/misc/tz-ppc.h
130
50 files changed, 1595 insertions(+), 235 deletions(-)
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
131
delete mode 100644 include/hw/devices.h
125
create mode 100644 target/arm/idau.h
132
create mode 100644 include/hw/display/blizzard.h
126
create mode 100644 hw/arm/iotkit.c
133
create mode 100644 include/hw/display/tc6393xb.h
127
create mode 100644 hw/arm/mps2-tz.c
134
create mode 100644 include/hw/input/gamepad.h
128
create mode 100644 hw/core/split-irq.c
135
create mode 100644 include/hw/input/tsc2xxx.h
129
create mode 100644 hw/misc/iotkit-secctl.c
136
create mode 100644 include/hw/misc/cbus.h
130
create mode 100644 hw/misc/mps2-fpgaio.c
137
create mode 100644 include/hw/net/lan9118.h
131
create mode 100644 hw/misc/tz-ppc.c
138
create mode 100644 include/hw/net/smc91c111.h
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
139
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
The SMMUNotifierNode struct is not necessary and brings extra
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
complexity so let's remove it. We now directly track the SMMUDevices
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
which have registered IOMMU MR notifiers.
6
7
This is inspired from the same transformation on intel-iommu
8
done in commit b4a4ba0d68f50f218ee3957b6638dbee32a5eeef
9
("intel-iommu: remove IntelIOMMUNotifierNode")
10
11
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
Reviewed-by: Peter Xu <peterx@redhat.com>
13
Message-id: 20190409160219.19026-1-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
15
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
16
include/hw/arm/smmu-common.h | 8 ++------
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
17
hw/arm/smmu-common.c | 6 +++---
10
2 files changed, 16 insertions(+)
18
hw/arm/smmuv3.c | 28 +++++++---------------------
19
3 files changed, 12 insertions(+), 30 deletions(-)
11
20
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
21
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
23
--- a/include/hw/arm/smmu-common.h
15
+++ b/include/hw/arm/xlnx-zynqmp.h
24
+++ b/include/hw/arm/smmu-common.h
16
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUDevice {
17
#include "hw/dma/xlnx_dpdma.h"
26
AddressSpace as;
18
#include "hw/display/xlnx_dp.h"
27
uint32_t cfg_cache_hits;
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
28
uint32_t cfg_cache_misses;
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
29
+ QLIST_ENTRY(SMMUDevice) next;
21
30
} SMMUDevice;
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
31
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
32
-typedef struct SMMUNotifierNode {
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
33
- SMMUDevice *sdev;
25
XlnxDPState dp;
34
- QLIST_ENTRY(SMMUNotifierNode) next;
26
XlnxDPDMAState dpdma;
35
-} SMMUNotifierNode;
27
XlnxZynqMPIPI ipi;
36
-
28
+ XlnxZynqMPRTC rtc;
37
typedef struct SMMUPciBus {
29
38
PCIBus *bus;
30
char *boot_cpu;
39
SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
31
ARMCPU *boot_cpu_ptr;
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUState {
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
41
GHashTable *iotlb;
42
SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
43
PCIBus *pci_bus;
44
- QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
45
+ QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
46
uint8_t bus_num;
47
PCIBus *primary_bus;
48
} SMMUState;
49
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
33
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/xlnx-zynqmp.c
51
--- a/hw/arm/smmu-common.c
35
+++ b/hw/arm/xlnx-zynqmp.c
52
+++ b/hw/arm/smmu-common.c
36
@@ -XXX,XX +XXX,XX @@
53
@@ -XXX,XX +XXX,XX @@ inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
37
#define IPI_ADDR 0xFF300000
54
/* Unmap all notifiers of all mr's */
38
#define IPI_IRQ 64
55
void smmu_inv_notifiers_all(SMMUState *s)
39
56
{
40
+#define RTC_ADDR 0xffa60000
57
- SMMUNotifierNode *node;
41
+#define RTC_IRQ 26
58
+ SMMUDevice *sdev;
42
+
59
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
60
- QLIST_FOREACH(node, &s->notifiers_list, next) {
44
61
- smmu_inv_notifiers_mr(&node->sdev->iommu);
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
62
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
63
+ smmu_inv_notifiers_mr(&sdev->iommu);
47
64
}
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
53
}
65
}
54
66
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
67
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/arm/smmuv3.c
70
+++ b/hw/arm/smmuv3.c
71
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
72
/* invalidate an asid/iova tuple in all mr's */
73
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
74
{
75
- SMMUNotifierNode *node;
76
+ SMMUDevice *sdev;
77
78
- QLIST_FOREACH(node, &s->notifiers_list, next) {
79
- IOMMUMemoryRegion *mr = &node->sdev->iommu;
80
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
81
+ IOMMUMemoryRegion *mr = &sdev->iommu;
82
IOMMUNotifier *n;
83
84
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
85
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
86
SMMUDevice *sdev = container_of(iommu, SMMUDevice, iommu);
87
SMMUv3State *s3 = sdev->smmu;
88
SMMUState *s = &(s3->smmu_state);
89
- SMMUNotifierNode *node = NULL;
90
- SMMUNotifierNode *next_node = NULL;
91
92
if (new & IOMMU_NOTIFIER_MAP) {
93
int bus_num = pci_bus_num(sdev->bus);
94
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
95
96
if (old == IOMMU_NOTIFIER_NONE) {
97
trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
98
- node = g_malloc0(sizeof(*node));
99
- node->sdev = sdev;
100
- QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
101
- return;
102
- }
103
-
104
- /* update notifier node with new flags */
105
- QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
106
- if (node->sdev == sdev) {
107
- if (new == IOMMU_NOTIFIER_NONE) {
108
- trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
109
- QLIST_REMOVE(node, next);
110
- g_free(node);
111
- }
112
- return;
113
- }
114
+ QLIST_INSERT_HEAD(&s->devices_with_notifiers, sdev, next);
115
+ } else if (new == IOMMU_NOTIFIER_NONE) {
116
+ trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
117
+ QLIST_REMOVE(sdev, next);
57
}
118
}
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
60
+
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
62
+ if (err) {
63
+ error_propagate(errp, err);
64
+ return;
65
+ }
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
68
}
119
}
69
120
70
static Property xlnx_zynqmp_props[] = {
71
--
121
--
72
2.16.2
122
2.20.1
73
123
74
124
diff view generated by jsdifflib
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
1
In the stripe8() function we use a variable length array; however
2
as the opaque data pointor for the irq handler function. Usually
2
we know that the maximum length required is MAX_NUM_BUSSES. Use
3
this is what you want, but in some cases it would be helpful to use
3
a fixed-length array and an assert instead.
4
some other data pointer.
5
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
7
the caller to specify the data pointer they want.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-id: 20190328152635.2794-1-peter.maydell@linaro.org
13
---
11
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
12
hw/ssi/xilinx_spips.c | 6 ++++--
15
hw/core/qdev.c | 8 +++++---
13
1 file changed, 4 insertions(+), 2 deletions(-)
16
2 files changed, 33 insertions(+), 5 deletions(-)
17
14
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
17
--- a/hw/ssi/xilinx_spips.c
21
+++ b/include/hw/qdev-core.h
18
+++ b/hw/ssi/xilinx_spips.c
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
19
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
23
/* GPIO inputs also double as IRQ sinks. */
20
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
21
static inline void stripe8(uint8_t *x, int num, bool dir)
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
22
{
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
23
- uint8_t r[num];
27
- const char *name, int n);
24
- memset(r, 0, sizeof(uint8_t) * num);
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
25
+ uint8_t r[MAX_NUM_BUSSES];
29
const char *name, int n);
26
int idx[2] = {0, 0};
30
+/**
27
int bit[2] = {0, 7};
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
28
int d = dir;
32
+ * for the specified device
29
33
+ *
30
+ assert(num <= MAX_NUM_BUSSES);
34
+ * @dev: Device to create input GPIOs for
31
+ memset(r, 0, sizeof(uint8_t) * num);
35
+ * @handler: Function to call when GPIO line value is set
36
+ * @opaque: Opaque data pointer to pass to @handler
37
+ * @name: Name of the GPIO input (must be unique for this device)
38
+ * @n: Number of GPIO lines in this input set
39
+ */
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
41
+ qemu_irq_handler handler,
42
+ void *opaque,
43
+ const char *name, int n);
44
+
32
+
45
+/**
33
for (idx[0] = 0; idx[0] < num; ++idx[0]) {
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
34
for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
47
+ * for the specified device
35
r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
48
+ *
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
51
+ */
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
53
+ qemu_irq_handler handler,
54
+ const char *name, int n)
55
+{
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
57
+}
58
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
60
const char *name);
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/core/qdev.c
64
+++ b/hw/core/qdev.c
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
66
return ngl;
67
}
68
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
70
- const char *name, int n)
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
72
+ qemu_irq_handler handler,
73
+ void *opaque,
74
+ const char *name, int n)
75
{
76
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
78
79
assert(gpio_list->num_out == 0 || !name);
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
81
- dev, n);
82
+ opaque, n);
83
84
if (!name) {
85
name = "unnamed-gpio-in";
86
--
36
--
87
2.16.2
37
2.20.1
88
38
89
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Normally configure identifies the source path by looking
2
at the location where the configure script itself exists.
3
We also provide a --source-path option which lets the user
4
manually override this.
2
5
3
Enable it for the "any" CPU used by *-linux-user.
6
There isn't really an obvious use case for the --source-path
7
option, and in commit 927128222b0a91f56c13a in 2017 we
8
accidentally added some logic that looks at $source_path
9
before the command line option that overrides it has been
10
processed.
4
11
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
The fact that nobody complained suggests that there isn't
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
any use of this option and we aren't testing it either;
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
14
remove it. This allows us to move the "make $source_path
15
absolute" logic up so that there is no window in the script
16
where $source_path is set but not yet absolute.
17
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
20
Message-id: 20190318134019.23729-1-peter.maydell@linaro.org
9
---
21
---
10
target/arm/cpu.c | 1 +
22
configure | 10 ++--------
11
target/arm/cpu64.c | 1 +
23
1 file changed, 2 insertions(+), 8 deletions(-)
12
2 files changed, 2 insertions(+)
13
24
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
25
diff --git a/configure b/configure
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100755
16
--- a/target/arm/cpu.c
27
--- a/configure
17
+++ b/target/arm/cpu.c
28
+++ b/configure
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
29
@@ -XXX,XX +XXX,XX @@ ld_has() {
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
30
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
31
# default parameters
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
32
source_path=$(dirname "$0")
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
33
+# make source path absolute
23
cpu->midr = 0xffffffff;
34
+source_path=$(cd "$source_path"; pwd)
24
}
35
cpu=""
25
#endif
36
iasl="iasl"
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
37
interp_prefix="/usr/gnemul/qemu-%M"
27
index XXXXXXX..XXXXXXX 100644
38
@@ -XXX,XX +XXX,XX @@ for opt do
28
--- a/target/arm/cpu64.c
39
;;
29
+++ b/target/arm/cpu64.c
40
--cxx=*) CXX="$optarg"
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
41
;;
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
42
- --source-path=*) source_path="$optarg"
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
43
- ;;
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
44
--cpu=*) cpu="$optarg"
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
45
;;
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
46
--extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
36
cpu->dcz_blocksize = 7; /* 512 bytes */
47
@@ -XXX,XX +XXX,XX @@ if test "$debug_info" = "yes"; then
37
}
48
LDFLAGS="-g $LDFLAGS"
49
fi
50
51
-# make source path absolute
52
-source_path=$(cd "$source_path"; pwd)
53
-
54
# running configure in the source tree?
55
# we know that's the case if configure is there.
56
if test -f "./configure"; then
57
@@ -XXX,XX +XXX,XX @@ for opt do
58
;;
59
--interp-prefix=*) interp_prefix="$optarg"
60
;;
61
- --source-path=*)
62
- ;;
63
--cross-prefix=*)
64
;;
65
--cc=*)
66
@@ -XXX,XX +XXX,XX @@ $(echo Available targets: $default_target_list | \
67
--target-list-exclude=LIST exclude a set of targets from the default target-list
68
69
Advanced options (experts only):
70
- --source-path=PATH path of source code [$source_path]
71
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
72
--cc=CC use C compiler CC [$cc]
73
--iasl=IASL use ACPI compiler IASL [$iasl]
38
--
74
--
39
2.16.2
75
2.20.1
40
76
41
77
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Enforce that for M-profile various FPSCR bits which are RES0 there
2
but have defined meanings on A-profile are never settable. This
3
ensures that M-profile code can't enable the A-profile behaviour
4
(notably vector length/stride handling) by accident.
2
5
3
Enable it for the "any" CPU used by *-linux-user.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-2-peter.maydell@linaro.org
9
---
10
target/arm/vfp_helper.c | 8 ++++++++
11
1 file changed, 8 insertions(+)
4
12
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180228193125.20577-10-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/cpu.c | 1 +
11
target/arm/cpu64.c | 1 +
12
2 files changed, 2 insertions(+)
13
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
15
--- a/target/arm/vfp_helper.c
17
+++ b/target/arm/cpu.c
16
+++ b/target/arm/vfp_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
18
val &= ~FPCR_FZ16;
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
19
}
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
20
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
21
+ if (arm_feature(env, ARM_FEATURE_M)) {
23
cpu->midr = 0xffffffff;
22
+ /*
24
}
23
+ * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
25
#endif
24
+ * and also for the trapped-exception-handling bits IxE.
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
25
+ */
27
index XXXXXXX..XXXXXXX 100644
26
+ val &= 0xf7c0009f;
28
--- a/target/arm/cpu64.c
27
+ }
29
+++ b/target/arm/cpu64.c
28
+
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
29
/*
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
30
* We don't implement trapped exception handling, so the
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
31
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
37
cpu->dcz_blocksize = 7; /* 512 bytes */
38
--
32
--
39
2.16.2
33
2.20.1
40
34
41
35
diff view generated by jsdifflib
New patch
1
For M-profile the MVFR* ID registers are memory mapped, in the
2
range we implement via the NVIC. Allow them to be read.
3
(If the CPU has no FPU, these registers are defined to be RAZ.)
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190416125744.27770-3-peter.maydell@linaro.org
8
---
9
hw/intc/armv7m_nvic.c | 6 ++++++
10
1 file changed, 6 insertions(+)
11
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
return 0;
18
}
19
return cpu->env.v7m.sfar;
20
+ case 0xf40: /* MVFR0 */
21
+ return cpu->isar.mvfr0;
22
+ case 0xf44: /* MVFR1 */
23
+ return cpu->isar.mvfr1;
24
+ case 0xf48: /* MVFR2 */
25
+ return cpu->isar.mvfr2;
26
default:
27
bad_offset:
28
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
The M-profile floating point support has three associated config
2
secure Vector Table Offset Register (VTOR) by asserting config
2
registers: FPCAR, FPCCR and FPDSCR. It also makes the registers
3
signals. In particular, guest images for the MPS2 AN505 board rely
3
CPACR and NSACR have behaviour other than reads-as-zero.
4
on the MPS2's initial VTOR being correct for that board.
4
Add support for all of these as simple reads-as-written registers.
5
Implement a QEMU property so board and SoC code can set the reset
5
We will hook up actual functionality later.
6
value to the correct value.
6
7
The main complexity here is handling the FPCCR register, which
8
has a mix of banked and unbanked bits.
9
10
Note that we don't share storage with the A-profile
11
cpu->cp15.nsacr and cpu->cp15.cpacr_el1, though the behaviour
12
is quite similar, for two reasons:
13
* the M profile CPACR is banked between security states
14
* it preserves the invariant that M profile uses no state
15
inside the cp15 substruct
7
16
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
19
Message-id: 20190416125744.27770-4-peter.maydell@linaro.org
11
---
20
---
12
target/arm/cpu.h | 3 +++
21
target/arm/cpu.h | 34 ++++++++++++
13
target/arm/cpu.c | 18 ++++++++++++++----
22
hw/intc/armv7m_nvic.c | 125 ++++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 17 insertions(+), 4 deletions(-)
23
target/arm/cpu.c | 5 ++
24
target/arm/machine.c | 16 ++++++
25
4 files changed, 180 insertions(+)
15
26
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
29
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
30
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
21
*/
32
uint32_t scr[M_REG_NUM_BANKS];
22
uint32_t psci_conduit;
33
uint32_t msplim[M_REG_NUM_BANKS];
23
34
uint32_t psplim[M_REG_NUM_BANKS];
24
+ /* For v8M, initial value of the Secure VTOR */
35
+ uint32_t fpcar[M_REG_NUM_BANKS];
25
+ uint32_t init_svtor;
36
+ uint32_t fpccr[M_REG_NUM_BANKS];
26
+
37
+ uint32_t fpdscr[M_REG_NUM_BANKS];
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
38
+ uint32_t cpacr[M_REG_NUM_BANKS];
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
39
+ uint32_t nsacr;
29
*/
40
} v7m;
41
42
/* Information associated with an exception about to be taken:
43
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CSSELR, LEVEL, 1, 3)
44
*/
45
FIELD(V7M_CSSELR, INDEX, 0, 4)
46
47
+/* v7M FPCCR bits */
48
+FIELD(V7M_FPCCR, LSPACT, 0, 1)
49
+FIELD(V7M_FPCCR, USER, 1, 1)
50
+FIELD(V7M_FPCCR, S, 2, 1)
51
+FIELD(V7M_FPCCR, THREAD, 3, 1)
52
+FIELD(V7M_FPCCR, HFRDY, 4, 1)
53
+FIELD(V7M_FPCCR, MMRDY, 5, 1)
54
+FIELD(V7M_FPCCR, BFRDY, 6, 1)
55
+FIELD(V7M_FPCCR, SFRDY, 7, 1)
56
+FIELD(V7M_FPCCR, MONRDY, 8, 1)
57
+FIELD(V7M_FPCCR, SPLIMVIOL, 9, 1)
58
+FIELD(V7M_FPCCR, UFRDY, 10, 1)
59
+FIELD(V7M_FPCCR, RES0, 11, 15)
60
+FIELD(V7M_FPCCR, TS, 26, 1)
61
+FIELD(V7M_FPCCR, CLRONRETS, 27, 1)
62
+FIELD(V7M_FPCCR, CLRONRET, 28, 1)
63
+FIELD(V7M_FPCCR, LSPENS, 29, 1)
64
+FIELD(V7M_FPCCR, LSPEN, 30, 1)
65
+FIELD(V7M_FPCCR, ASPEN, 31, 1)
66
+/* These bits are banked. Others are non-banked and live in the M_REG_S bank */
67
+#define R_V7M_FPCCR_BANKED_MASK \
68
+ (R_V7M_FPCCR_LSPACT_MASK | \
69
+ R_V7M_FPCCR_USER_MASK | \
70
+ R_V7M_FPCCR_THREAD_MASK | \
71
+ R_V7M_FPCCR_MMRDY_MASK | \
72
+ R_V7M_FPCCR_SPLIMVIOL_MASK | \
73
+ R_V7M_FPCCR_UFRDY_MASK | \
74
+ R_V7M_FPCCR_ASPEN_MASK)
75
+
76
/*
77
* System register ID fields.
78
*/
79
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/intc/armv7m_nvic.c
82
+++ b/hw/intc/armv7m_nvic.c
83
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
84
}
85
case 0xd84: /* CSSELR */
86
return cpu->env.v7m.csselr[attrs.secure];
87
+ case 0xd88: /* CPACR */
88
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
89
+ return 0;
90
+ }
91
+ return cpu->env.v7m.cpacr[attrs.secure];
92
+ case 0xd8c: /* NSACR */
93
+ if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
94
+ return 0;
95
+ }
96
+ return cpu->env.v7m.nsacr;
97
/* TODO: Implement debug registers. */
98
case 0xd90: /* MPU_TYPE */
99
/* Unified MPU; if the MPU is not present this value is zero */
100
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
101
return 0;
102
}
103
return cpu->env.v7m.sfar;
104
+ case 0xf34: /* FPCCR */
105
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
106
+ return 0;
107
+ }
108
+ if (attrs.secure) {
109
+ return cpu->env.v7m.fpccr[M_REG_S];
110
+ } else {
111
+ /*
112
+ * NS can read LSPEN, CLRONRET and MONRDY. It can read
113
+ * BFRDY and HFRDY if AIRCR.BFHFNMINS != 0;
114
+ * other non-banked bits RAZ.
115
+ * TODO: MONRDY should RAZ/WI if DEMCR.SDME is set.
116
+ */
117
+ uint32_t value = cpu->env.v7m.fpccr[M_REG_S];
118
+ uint32_t mask = R_V7M_FPCCR_LSPEN_MASK |
119
+ R_V7M_FPCCR_CLRONRET_MASK |
120
+ R_V7M_FPCCR_MONRDY_MASK;
121
+
122
+ if (s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
123
+ mask |= R_V7M_FPCCR_BFRDY_MASK | R_V7M_FPCCR_HFRDY_MASK;
124
+ }
125
+
126
+ value &= mask;
127
+
128
+ value |= cpu->env.v7m.fpccr[M_REG_NS];
129
+ return value;
130
+ }
131
+ case 0xf38: /* FPCAR */
132
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
133
+ return 0;
134
+ }
135
+ return cpu->env.v7m.fpcar[attrs.secure];
136
+ case 0xf3c: /* FPDSCR */
137
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
138
+ return 0;
139
+ }
140
+ return cpu->env.v7m.fpdscr[attrs.secure];
141
case 0xf40: /* MVFR0 */
142
return cpu->isar.mvfr0;
143
case 0xf44: /* MVFR1 */
144
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
145
cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
146
}
147
break;
148
+ case 0xd88: /* CPACR */
149
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
150
+ /* We implement only the Floating Point extension's CP10/CP11 */
151
+ cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
152
+ }
153
+ break;
154
+ case 0xd8c: /* NSACR */
155
+ if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
156
+ /* We implement only the Floating Point extension's CP10/CP11 */
157
+ cpu->env.v7m.nsacr = value & (3 << 10);
158
+ }
159
+ break;
160
case 0xd90: /* MPU_TYPE */
161
return; /* RO */
162
case 0xd94: /* MPU_CTRL */
163
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
164
}
165
break;
166
}
167
+ case 0xf34: /* FPCCR */
168
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
169
+ /* Not all bits here are banked. */
170
+ uint32_t fpccr_s;
171
+
172
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
173
+ /* Don't allow setting of bits not present in v7M */
174
+ value &= (R_V7M_FPCCR_LSPACT_MASK |
175
+ R_V7M_FPCCR_USER_MASK |
176
+ R_V7M_FPCCR_THREAD_MASK |
177
+ R_V7M_FPCCR_HFRDY_MASK |
178
+ R_V7M_FPCCR_MMRDY_MASK |
179
+ R_V7M_FPCCR_BFRDY_MASK |
180
+ R_V7M_FPCCR_MONRDY_MASK |
181
+ R_V7M_FPCCR_LSPEN_MASK |
182
+ R_V7M_FPCCR_ASPEN_MASK);
183
+ }
184
+ value &= ~R_V7M_FPCCR_RES0_MASK;
185
+
186
+ if (!attrs.secure) {
187
+ /* Some non-banked bits are configurably writable by NS */
188
+ fpccr_s = cpu->env.v7m.fpccr[M_REG_S];
189
+ if (!(fpccr_s & R_V7M_FPCCR_LSPENS_MASK)) {
190
+ uint32_t lspen = FIELD_EX32(value, V7M_FPCCR, LSPEN);
191
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, LSPEN, lspen);
192
+ }
193
+ if (!(fpccr_s & R_V7M_FPCCR_CLRONRETS_MASK)) {
194
+ uint32_t cor = FIELD_EX32(value, V7M_FPCCR, CLRONRET);
195
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, CLRONRET, cor);
196
+ }
197
+ if ((s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
198
+ uint32_t hfrdy = FIELD_EX32(value, V7M_FPCCR, HFRDY);
199
+ uint32_t bfrdy = FIELD_EX32(value, V7M_FPCCR, BFRDY);
200
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
201
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
202
+ }
203
+ /* TODO MONRDY should RAZ/WI if DEMCR.SDME is set */
204
+ {
205
+ uint32_t monrdy = FIELD_EX32(value, V7M_FPCCR, MONRDY);
206
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, MONRDY, monrdy);
207
+ }
208
+
209
+ /*
210
+ * All other non-banked bits are RAZ/WI from NS; write
211
+ * just the banked bits to fpccr[M_REG_NS].
212
+ */
213
+ value &= R_V7M_FPCCR_BANKED_MASK;
214
+ cpu->env.v7m.fpccr[M_REG_NS] = value;
215
+ } else {
216
+ fpccr_s = value;
217
+ }
218
+ cpu->env.v7m.fpccr[M_REG_S] = fpccr_s;
219
+ }
220
+ break;
221
+ case 0xf38: /* FPCAR */
222
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
223
+ value &= ~7;
224
+ cpu->env.v7m.fpcar[attrs.secure] = value;
225
+ }
226
+ break;
227
+ case 0xf3c: /* FPDSCR */
228
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
229
+ value &= 0x07c00000;
230
+ cpu->env.v7m.fpdscr[attrs.secure] = value;
231
+ }
232
+ break;
233
case 0xf50: /* ICIALLU */
234
case 0xf58: /* ICIMVAU */
235
case 0xf5c: /* DCIMVAC */
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
236
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
237
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
238
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
239
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
240
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
35
uint32_t initial_msp; /* Loaded from 0x0 */
241
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
36
uint32_t initial_pc; /* Loaded from 0x4 */
242
}
37
uint8_t *rom;
243
38
+ uint32_t vecbase;
244
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
39
245
+ env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
246
+ env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
41
env->v7m.secure = true;
247
+ R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
248
+ }
43
/* Unlike A/R profile, M profile defines the reset LR value */
249
/* Unlike A/R profile, M profile defines the reset LR value */
44
env->regs[14] = 0xffffffff;
250
env->regs[14] = 0xffffffff;
45
251
46
- /* Load the initial SP and PC from the vector table at address 0 */
252
diff --git a/target/arm/machine.c b/target/arm/machine.c
47
- rom = rom_ptr(0);
253
index XXXXXXX..XXXXXXX 100644
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
254
--- a/target/arm/machine.c
49
+
255
+++ b/target/arm/machine.c
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_v8m = {
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
257
}
52
+ rom = rom_ptr(vecbase);
258
};
53
if (rom) {
259
54
/* Address zero is covered by ROM which hasn't yet been
260
+static const VMStateDescription vmstate_m_fp = {
55
* copied into physical memory.
261
+ .name = "cpu/m/fp",
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
262
+ .version_id = 1,
57
* it got copied into memory. In the latter case, rom_ptr
263
+ .minimum_version_id = 1,
58
* will return a NULL pointer and we should use ldl_phys instead.
264
+ .needed = vfp_needed,
59
*/
265
+ .fields = (VMStateField[]) {
60
- initial_msp = ldl_phys(s->as, 0);
266
+ VMSTATE_UINT32_ARRAY(env.v7m.fpcar, ARMCPU, M_REG_NUM_BANKS),
61
- initial_pc = ldl_phys(s->as, 4);
267
+ VMSTATE_UINT32_ARRAY(env.v7m.fpccr, ARMCPU, M_REG_NUM_BANKS),
62
+ initial_msp = ldl_phys(s->as, vecbase);
268
+ VMSTATE_UINT32_ARRAY(env.v7m.fpdscr, ARMCPU, M_REG_NUM_BANKS),
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
269
+ VMSTATE_UINT32_ARRAY(env.v7m.cpacr, ARMCPU, M_REG_NUM_BANKS),
64
}
270
+ VMSTATE_UINT32(env.v7m.nsacr, ARMCPU),
65
271
+ VMSTATE_END_OF_LIST()
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
272
+ }
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
273
+};
68
pmsav7_dregion,
274
+
69
qdev_prop_uint32, uint32_t);
275
static const VMStateDescription vmstate_m = {
70
276
.name = "cpu/m",
71
+/* M profile: initial value of the Secure VTOR */
277
.version_id = 4,
72
+static Property arm_cpu_initsvtor_property =
278
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
279
&vmstate_m_scr,
74
+
280
&vmstate_m_other_sp,
75
static void arm_cpu_post_init(Object *obj)
281
&vmstate_m_v8m,
76
{
282
+ &vmstate_m_fp,
77
ARMCPU *cpu = ARM_CPU(obj);
283
NULL
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
284
}
79
qdev_prop_allow_set_link_before_realize,
285
};
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
81
&error_abort);
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
83
+ &error_abort);
84
}
85
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
87
--
286
--
88
2.16.2
287
2.20.1
89
288
90
289
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The only "system register" that M-profile floating point exposes
2
via the VMRS/VMRS instructions is FPSCR, and it does not have
3
the odd special case for rd==15. Add a check to ensure we only
4
expose FPSCR.
2
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20180228193125.20577-14-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-5-peter.maydell@linaro.org
7
---
9
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 19 +++++++++++++++++--
9
1 file changed, 68 insertions(+)
11
1 file changed, 17 insertions(+), 2 deletions(-)
10
12
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
15
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
16
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
16
return 0;
17
}
18
19
+/* Advanced SIMD three registers of the same length extension.
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
24
+ */
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
26
+{
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
28
+ int rd, rn, rm, rot, size, opr_sz;
29
+ TCGv_ptr fpst;
30
+ bool q;
31
+
32
+ q = extract32(insn, 6, 1);
33
+ VFP_DREG_D(rd, insn);
34
+ VFP_DREG_N(rn, insn);
35
+ VFP_DREG_M(rm, insn);
36
+ if ((rd | rn | rm) & q) {
37
+ return 1;
38
+ }
39
+
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
42
+ size = extract32(insn, 20, 1);
43
+ rot = extract32(insn, 23, 2);
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
46
+ return 1;
47
+ }
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
51
+ size = extract32(insn, 20, 1);
52
+ rot = extract32(insn, 24, 1);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
55
+ return 1;
56
+ }
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
58
+ } else {
59
+ return 1;
60
+ }
61
+
62
+ if (s->fp_excp_el) {
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
65
+ return 0;
66
+ }
67
+ if (!s->vfp_enabled) {
68
+ return 1;
69
+ }
70
+
71
+ opr_sz = (1 + q) * 8;
72
+ fpst = get_fpstatus_ptr(1);
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
74
+ vfp_reg_offset(1, rn),
75
+ vfp_reg_offset(1, rm), fpst,
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
77
+ tcg_temp_free_ptr(fpst);
78
+ return 0;
79
+}
80
+
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
82
{
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
85
}
18
}
86
}
19
}
87
}
20
} else { /* !dp */
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
21
+ bool is_sysreg;
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
22
+
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
23
if ((insn & 0x6f) != 0x00)
91
+ goto illegal_op;
24
return 1;
92
+ }
25
rn = VFP_SREG_N(insn);
93
+ return;
26
+
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
27
+ is_sysreg = extract32(insn, 21, 1);
95
/* Coprocessor double register transfer. */
28
+
96
ARCH(5TE);
29
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
30
+ /*
31
+ * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
32
+ * Writes to R15 are UNPREDICTABLE; we choose to undef.
33
+ */
34
+ if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
35
+ return 1;
36
+ }
37
+ }
38
+
39
if (insn & ARM_CP_RW_BIT) {
40
/* vfp->arm */
41
- if (insn & (1 << 21)) {
42
+ if (is_sysreg) {
43
/* system register */
44
rn >>= 1;
45
46
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
47
}
48
} else {
49
/* arm->vfp */
50
- if (insn & (1 << 21)) {
51
+ if (is_sysreg) {
52
rn >>= 1;
53
/* system register */
54
switch (rn) {
97
--
55
--
98
2.16.2
56
2.20.1
99
57
100
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Like AArch64, M-profile floating point has no FPEXC enable
2
bit to gate floating point; so always set the VFPEN TB flag.
2
3
3
Happily, the bits are in the same places compared to a32.
4
M-profile also has CPACR and NSACR similar to A-profile;
5
they behave slightly differently:
6
* the CPACR is banked between Secure and Non-Secure
7
* if the NSACR forces a trap then this is taken to
8
the Secure state, not the Non-Secure state
4
9
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Honour the CPACR and NSACR settings. The NSACR handling
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
11
requires us to borrow the exception.target_el field
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
(usually meaningless for M profile) to distinguish the
13
NOCP UsageFault taken to Secure state from the more
14
usual fault taken to the current security state.
15
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20190416125744.27770-6-peter.maydell@linaro.org
9
---
19
---
10
target/arm/translate.c | 14 +++++++++++++-
20
target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++++---
11
1 file changed, 13 insertions(+), 1 deletion(-)
21
target/arm/translate.c | 10 ++++++--
22
2 files changed, 60 insertions(+), 5 deletions(-)
12
23
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
27
+++ b/target/arm/helper.c
28
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
29
return target_el;
30
}
31
32
+/*
33
+ * Return true if the v7M CPACR permits access to the FPU for the specified
34
+ * security state and privilege level.
35
+ */
36
+static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
37
+{
38
+ switch (extract32(env->v7m.cpacr[is_secure], 20, 2)) {
39
+ case 0:
40
+ case 2: /* UNPREDICTABLE: we treat like 0 */
41
+ return false;
42
+ case 1:
43
+ return is_priv;
44
+ case 3:
45
+ return true;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
+}
50
+
51
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
52
ARMMMUIdx mmu_idx, bool ignfault)
53
{
54
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
55
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNDEFINSTR_MASK;
56
break;
57
case EXCP_NOCP:
58
- armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
59
- env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
60
+ {
61
+ /*
62
+ * NOCP might be directed to something other than the current
63
+ * security state if this fault is because of NSACR; we indicate
64
+ * the target security state using exception.target_el.
65
+ */
66
+ int target_secstate;
67
+
68
+ if (env->exception.target_el == 3) {
69
+ target_secstate = M_REG_S;
70
+ } else {
71
+ target_secstate = env->v7m.secure;
72
+ }
73
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, target_secstate);
74
+ env->v7m.cfsr[target_secstate] |= R_V7M_CFSR_NOCP_MASK;
75
break;
76
+ }
77
case EXCP_INVSTATE:
78
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
79
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
80
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
81
return 0;
82
}
83
84
+ if (arm_feature(env, ARM_FEATURE_M)) {
85
+ /* CPACR can cause a NOCP UsageFault taken to current security state */
86
+ if (!v7m_cpacr_pass(env, env->v7m.secure, cur_el != 0)) {
87
+ return 1;
88
+ }
89
+
90
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) && !env->v7m.secure) {
91
+ if (!extract32(env->v7m.nsacr, 10, 1)) {
92
+ /* FP insns cause a NOCP UsageFault taken to Secure */
93
+ return 3;
94
+ }
95
+ }
96
+
97
+ return 0;
98
+ }
99
+
100
/* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
101
* 0, 2 : trap EL0 and EL1/PL1 accesses
102
* 1 : trap only EL0 accesses
103
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
104
flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
105
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
106
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
107
- || arm_el_is_aa64(env, 1)) {
108
+ || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
109
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
110
}
111
flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
112
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
114
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
115
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
116
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
18
default_exception_el(s));
117
* for attempts to execute invalid vfp/neon encodings with FP disabled.
19
break;
118
*/
20
}
119
if (s->fp_excp_el) {
21
- if (((insn >> 24) & 3) == 3) {
120
- gen_exception_insn(s, 4, EXCP_UDEF,
22
+ if ((insn & 0xfe000a00) == 0xfc000800
121
- syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
122
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
24
+ /* The Thumb2 and ARM encodings are identical. */
123
+ gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
124
+ s->fp_excp_el);
26
+ goto illegal_op;
125
+ } else {
27
+ }
126
+ gen_exception_insn(s, 4, EXCP_UDEF,
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
127
+ syn_fp_access_trap(1, 0xe, false),
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
128
+ s->fp_excp_el);
30
+ /* The Thumb2 and ARM encodings are identical. */
129
+ }
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
130
return 0;
32
+ goto illegal_op;
131
}
33
+ }
132
34
+ } else if (((insn >> 24) & 3) == 3) {
35
/* Translate into the equivalent ARM encoding. */
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
37
if (disas_neon_data_insn(s, insn)) {
38
--
133
--
39
2.16.2
134
2.20.1
40
135
41
136
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Correct the decode of the M-profile "coprocessor and
2
floating-point instructions" space:
3
* op0 == 0b11 is always unallocated
4
* if the CPU has an FPU then all insns with op1 == 0b101
5
are floating point and go to disas_vfp_insn()
2
6
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
For the moment we leave VLLDM and VLSTM as NOPs; in
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
a later commit we will fill in the proper implementation
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
9
for the case where an FPU is present.
10
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190416125744.27770-7-peter.maydell@linaro.org
7
---
14
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
15
target/arm/translate.c | 26 ++++++++++++++++++++++----
9
1 file changed, 67 insertions(+), 19 deletions(-)
16
1 file changed, 22 insertions(+), 4 deletions(-)
10
17
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
20
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
21
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
16
#include "disas/disas.h"
23
case 6: case 7: case 14: case 15:
17
#include "exec/exec-all.h"
24
/* Coprocessor. */
18
#include "tcg-op.h"
25
if (arm_dc_feature(s, ARM_FEATURE_M)) {
19
+#include "tcg-op-gvec.h"
26
- /* We don't currently implement M profile FP support,
20
#include "qemu/log.h"
27
- * so this entire space should give a NOCP fault, with
21
#include "qemu/bitops.h"
28
- * the exception of the v8M VLLDM and VLSTM insns, which
22
#include "arm_ldst.h"
29
- * must be NOPs in Secure state and UNDEF in Nonsecure state.
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
30
+ /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
24
#define NEON_3R_VPMAX 20
31
+ if (extract32(insn, 24, 2) == 3) {
25
#define NEON_3R_VPMIN 21
32
+ goto illegal_op; /* op0 = 0b11 : unallocated */
26
#define NEON_3R_VQDMULH_VQRDMULH 22
33
+ }
27
-#define NEON_3R_VPADD 23
28
+#define NEON_3R_VPADD_VQRDMLAH 23
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
34
+
52
+/* Expand v8.1 simd helper. */
35
+ /*
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
36
+ * Decode VLLDM and VLSTM first: these are nonstandard because:
54
+ int q, int rd, int rn, int rm)
37
+ * * if there is no FPU then these insns must NOP in
55
+{
38
+ * Secure state and UNDEF in Nonsecure state
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
39
+ * * if there is an FPU then these insns do not have
57
+ int opr_sz = (1 + q) * 8;
40
+ * the usual behaviour that disas_vfp_insn() provides of
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
41
+ * being controlled by CPACR/NSACR enable bits or the
59
+ vfp_reg_offset(1, rn),
42
+ * lazy-stacking logic.
60
+ vfp_reg_offset(1, rm), cpu_env,
43
*/
61
+ opr_sz, opr_sz, 0, fn);
44
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
62
+ return 0;
45
(insn & 0xffa00f00) == 0xec200a00) {
63
+ }
46
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
64
+ return 1;
47
/* Just NOP since FP support is not implemented */
65
+}
48
break;
66
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
68
instruction is invalid.
69
We process data in a mixture of 32-bit and 64-bit chunks.
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
if (q && ((rd | rn | rm) & 1)) {
72
return 1;
73
}
74
- /*
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
49
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
50
+ if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
91
tcg_temp_free_ptr(ptr2);
51
+ ((insn >> 8) & 0xe) == 10) {
92
tcg_temp_free_ptr(ptr3);
52
+ /* FP, and the CPU supports it */
93
return 0;
53
+ if (disas_vfp_insn(s, insn)) {
94
+
54
+ goto illegal_op;
95
+ case NEON_3R_VPADD_VQRDMLAH:
96
+ if (!u) {
97
+ break; /* VPADD */
98
+ }
99
+ /* VQRDMLAH */
100
+ switch (size) {
101
+ case 1:
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
103
+ q, rd, rn, rm);
104
+ case 2:
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
106
+ q, rd, rn, rm);
107
+ }
108
+ return 1;
109
+
110
+ case NEON_3R_VFM_VQRDMLSH:
111
+ if (!u) {
112
+ /* VFM, VFMS */
113
+ if (size == 1) {
114
+ return 1;
115
+ }
55
+ }
116
+ break;
56
+ break;
117
+ }
57
+ }
118
+ /* VQRDMLSH */
58
+
119
+ switch (size) {
59
/* All other insns: NOCP */
120
+ case 1:
60
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
61
default_exception_el(s));
122
+ q, rd, rn, rm);
123
+ case 2:
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
125
+ q, rd, rn, rm);
126
+ }
127
+ return 1;
128
}
129
if (size == 3 && op != NEON_3R_LOGIC) {
130
/* 64-bit element instructions. */
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
rm = rtmp;
133
}
134
break;
135
- case NEON_3R_VPADD:
136
- if (u) {
137
- return 1;
138
- }
139
- /* Fall through */
140
+ case NEON_3R_VPADD_VQRDMLAH:
141
case NEON_3R_VPMAX:
142
case NEON_3R_VPMIN:
143
pairwise = 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
return 1;
146
}
147
break;
148
- case NEON_3R_VFM:
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
150
+ case NEON_3R_VFM_VQRDMLSH:
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
152
return 1;
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
62
--
174
2.16.2
63
2.20.1
175
64
176
65
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
If the floating point extension is present, then the SG instruction
2
we can forward to the CPU object. Annoyingly, we can't use
2
must clear the CONTROL_S.SFPA bit. Implement this.
3
object_property_add_alias() because the CPU object we want to
3
4
forward to doesn't exist until the armv7m container is realized.
4
(On a no-FPU system the bit will always be zero, so we don't need
5
to make the clearing of the bit conditional on ARM_FEATURE_VFP.)
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-6-peter.maydell@linaro.org
9
Message-id: 20190416125744.27770-8-peter.maydell@linaro.org
9
---
10
---
10
include/hw/arm/armv7m.h | 3 +++
11
target/arm/helper.c | 1 +
11
hw/arm/armv7m.c | 9 +++++++++
12
1 file changed, 1 insertion(+)
12
2 files changed, 12 insertions(+)
13
13
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
16
--- a/target/arm/helper.c
17
+++ b/include/hw/arm/armv7m.h
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
19
19
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
20
#include "hw/sysbus.h"
20
", executing it\n", env->regs[15]);
21
#include "hw/intc/armv7m_nvic.h"
21
env->regs[14] &= ~1;
22
+#include "target/arm/idau.h"
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
23
23
switch_v7m_security_state(env, true);
24
#define TYPE_BITBAND "ARM,bitband-memory"
24
xpsr_write(env, 0, XPSR_IT);
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
25
env->regs[15] += 4;
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
* + Property "memory": MemoryRegion defining the physical address space
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
29
* devices will be automatically layered on top of this view.)
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
31
*/
32
typedef struct ARMv7MState {
33
/*< private >*/
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
char *cpu_type;
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
37
MemoryRegion *board_memory;
38
+ Object *idau;
39
} ARMv7MState;
40
41
#endif
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
45
+++ b/hw/arm/armv7m.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "sysemu/qtest.h"
48
#include "qemu/error-report.h"
49
#include "exec/address-spaces.h"
50
+#include "target/arm/idau.h"
51
52
/* Bitbanded IO. Each word corresponds to a single bit. */
53
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
55
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
57
&error_abort);
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
60
+ if (err != NULL) {
61
+ error_propagate(errp, err);
62
+ return;
63
+ }
64
+ }
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
66
if (err != NULL) {
67
error_propagate(errp, err);
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
71
MemoryRegion *),
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
73
DEFINE_PROP_END_OF_LIST(),
74
};
75
76
--
26
--
77
2.16.2
27
2.20.1
78
28
79
29
diff view generated by jsdifflib
1
Instead of loading guest images to the system address space, use the
1
The M-profile CONTROL register has two bits -- SFPA and FPCA --
2
CPU's address space. This is important if we're trying to load the
2
which relate to floating-point support, and should be RES0 otherwise.
3
file to memory or via an alias memory region that is provided by an
3
Handle them correctly in the MSR/MRS register access code.
4
SoC object and thus not mapped into the system address space.
4
Neither is banked between security states, so they are stored
5
in v7m.control[M_REG_S] regardless of current security state.
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
9
Message-id: 20190416125744.27770-9-peter.maydell@linaro.org
10
---
10
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
11
target/arm/helper.c | 57 ++++++++++++++++++++++++++++++++++++++-------
12
1 file changed, 14 insertions(+), 3 deletions(-)
12
1 file changed, 49 insertions(+), 8 deletions(-)
13
13
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
16
--- a/target/arm/helper.c
17
+++ b/hw/arm/armv7m.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
18
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
19
uint64_t entry;
19
return xpsr_read(env) & mask;
20
uint64_t lowaddr;
20
break;
21
int big_endian;
21
case 20: /* CONTROL */
22
+ AddressSpace *as;
22
- return env->v7m.control[env->v7m.secure];
23
+ int asidx;
23
+ {
24
+ CPUState *cs = CPU(cpu);
24
+ uint32_t value = env->v7m.control[env->v7m.secure];
25
25
+ if (!env->v7m.secure) {
26
#ifdef TARGET_WORDS_BIGENDIAN
26
+ /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
27
big_endian = 1;
27
+ value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
28
+ }
29
exit(1);
29
+ return value;
30
+ }
31
case 0x94: /* CONTROL_NS */
32
/* We have to handle this here because unprivileged Secure code
33
* can read the NS CONTROL register.
34
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
35
if (!env->v7m.secure) {
36
return 0;
37
}
38
- return env->v7m.control[M_REG_NS];
39
+ return env->v7m.control[M_REG_NS] |
40
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK);
30
}
41
}
31
42
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
43
if (el == 0) {
33
+ asidx = ARMASIdx_S;
44
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
34
+ } else {
45
*/
35
+ asidx = ARMASIdx_NS;
46
uint32_t mask = extract32(maskreg, 8, 4);
36
+ }
47
uint32_t reg = extract32(maskreg, 0, 8);
37
+ as = cpu_get_address_space(cs, asidx);
48
+ int cur_el = arm_current_el(env);
38
+
49
39
if (kernel_filename) {
50
- if (arm_current_el(env) == 0 && reg > 7) {
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
51
- /* only xPSR sub-fields may be written by unprivileged */
41
- NULL, big_endian, EM_ARM, 1, 0);
52
+ if (cur_el == 0 && reg > 7 && reg != 20) {
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
53
+ /*
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
54
+ * only xPSR sub-fields and CONTROL.SFPA may be written by
44
if (image_size < 0) {
55
+ * unprivileged code
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
56
+ */
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
57
return;
47
+ mem_size, as);
58
}
48
lowaddr = 0;
59
60
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
61
env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
62
env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
63
}
64
+ /*
65
+ * SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
66
+ * RES0 if the FPU is not present, and is stored in the S bank
67
+ */
68
+ if (arm_feature(env, ARM_FEATURE_VFP) &&
69
+ extract32(env->v7m.nsacr, 10, 1)) {
70
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
71
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
72
+ }
73
return;
74
case 0x98: /* SP_NS */
75
{
76
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
77
env->v7m.faultmask[env->v7m.secure] = val & 1;
78
break;
79
case 20: /* CONTROL */
80
- /* Writing to the SPSEL bit only has an effect if we are in
81
+ /*
82
+ * Writing to the SPSEL bit only has an effect if we are in
83
* thread mode; other bits can be updated by any privileged code.
84
* write_v7m_control_spsel() deals with updating the SPSEL bit in
85
* env->v7m.control, so we only need update the others.
86
* For v7M, we must just ignore explicit writes to SPSEL in handler
87
* mode; for v8M the write is permitted but will have no effect.
88
+ * All these bits are writes-ignored from non-privileged code,
89
+ * except for SFPA.
90
*/
91
- if (arm_feature(env, ARM_FEATURE_V8) ||
92
- !arm_v7m_is_handler_mode(env)) {
93
+ if (cur_el > 0 && (arm_feature(env, ARM_FEATURE_V8) ||
94
+ !arm_v7m_is_handler_mode(env))) {
95
write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
49
}
96
}
50
if (image_size < 0) {
97
- if (arm_feature(env, ARM_FEATURE_M_MAIN)) {
98
+ if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
99
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
100
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
101
}
102
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
103
+ /*
104
+ * SFPA is RAZ/WI from NS or if no FPU.
105
+ * FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
106
+ * Both are stored in the S bank.
107
+ */
108
+ if (env->v7m.secure) {
109
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
110
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_SFPA_MASK;
111
+ }
112
+ if (cur_el > 0 &&
113
+ (env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_SECURITY) ||
114
+ extract32(env->v7m.nsacr, 10, 1))) {
115
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
116
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
117
+ }
118
+ }
119
break;
120
default:
121
bad_reg:
51
--
122
--
52
2.16.2
123
2.20.1
53
124
54
125
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
Currently the code in v7m_push_stack() which detects a violation
2
* NSCCFG just routes its two bits out to external GPIO lines
2
of the v8M stack limit simply returns early if it does so. This
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
3
is OK for the current integer-only code, but won't work for the
4
bus fabric can never report errors
4
floating point handling we're about to add. We need to continue
5
executing the rest of the function so that we check for other
6
exceptions like not having permission to use the FPU and so
7
that we correctly set the FPCCR state if we are doing lazy
8
stacking. Refactor to avoid the early return.
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-10-peter.maydell@linaro.org
8
---
13
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
14
target/arm/helper.c | 23 ++++++++++++++++++-----
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
15
1 file changed, 18 insertions(+), 5 deletions(-)
11
2 files changed, 30 insertions(+), 6 deletions(-)
12
16
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
19
--- a/target/arm/helper.c
16
+++ b/include/hw/misc/iotkit-secctl.h
20
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
22
* should ignore further stack faults trying to process
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
23
* that derived exception.)
20
* should RAZ/WI or bus error
24
*/
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
25
- bool stacked_ok;
22
* Controlling the 2 APB PPCs in the IoTKit:
26
+ bool stacked_ok = true, limitviol = false;
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
27
CPUARMState *env = &cpu->env;
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
28
uint32_t xpsr = xpsr_read(env);
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
29
uint32_t frameptr = env->regs[13];
26
30
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
27
/*< public >*/
31
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
28
qemu_irq sec_resp_cfg;
32
env->v7m.secure);
29
+ qemu_irq nsc_cfg_irq;
33
env->regs[13] = limit;
30
34
- return true;
31
MemoryRegion s_regs;
35
+ /*
32
MemoryRegion ns_regs;
36
+ * We won't try to perform any further memory accesses but
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
37
+ * we must continue through the following code to check for
34
uint32_t secppcintstat;
38
+ * permission faults during FPU state preservation, and we
35
uint32_t secppcinten;
39
+ * must update FPCCR if lazy stacking is enabled.
36
uint32_t secrespcfg;
40
+ */
37
+ uint32_t nsccfg;
41
+ limitviol = true;
38
+ uint32_t brginten;
42
+ stacked_ok = false;
39
43
}
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
45
+++ b/hw/misc/iotkit-secctl.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
47
case A_SECRESPCFG:
48
r = s->secrespcfg;
49
break;
50
+ case A_NSCCFG:
51
+ r = s->nsccfg;
52
+ break;
53
case A_SECPPCINTSTAT:
54
r = s->secppcintstat;
55
break;
56
case A_SECPPCINTEN:
57
r = s->secppcinten;
58
break;
59
+ case A_BRGINTSTAT:
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
61
+ * writes, so we never report bridge interrupts.
62
+ */
63
+ r = 0;
64
+ break;
65
+ case A_BRGINTEN:
66
+ r = s->brginten;
67
+ break;
68
case A_AHBNSPPCEXP0:
69
case A_AHBNSPPCEXP1:
70
case A_AHBNSPPCEXP2:
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
72
case A_APBSPPPCEXP3:
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
74
break;
75
- case A_NSCCFG:
76
case A_SECMPCINTSTATUS:
77
case A_SECMSCINTSTAT:
78
case A_SECMSCINTEN:
79
- case A_BRGINTSTAT:
80
- case A_BRGINTEN:
81
case A_NSMSCEXP:
82
qemu_log_mask(LOG_UNIMP,
83
"IoTKit SecCtl S block read: "
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
85
}
44
}
86
45
87
switch (offset) {
46
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
88
+ case A_NSCCFG:
47
* (which may be taken in preference to the one we started with
89
+ s->nsccfg = value & 3;
48
* if it has higher priority).
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
49
*/
91
+ break;
50
- stacked_ok =
92
case A_SECRESPCFG:
51
+ stacked_ok = stacked_ok &&
93
value &= 1;
52
v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
94
s->secrespcfg = value;
53
v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
54
v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
96
s->secppcinten = value & 0x00f000f3;
55
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
56
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
98
break;
57
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
99
+ case A_BRGINTCLR:
58
100
+ break;
59
- /* Update SP regardless of whether any of the stack accesses failed. */
101
+ case A_BRGINTEN:
60
- env->regs[13] = frameptr;
102
+ s->brginten = value & 0xffff0000;
61
+ /*
103
+ break;
62
+ * If we broke a stack limit then SP was already updated earlier;
104
case A_AHBNSPPCEXP0:
63
+ * otherwise we update SP regardless of whether any of the stack
105
case A_AHBNSPPCEXP1:
64
+ * accesses failed or we took some other kind of fault.
106
case A_AHBNSPPCEXP2:
65
+ */
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
66
+ if (!limitviol) {
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
67
+ env->regs[13] = frameptr;
109
iotkit_secctl_ppc_sp_write(ppc, value);
68
+ }
110
break;
69
111
- case A_NSCCFG:
70
return !stacked_ok;
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
71
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
129
}
130
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
133
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
135
s, "iotkit-secctl-s-regs", 0x1000);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
145
--
72
--
146
2.16.2
73
2.20.1
147
74
148
75
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Handle floating point registers in exception entry.
2
This corresponds to the FP-specific parts of the pseudocode
3
functions ActivateException() and PushStack().
2
4
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
We defer the code corresponding to UpdateFPCCR() to a later patch.
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
6
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-11-peter.maydell@linaro.org
7
---
10
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 98 +++++++++++++++++++++++++++++++++++++++++++--
9
1 file changed, 61 insertions(+)
12
1 file changed, 95 insertions(+), 3 deletions(-)
10
13
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
16
--- a/target/arm/helper.c
14
+++ b/target/arm/translate.c
17
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
16
return 0;
19
switch_v7m_security_state(env, targets_secure);
17
}
20
write_v7m_control_spsel(env, 0);
18
21
arm_clear_exclusive(env);
19
+/* Advanced SIMD two registers and a scalar extension.
22
+ /* Clear SFPA and FPCA (has no effect if no FPU) */
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
23
+ env->v7m.control[M_REG_S] &=
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
24
+ ~(R_V7M_CONTROL_FPCA_MASK | R_V7M_CONTROL_SFPA_MASK);
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
25
/* Clear IT bits */
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
26
env->condexec_bits = 0;
24
+ *
27
env->regs[14] = lr;
25
+ */
28
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
29
uint32_t xpsr = xpsr_read(env);
30
uint32_t frameptr = env->regs[13];
31
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
32
+ uint32_t framesize;
33
+ bool nsacr_cp10 = extract32(env->v7m.nsacr, 10, 1);
26
+
34
+
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
35
+ if ((env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) &&
28
+{
36
+ (env->v7m.secure || nsacr_cp10)) {
29
+ int rd, rn, rm, rot, size, opr_sz;
37
+ if (env->v7m.secure &&
30
+ TCGv_ptr fpst;
38
+ env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK) {
31
+ bool q;
39
+ framesize = 0xa8;
32
+
40
+ } else {
33
+ q = extract32(insn, 6, 1);
41
+ framesize = 0x68;
34
+ VFP_DREG_D(rd, insn);
42
+ }
35
+ VFP_DREG_N(rn, insn);
43
+ } else {
36
+ VFP_DREG_M(rm, insn);
44
+ framesize = 0x20;
37
+ if ((rd | rn) & q) {
45
+ }
38
+ return 1;
46
47
/* Align stack pointer if the guest wants that */
48
if ((frameptr & 4) &&
49
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
50
xpsr |= XPSR_SPREALIGN;
51
}
52
53
- frameptr -= 0x20;
54
+ xpsr &= ~XPSR_SFPA;
55
+ if (env->v7m.secure &&
56
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
57
+ xpsr |= XPSR_SFPA;
39
+ }
58
+ }
40
+
59
+
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
60
+ frameptr -= framesize;
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
61
43
+ rot = extract32(insn, 20, 2);
62
if (arm_feature(env, ARM_FEATURE_V8)) {
44
+ size = extract32(insn, 23, 1);
63
uint32_t limit = v7m_sp_limit(env);
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
64
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
65
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
47
+ return 1;
66
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
67
68
+ if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
69
+ /* FPU is active, try to save its registers */
70
+ bool fpccr_s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
71
+ bool lspact = env->v7m.fpccr[fpccr_s] & R_V7M_FPCCR_LSPACT_MASK;
72
+
73
+ if (lspact && arm_feature(env, ARM_FEATURE_M_SECURITY)) {
74
+ qemu_log_mask(CPU_LOG_INT,
75
+ "...SecureFault because LSPACT and FPCA both set\n");
76
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
77
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
78
+ } else if (!env->v7m.secure && !nsacr_cp10) {
79
+ qemu_log_mask(CPU_LOG_INT,
80
+ "...Secure UsageFault with CFSR.NOCP because "
81
+ "NSACR.CP10 prevents stacking FP regs\n");
82
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
83
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
84
+ } else {
85
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
86
+ /* Lazy stacking disabled, save registers now */
87
+ int i;
88
+ bool cpacr_pass = v7m_cpacr_pass(env, env->v7m.secure,
89
+ arm_current_el(env) != 0);
90
+
91
+ if (stacked_ok && !cpacr_pass) {
92
+ /*
93
+ * Take UsageFault if CPACR forbids access. The pseudocode
94
+ * here does a full CheckCPEnabled() but we know the NSACR
95
+ * check can never fail as we have already handled that.
96
+ */
97
+ qemu_log_mask(CPU_LOG_INT,
98
+ "...UsageFault with CFSR.NOCP because "
99
+ "CPACR.CP10 prevents stacking FP regs\n");
100
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
101
+ env->v7m.secure);
102
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
103
+ stacked_ok = false;
104
+ }
105
+
106
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
107
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
108
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
109
+ uint32_t slo = extract64(dn, 0, 32);
110
+ uint32_t shi = extract64(dn, 32, 32);
111
+
112
+ if (i >= 16) {
113
+ faddr += 8; /* skip the slot for the FPSCR */
114
+ }
115
+ stacked_ok = stacked_ok &&
116
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
117
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
118
+ }
119
+ stacked_ok = stacked_ok &&
120
+ v7m_stack_write(cpu, frameptr + 0x60,
121
+ vfp_get_fpscr(env), mmu_idx, false);
122
+ if (cpacr_pass) {
123
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
124
+ *aa32_vfp_dreg(env, i / 2) = 0;
125
+ }
126
+ vfp_set_fpscr(env, 0);
127
+ }
128
+ } else {
129
+ /* Lazy stacking enabled, save necessary info to stack later */
130
+ /* TODO : equivalent of UpdateFPCCR() pseudocode */
131
+ }
48
+ }
132
+ }
49
+ } else {
50
+ return 1;
51
+ }
133
+ }
52
+
134
+
53
+ if (s->fp_excp_el) {
135
/*
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
136
* If we broke a stack limit then SP was already updated earlier;
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
137
* otherwise we update SP regardless of whether any of the stack
56
+ return 0;
138
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
57
+ }
139
58
+ if (!s->vfp_enabled) {
140
if (arm_feature(env, ARM_FEATURE_V8)) {
59
+ return 1;
141
lr = R_V7M_EXCRET_RES1_MASK |
60
+ }
142
- R_V7M_EXCRET_DCRS_MASK |
61
+
143
- R_V7M_EXCRET_FTYPE_MASK;
62
+ opr_sz = (1 + q) * 8;
144
+ R_V7M_EXCRET_DCRS_MASK;
63
+ fpst = get_fpstatus_ptr(1);
145
/* The S bit indicates whether we should return to Secure
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
146
* or NonSecure (ie our current state).
65
+ vfp_reg_offset(1, rn),
147
* The ES bit indicates whether we're taking this exception
66
+ vfp_reg_offset(1, rm), fpst,
148
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
67
+ opr_sz, opr_sz, rot,
149
if (env->v7m.secure) {
68
+ size ? gen_helper_gvec_fcmlas_idx
150
lr |= R_V7M_EXCRET_S_MASK;
69
+ : gen_helper_gvec_fcmlah_idx);
151
}
70
+ tcg_temp_free_ptr(fpst);
152
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
71
+ return 0;
153
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
72
+}
154
+ }
73
+
155
} else {
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
156
lr = R_V7M_EXCRET_RES1_MASK |
75
{
157
R_V7M_EXCRET_S_MASK |
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
78
goto illegal_op;
79
}
80
return;
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
84
+ goto illegal_op;
85
+ }
86
+ return;
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
88
/* Coprocessor double register transfer. */
89
ARCH(5TE);
90
--
158
--
91
2.16.2
159
2.20.1
92
160
93
161
diff view generated by jsdifflib
1
Instead of loading kernels, device trees, and the like to
1
Implement the code which updates the FPCCR register on an
2
the system address space, use the CPU's address space. This
2
exception entry where we are going to use lazy FP stacking.
3
is important if we're trying to load the file to memory or
3
We have to defer to the NVIC to determine whether the
4
via an alias memory region that is provided by an SoC
4
various exceptions are currently ready or not.
5
object and thus not mapped into the system address space.
6
5
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20190416125744.27770-12-peter.maydell@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
8
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
9
target/arm/cpu.h | 14 +++++++++
13
1 file changed, 76 insertions(+), 43 deletions(-)
10
hw/intc/armv7m_nvic.c | 34 ++++++++++++++++++++++
11
target/arm/helper.c | 67 ++++++++++++++++++++++++++++++++++++++++++-
12
3 files changed, 114 insertions(+), 1 deletion(-)
14
13
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
16
--- a/target/arm/cpu.h
18
+++ b/hw/arm/boot.c
17
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque);
20
#define ARM64_TEXT_OFFSET_OFFSET 8
19
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
21
#define ARM64_MAGIC_OFFSET 56
20
*/
22
21
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
22
+/**
24
+ const struct arm_boot_info *info)
23
+ * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
24
+ * @opaque: the NVIC
25
+ * @irq: the exception number to mark pending
26
+ * @secure: false for non-banked exceptions or for the nonsecure
27
+ * version of a banked exception, true for the secure version of a banked
28
+ * exception.
29
+ *
30
+ * Return whether an exception is "ready", i.e. whether the exception is
31
+ * enabled and is configured at a priority which would allow it to
32
+ * interrupt the current execution priority. This controls whether the
33
+ * RDY bit for it in the FPCCR is set.
34
+ */
35
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure);
36
/**
37
* armv7m_nvic_raw_execution_priority: return the raw execution priority
38
* @opaque: the NVIC
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
44
return ret;
45
}
46
47
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
25
+{
48
+{
26
+ /* Return the address space to use for bootloader reads and writes.
49
+ /*
27
+ * We prefer the secure address space if the CPU has it and we're
50
+ * Return whether an exception is "ready", i.e. it is enabled and is
28
+ * going to boot the guest into it.
51
+ * configured at a priority which would allow it to interrupt the
52
+ * current execution priority.
53
+ *
54
+ * irq and secure have the same semantics as for armv7m_nvic_set_pending():
55
+ * for non-banked exceptions secure is always false; for banked exceptions
56
+ * it indicates which of the exceptions is required.
29
+ */
57
+ */
30
+ int asidx;
58
+ NVICState *s = (NVICState *)opaque;
31
+ CPUState *cs = CPU(cpu);
59
+ bool banked = exc_is_banked(irq);
60
+ VecInfo *vec;
61
+ int running = nvic_exec_prio(s);
32
+
62
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
63
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
34
+ asidx = ARMASIdx_S;
64
+ assert(!secure || banked);
35
+ } else {
65
+
36
+ asidx = ARMASIdx_NS;
66
+ /*
67
+ * HardFault is an odd special case: we always check against -1,
68
+ * even if we're secure and HardFault has priority -3; we never
69
+ * need to check for enabled state.
70
+ */
71
+ if (irq == ARMV7M_EXCP_HARD) {
72
+ return running > -1;
37
+ }
73
+ }
38
+
74
+
39
+ return cpu_get_address_space(cs, asidx);
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
76
+
77
+ return vec->enabled &&
78
+ exc_group_prio(s, vec->prio, secure) < running;
40
+}
79
+}
41
+
80
+
42
typedef enum {
81
/* callback when external interrupt line is changed */
43
FIXUP_NONE = 0, /* do nothing */
82
static void set_irq_level(void *opaque, int n, int level)
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
47
48
static void write_bootloader(const char *name, hwaddr addr,
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
51
+ AddressSpace *as)
52
{
83
{
53
/* Fix up the specified bootloader fragment and write it into
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
85
index XXXXXXX..XXXXXXX 100644
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
86
--- a/target/arm/helper.c
56
code[i] = tswap32(insn);
87
+++ b/target/arm/helper.c
57
}
88
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
58
89
env->thumb = addr & 1;
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
61
62
g_free(code);
63
}
90
}
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
91
65
const struct arm_boot_info *info)
92
+static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
93
+ bool apply_splim)
94
+{
95
+ /*
96
+ * Like the pseudocode UpdateFPCCR: save state in FPCAR and FPCCR
97
+ * that we will need later in order to do lazy FP reg stacking.
98
+ */
99
+ bool is_secure = env->v7m.secure;
100
+ void *nvic = env->nvic;
101
+ /*
102
+ * Some bits are unbanked and live always in fpccr[M_REG_S]; some bits
103
+ * are banked and we want to update the bit in the bank for the
104
+ * current security state; and in one case we want to specifically
105
+ * update the NS banked version of a bit even if we are secure.
106
+ */
107
+ uint32_t *fpccr_s = &env->v7m.fpccr[M_REG_S];
108
+ uint32_t *fpccr_ns = &env->v7m.fpccr[M_REG_NS];
109
+ uint32_t *fpccr = &env->v7m.fpccr[is_secure];
110
+ bool hfrdy, bfrdy, mmrdy, ns_ufrdy, s_ufrdy, sfrdy, monrdy;
111
+
112
+ env->v7m.fpcar[is_secure] = frameptr & ~0x7;
113
+
114
+ if (apply_splim && arm_feature(env, ARM_FEATURE_V8)) {
115
+ bool splimviol;
116
+ uint32_t splim = v7m_sp_limit(env);
117
+ bool ign = armv7m_nvic_neg_prio_requested(nvic, is_secure) &&
118
+ (env->v7m.ccr[is_secure] & R_V7M_CCR_STKOFHFNMIGN_MASK);
119
+
120
+ splimviol = !ign && frameptr < splim;
121
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, SPLIMVIOL, splimviol);
122
+ }
123
+
124
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, LSPACT, 1);
125
+
126
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, S, is_secure);
127
+
128
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, USER, arm_current_el(env) == 0);
129
+
130
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, THREAD,
131
+ !arm_v7m_is_handler_mode(env));
132
+
133
+ hfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_HARD, false);
134
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
135
+
136
+ bfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_BUS, false);
137
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
138
+
139
+ mmrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_MEM, is_secure);
140
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, MMRDY, mmrdy);
141
+
142
+ ns_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, false);
143
+ *fpccr_ns = FIELD_DP32(*fpccr_ns, V7M_FPCCR, UFRDY, ns_ufrdy);
144
+
145
+ monrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_DEBUG, false);
146
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, MONRDY, monrdy);
147
+
148
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
149
+ s_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, true);
150
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, UFRDY, s_ufrdy);
151
+
152
+ sfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_SECURE, false);
153
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, SFRDY, sfrdy);
154
+ }
155
+}
156
+
157
static bool v7m_push_stack(ARMCPU *cpu)
66
{
158
{
67
uint32_t fixupcontext[FIXUP_MAX];
159
/* Do the "set up stack frame" part of exception entry,
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
160
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
69
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
73
}
74
75
write_bootloader("smpboot", info->smp_loader_start,
76
- smpboot, fixupcontext);
77
+ smpboot, fixupcontext, as);
78
}
79
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
81
const struct arm_boot_info *info,
82
hwaddr mvbar_addr)
83
{
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
85
int n;
86
uint32_t mvbar_blob[] = {
87
/* mvbar_addr: secure monitor vectors
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
91
}
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
93
- mvbar_addr);
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
95
+ mvbar_addr, as);
96
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
99
}
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
101
- sizeof(board_setup_blob), info->board_setup_addr);
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
202
203
if (cs == first_cpu) {
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
205
+
206
cpu_set_pc(cs, info->loader_start);
207
208
if (!have_dtb(info)) {
209
if (old_param) {
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
161
}
217
} else {
162
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
163
/* Lazy stacking enabled, save necessary info to stack later */
219
164
- /* TODO : equivalent of UpdateFPCCR() pseudocode */
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
165
+ v7m_update_fpccr(env, frameptr + 0x20, true);
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
229
}
230
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
233
- 1, data_swab);
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
236
+ 1, data_swab, as);
237
if (ret <= 0) {
238
/* The header loaded but the image didn't */
239
exit(1);
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
241
}
242
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
244
- hwaddr *entry)
245
+ hwaddr *entry, AddressSpace *as)
246
{
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
248
uint8_t *buffer;
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
250
}
251
252
*entry = mem_base + kernel_load_offset;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
255
256
g_free(buffer);
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
259
ARMCPU *cpu = n->cpu;
260
struct arm_boot_info *info =
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
263
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
166
}
292
}
167
}
293
}
168
}
294
entry = elf_entry;
295
if (kernel_size < 0) {
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
297
- &is_linux, NULL, NULL);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
299
+ &is_linux, NULL, NULL, as);
300
}
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
169
--
361
2.16.2
170
2.20.1
362
171
363
172
diff view generated by jsdifflib
1
Move the definition of the struct for the unimplemented-device
1
For v8M floating point support, transitions from Secure
2
from unimp.c to unimp.h, so that users can embed the struct
2
to Non-secure state via BLNS and BLXNS must clear the
3
in their own device structs if they prefer.
3
CONTROL.SFPA bit. (This corresponds to the pseudocode
4
BranchToNS() function.)
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
8
Message-id: 20190416125744.27770-13-peter.maydell@linaro.org
9
---
9
---
10
include/hw/misc/unimp.h | 10 ++++++++++
10
target/arm/helper.c | 4 ++++
11
hw/misc/unimp.c | 10 ----------
11
1 file changed, 4 insertions(+)
12
2 files changed, 10 insertions(+), 10 deletions(-)
13
12
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
15
--- a/target/arm/helper.c
17
+++ b/include/hw/misc/unimp.h
16
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
19
18
/* translate.c should have made BXNS UNDEF unless we're secure */
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
19
assert(env->v7m.secure);
21
20
22
+#define UNIMPLEMENTED_DEVICE(obj) \
21
+ if (!(dest & 1)) {
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
24
+
23
+ }
25
+typedef struct {
24
switch_v7m_security_state(env, dest & 1);
26
+ SysBusDevice parent_obj;
25
env->thumb = 1;
27
+ MemoryRegion iomem;
26
env->regs[15] = dest & ~1;
28
+ char *name;
27
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
29
+ uint64_t size;
28
*/
30
+} UnimplementedDeviceState;
29
write_v7m_exception(env, 1);
31
+
30
}
32
/**
31
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
33
* create_unimplemented_device: create and map a dummy device
32
switch_v7m_security_state(env, 0);
34
* @name: name of the device for debug logging
33
env->thumb = 1;
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
34
env->regs[15] = dest;
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
38
+++ b/hw/misc/unimp.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "qemu/log.h"
41
#include "qapi/error.h"
42
43
-#define UNIMPLEMENTED_DEVICE(obj) \
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
45
-
46
-typedef struct {
47
- SysBusDevice parent_obj;
48
- MemoryRegion iomem;
49
- char *name;
50
- uint64_t size;
51
-} UnimplementedDeviceState;
52
-
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
54
{
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
56
--
35
--
57
2.16.2
36
2.20.1
58
37
59
38
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
The TailChain() pseudocode specifies that a tail chaining
2
that expose to software the controls for the Peripheral
2
exception should sanitize the excReturn all-ones bits and
3
Protection Controllers in the system. Implement these.
3
(if there is no FPU) the excReturn FType bits; we weren't
4
doing this.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
8
Message-id: 20190416125744.27770-14-peter.maydell@linaro.org
8
---
9
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
10
target/arm/helper.c | 8 ++++++++
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
11
1 file changed, 8 insertions(+)
11
2 files changed, 315 insertions(+), 19 deletions(-)
12
12
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
15
--- a/target/arm/helper.c
16
+++ b/include/hw/misc/iotkit-secctl.h
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
18
* QEMU interface:
18
qemu_log_mask(CPU_LOG_INT, "...taking pending %s exception %d\n",
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
19
targets_secure ? "secure" : "nonsecure", exc);
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
20
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
21
+ if (dotailchain) {
22
+ * should RAZ/WI or bus error
22
+ /* Sanitize LR FType and PREFIX bits */
23
+ * Controlling the 2 APB PPCs in the IoTKit:
23
+ if (!arm_feature(env, ARM_FEATURE_VFP)) {
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
24
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
30
+ * might provide:
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
44
45
#ifndef IOTKIT_SECCTL_H
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
49
50
-typedef struct IoTKitSecCtl {
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
53
+#define IOTS_PPC_NUM_PORTS 16
54
+#define IOTS_NUM_APB_PPC 2
55
+#define IOTS_NUM_APB_EXP_PPC 4
56
+#define IOTS_NUM_AHB_EXP_PPC 4
57
+
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
59
+
60
+/* State and IRQ lines relating to a PPC. For the
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
62
+ */
63
+typedef struct IoTKitSecCtlPPC {
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
66
+ qemu_irq irq_enable;
67
+ qemu_irq irq_clear;
68
+
69
+ uint32_t ns;
70
+ uint32_t sp;
71
+ uint32_t nsp;
72
+
73
+ /* Number of ports actually present */
74
+ int numports;
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
76
+ int irq_bit_offset;
77
+ IoTKitSecCtl *parent;
78
+} IoTKitSecCtlPPC;
79
+
80
+struct IoTKitSecCtl {
81
/*< private >*/
82
SysBusDevice parent_obj;
83
84
/*< public >*/
85
+ qemu_irq sec_resp_cfg;
86
87
MemoryRegion s_regs;
88
MemoryRegion ns_regs;
89
-} IoTKitSecCtl;
90
+
91
+ uint32_t secppcintstat;
92
+ uint32_t secppcinten;
93
+ uint32_t secrespcfg;
94
+
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
98
+};
99
100
#endif
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/misc/iotkit-secctl.c
104
+++ b/hw/misc/iotkit-secctl.c
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
106
0x0d, 0xf0, 0x05, 0xb1,
107
};
108
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
110
+ * AHB expansion, APB expansion) are all set up so that they are
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
113
+ * into an an index into a PPC array easily.
114
+ */
115
+static inline int offset_to_ppc_idx(uint32_t offset)
116
+{
117
+ return extract32(offset, 2, 2);
118
+}
119
+
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
121
+
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
123
+{
124
+ int i;
125
+
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
127
+ fn(&s->apb[i]);
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
135
+}
136
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
138
uint64_t *pdata,
139
unsigned size, MemTxAttrs attrs)
140
{
141
uint64_t r;
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
146
case A_AHBNSPPC0:
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
148
r = 0;
149
break;
150
case A_SECRESPCFG:
151
- case A_NSCCFG:
152
- case A_SECMPCINTSTATUS:
153
+ r = s->secrespcfg;
154
+ break;
155
case A_SECPPCINTSTAT:
156
+ r = s->secppcintstat;
157
+ break;
158
case A_SECPPCINTEN:
159
- case A_SECMSCINTSTAT:
160
- case A_SECMSCINTEN:
161
- case A_BRGINTSTAT:
162
- case A_BRGINTEN:
163
+ r = s->secppcinten;
164
+ break;
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
209
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
211
+{
212
+ int i;
213
+
214
+ for (i = 0; i < ppc->numports; i++) {
215
+ bool v;
216
+
217
+ if (extract32(ppc->ns, i, 1)) {
218
+ v = extract32(ppc->nsp, i, 1);
219
+ } else {
220
+ v = extract32(ppc->sp, i, 1);
221
+ }
25
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
26
+ lr = deposit32(lr, 24, 8, 0xff);
223
+ }
224
+}
225
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
227
+{
228
+ int i;
229
+
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
231
+ for (i = 0; i < ppc->numports; i++) {
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
233
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
236
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
238
+{
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
240
+ iotkit_secctl_update_ppc_ap(ppc);
241
+}
242
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
244
+{
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
246
+ iotkit_secctl_update_ppc_ap(ppc);
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
268
uint32_t offset = addr;
269
+ IoTKitSecCtlPPC *ppc;
270
271
trace_iotkit_secctl_s_write(offset, value, size);
272
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
406
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
408
+{
409
+ ppc->ns = 0;
410
+ ppc->sp = 0;
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
27
+ }
489
+
28
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
29
if (arm_feature(env, ARM_FEATURE_V8)) {
491
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
31
(lr & R_V7M_EXCRET_S_MASK)) {
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
525
}
526
};
527
--
32
--
528
2.16.2
33
2.20.1
529
34
530
35
diff view generated by jsdifflib
1
Add a function load_ramdisk_as() which behaves like the existing
1
The magic value pushed onto the callee stack as an integrity
2
load_ramdisk() but allows the caller to specify the AddressSpace
2
check is different if floating point is present.
3
to use. This matches the pattern we have already for various
4
other loader functions.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
6
Message-id: 20190416125744.27770-15-peter.maydell@linaro.org
10
---
7
---
11
include/hw/loader.h | 12 +++++++++++-
8
target/arm/helper.c | 22 +++++++++++++++++++---
12
hw/core/loader.c | 8 +++++++-
9
1 file changed, 19 insertions(+), 3 deletions(-)
13
2 files changed, 18 insertions(+), 2 deletions(-)
14
10
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
13
--- a/target/arm/helper.c
18
+++ b/include/hw/loader.h
14
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
15
@@ -XXX,XX +XXX,XX @@ load_fail:
20
void *translate_opaque);
16
return false;
21
17
}
22
/**
18
23
- * load_ramdisk:
19
+static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
24
+ * load_ramdisk_as:
20
+{
25
* @filename: Path to the ramdisk image
21
+ /*
26
* @addr: Memory address to load the ramdisk to
22
+ * Return the integrity signature value for the callee-saves
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
23
+ * stack frame section. @lr is the exception return payload/LR value
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
24
+ * whose FType bit forms bit 0 of the signature if FP is present.
29
+ * is used if nothing is supplied here.
25
+ */
30
*
26
+ uint32_t sig = 0xfefa125a;
31
* Load a ramdisk image with U-Boot header to the specified memory
32
* address.
33
*
34
* Returns the size of the loaded image on success, -1 otherwise.
35
*/
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
37
+ AddressSpace *as);
38
+
27
+
39
+/**
28
+ if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
40
+ * load_ramdisk:
29
+ sig |= 1;
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
30
+ }
42
+ * an AddressSpace.
31
+ return sig;
43
+ */
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
45
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/core/loader.c
50
+++ b/hw/core/loader.c
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
52
53
/* Load a ramdisk. */
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
55
+{
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
57
+}
32
+}
58
+
33
+
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
34
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
60
+ AddressSpace *as)
35
bool ignore_faults)
61
{
36
{
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
37
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
63
- NULL, NULL, NULL);
38
bool stacked_ok;
64
+ NULL, NULL, as);
39
uint32_t limit;
65
}
40
bool want_psp;
66
41
+ uint32_t sig;
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
42
43
if (dotailchain) {
44
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
45
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
46
/* Write as much of the stack frame as we can. A write failure may
47
* cause us to pend a derived exception.
48
*/
49
+ sig = v7m_integrity_sig(env, lr);
50
stacked_ok =
51
- v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
52
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
53
v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
54
ignore_faults) &&
55
v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
56
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
57
if (return_to_secure &&
58
((excret & R_V7M_EXCRET_ES_MASK) == 0 ||
59
(excret & R_V7M_EXCRET_DCRS_MASK) == 0)) {
60
- uint32_t expected_sig = 0xfefa125b;
61
uint32_t actual_sig;
62
63
pop_ok = v7m_stack_read(cpu, &actual_sig, frameptr, mmu_idx);
64
65
- if (pop_ok && expected_sig != actual_sig) {
66
+ if (pop_ok && v7m_integrity_sig(env, excret) != actual_sig) {
67
/* Take a SecureFault on the current stack */
68
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
69
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
68
--
70
--
69
2.16.2
71
2.20.1
70
72
71
73
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Handle floating point registers in exception return.
2
This corresponds to pseudocode functions ValidateExceptionReturn(),
3
ExceptionReturn(), PopStack() and ConsumeExcStackFrame().
2
4
3
The integer size check was already outside of the opcode switch;
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
move the floating-point size check outside as well. Unify the
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
size vs index adjustment between fp and integer paths.
7
Message-id: 20190416125744.27770-16-peter.maydell@linaro.org
8
---
9
target/arm/helper.c | 142 +++++++++++++++++++++++++++++++++++++++++++-
10
1 file changed, 141 insertions(+), 1 deletion(-)
6
11
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
13
1 file changed, 32 insertions(+), 33 deletions(-)
14
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
14
--- a/target/arm/helper.c
18
+++ b/target/arm/translate-a64.c
15
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
16
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
20
case 0x05: /* FMLS */
17
bool rettobase = false;
21
case 0x09: /* FMUL */
18
bool exc_secure = false;
22
case 0x19: /* FMULX */
19
bool return_to_secure;
23
- if (size == 1) {
20
+ bool ftype;
24
- unallocated_encoding(s);
21
+ bool restore_s16_s31;
25
- return;
22
26
- }
23
/* If we're not in Handler mode then jumps to magic exception-exit
27
is_fp = true;
24
* addresses don't have magic behaviour. However for the v8M
28
break;
25
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
29
default:
26
excret);
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
27
}
31
if (is_fp) {
28
32
/* convert insn encoded size to TCGMemOp size */
29
+ ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
33
switch (size) {
30
+
34
- case 2: /* single precision */
31
+ if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
35
- size = MO_32;
32
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
36
- index = h << 1 | l;
33
+ "exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
37
- rm |= (m << 4);
34
+ "if FPU not present\n",
38
- break;
35
+ excret);
39
- case 3: /* double precision */
36
+ ftype = true;
40
- size = MO_64;
37
+ }
41
- if (l || !is_q) {
38
+
42
+ case 0: /* half-precision */
39
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
40
/* EXC_RETURN.ES validation check (R_SMFL). We must do this before
44
unallocated_encoding(s);
41
* we pick which FAULTMASK to clear.
45
return;
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
46
}
43
*/
47
- index = h;
44
write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
48
- rm |= (m << 4);
45
49
- break;
46
+ /*
50
- case 0: /* half precision */
47
+ * Clear scratch FP values left in caller saved registers; this
51
size = MO_16;
48
+ * must happen before any kind of tail chaining.
52
- index = h << 2 | l << 1 | m;
49
+ */
53
- is_fp16 = true;
50
+ if ((env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_CLRONRET_MASK) &&
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
51
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
55
- break;
52
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
56
- }
53
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
57
- /* fallthru */
54
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
58
- default: /* unallocated */
55
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
59
- unallocated_encoding(s);
56
+ "stackframe: error during lazy state deactivation\n");
60
- return;
57
+ v7m_exception_taken(cpu, excret, true, false);
61
- }
62
- } else {
63
- switch (size) {
64
- case 1:
65
- index = h << 2 | l << 1 | m;
66
break;
67
- case 2:
68
- index = h << 1 | l;
69
- rm |= (m << 4);
70
+ case MO_32: /* single precision */
71
+ case MO_64: /* double precision */
72
break;
73
default:
74
unallocated_encoding(s);
75
return;
76
}
77
+ } else {
78
+ switch (size) {
79
+ case MO_8:
80
+ case MO_64:
81
+ unallocated_encoding(s);
82
+ return;
58
+ return;
59
+ } else {
60
+ /* Clear s0..s15 and FPSCR */
61
+ int i;
62
+
63
+ for (i = 0; i < 16; i += 2) {
64
+ *aa32_vfp_dreg(env, i / 2) = 0;
65
+ }
66
+ vfp_set_fpscr(env, 0);
83
+ }
67
+ }
84
+ }
68
+ }
85
+
69
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
70
if (sfault) {
87
+ switch (size) {
71
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
88
+ case MO_16:
72
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
89
+ index = h << 2 | l << 1 | m;
73
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
90
+ break;
74
}
91
+ case MO_32:
75
}
92
+ index = h << 1 | l;
76
93
+ rm |= m << 4;
77
+ if (!ftype) {
94
+ break;
78
+ /* FP present and we need to handle it */
95
+ case MO_64:
79
+ if (!return_to_secure &&
96
+ if (l || !is_q) {
80
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK)) {
97
+ unallocated_encoding(s);
81
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
98
+ return;
82
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
83
+ qemu_log_mask(CPU_LOG_INT,
84
+ "...taking SecureFault on existing stackframe: "
85
+ "Secure LSPACT set but exception return is "
86
+ "not to secure state\n");
87
+ v7m_exception_taken(cpu, excret, true, false);
88
+ return;
89
+ }
90
+
91
+ restore_s16_s31 = return_to_secure &&
92
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
93
+
94
+ if (env->v7m.fpccr[return_to_secure] & R_V7M_FPCCR_LSPACT_MASK) {
95
+ /* State in FPU is still valid, just clear LSPACT */
96
+ env->v7m.fpccr[return_to_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
97
+ } else {
98
+ int i;
99
+ uint32_t fpscr;
100
+ bool cpacr_pass, nsacr_pass;
101
+
102
+ cpacr_pass = v7m_cpacr_pass(env, return_to_secure,
103
+ return_to_priv);
104
+ nsacr_pass = return_to_secure ||
105
+ extract32(env->v7m.nsacr, 10, 1);
106
+
107
+ if (!cpacr_pass) {
108
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
109
+ return_to_secure);
110
+ env->v7m.cfsr[return_to_secure] |= R_V7M_CFSR_NOCP_MASK;
111
+ qemu_log_mask(CPU_LOG_INT,
112
+ "...taking UsageFault on existing "
113
+ "stackframe: CPACR.CP10 prevents unstacking "
114
+ "FP regs\n");
115
+ v7m_exception_taken(cpu, excret, true, false);
116
+ return;
117
+ } else if (!nsacr_pass) {
118
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
119
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_INVPC_MASK;
120
+ qemu_log_mask(CPU_LOG_INT,
121
+ "...taking Secure UsageFault on existing "
122
+ "stackframe: NSACR.CP10 prevents unstacking "
123
+ "FP regs\n");
124
+ v7m_exception_taken(cpu, excret, true, false);
125
+ return;
126
+ }
127
+
128
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
129
+ uint32_t slo, shi;
130
+ uint64_t dn;
131
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
132
+
133
+ if (i >= 16) {
134
+ faddr += 8; /* Skip the slot for the FPSCR */
135
+ }
136
+
137
+ pop_ok = pop_ok &&
138
+ v7m_stack_read(cpu, &slo, faddr, mmu_idx) &&
139
+ v7m_stack_read(cpu, &shi, faddr + 4, mmu_idx);
140
+
141
+ if (!pop_ok) {
142
+ break;
143
+ }
144
+
145
+ dn = (uint64_t)shi << 32 | slo;
146
+ *aa32_vfp_dreg(env, i / 2) = dn;
147
+ }
148
+ pop_ok = pop_ok &&
149
+ v7m_stack_read(cpu, &fpscr, frameptr + 0x60, mmu_idx);
150
+ if (pop_ok) {
151
+ vfp_set_fpscr(env, fpscr);
152
+ }
153
+ if (!pop_ok) {
154
+ /*
155
+ * These regs are 0 if security extension present;
156
+ * otherwise merely UNKNOWN. We zero always.
157
+ */
158
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
159
+ *aa32_vfp_dreg(env, i / 2) = 0;
160
+ }
161
+ vfp_set_fpscr(env, 0);
162
+ }
163
+ }
99
+ }
164
+ }
100
+ index = h;
165
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
101
+ rm |= m << 4;
166
+ V7M_CONTROL, FPCA, !ftype);
102
+ break;
167
+
103
+ default:
168
/* Commit to consuming the stack frame */
104
+ g_assert_not_reached();
169
frameptr += 0x20;
170
+ if (!ftype) {
171
+ frameptr += 0x48;
172
+ if (restore_s16_s31) {
173
+ frameptr += 0x40;
174
+ }
175
+ }
176
/* Undo stack alignment (the SPREALIGN bit indicates that the original
177
* pre-exception SP was not 8-aligned and we added a padding word to
178
* align it, so we undo this by ORing in the bit that increases it
179
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
180
*frame_sp_p = frameptr;
105
}
181
}
106
182
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
107
if (!fp_access_check(s)) {
183
- xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
184
+ xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
185
+
186
+ if (env->v7m.secure) {
187
+ bool sfpa = xpsr & XPSR_SFPA;
188
+
189
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
190
+ V7M_CONTROL, SFPA, sfpa);
191
+ }
192
193
/* The restored xPSR exception field will be zero if we're
194
* resuming in Thread mode. If that doesn't match what the
108
--
195
--
109
2.16.2
196
2.20.1
110
197
111
198
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Move the NS TBFLAG down from bit 19 to bit 6, which has not
2
been used since commit c1e3781090b9d36c60 in 2015, when we
3
started passing the entire MMU index in the TB flags rather
4
than just a 'privilege level' bit.
2
5
3
Not enabled anywhere yet.
6
This rearrangement is not strictly necessary, but means that
7
we can put M-profile-only bits next to each other rather
8
than scattered across the flag word.
4
9
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-17-peter.maydell@linaro.org
9
---
13
---
10
target/arm/cpu.h | 1 +
14
target/arm/cpu.h | 11 ++++++-----
11
linux-user/elfload.c | 1 +
15
1 file changed, 6 insertions(+), 5 deletions(-)
12
2 files changed, 2 insertions(+)
13
16
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
25
+/*
23
};
26
+ * Indicates whether cp register reads and writes by guest code should access
24
27
+ * the secure or nonsecure bank of banked registers; note that this is not
25
static inline int arm_feature(CPUARMState *env, int feature)
28
+ * the same thing as the current security state of the processor!
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
29
+ */
27
index XXXXXXX..XXXXXXX 100644
30
+FIELD(TBFLAG_A32, NS, 6, 1)
28
--- a/linux-user/elfload.c
31
FIELD(TBFLAG_A32, VFPEN, 7, 1)
29
+++ b/linux-user/elfload.c
32
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
33
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
35
* checks on the other bits at runtime
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
36
*/
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
37
FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
35
#undef GET_FEATURE
38
-/* Indicates whether cp register reads and writes by guest code should access
36
39
- * the secure or nonsecure bank of banked registers; note that this is not
37
return hwcaps;
40
- * the same thing as the current security state of the processor!
41
- */
42
-FIELD(TBFLAG_A32, NS, 19, 1)
43
/* For M profile only, Handler (ie not Thread) mode */
44
FIELD(TBFLAG_A32, HANDLER, 21, 1)
45
/* For M profile only, whether we should generate stack-limit checks */
38
--
46
--
39
2.16.2
47
2.20.1
40
48
41
49
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
We are close to running out of TB flags for AArch32; we could
2
a small piece of hardware typically implemented in the SoC
2
start using the cs_base word, but before we do that we can
3
which provides board or SoC specific security attribution
3
economise on our usage by sharing the same bits for the VFP
4
information for each address that the CPU performs MPU/SAU
4
VECSTRIDE field and the XScale XSCALE_CPAR field. This
5
checks on. For QEMU, we model this with a QOM interface which
5
works because no XScale CPU ever had VFP.
6
is implemented by the board or SoC object and connected to
7
the CPU using a link property.
8
9
This commit defines the new interface class, adds the link
10
property to the CPU object, and makes the SAU checking
11
code call the IDAU interface if one is present.
12
6
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
9
Message-id: 20190416125744.27770-18-peter.maydell@linaro.org
16
---
10
---
17
target/arm/cpu.h | 3 +++
11
target/arm/cpu.h | 10 ++++++----
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
12
target/arm/cpu.c | 7 +++++++
19
target/arm/cpu.c | 15 +++++++++++++
13
target/arm/helper.c | 6 +++++-
20
target/arm/helper.c | 28 +++++++++++++++++++++---
14
target/arm/translate.c | 9 +++++++--
21
4 files changed, 104 insertions(+), 3 deletions(-)
15
4 files changed, 25 insertions(+), 7 deletions(-)
22
create mode 100644 target/arm/idau.h
23
16
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
29
/* MemoryRegion to use for secure physical accesses */
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
30
MemoryRegion *secure_memory;
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
31
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
33
+ Object *idau;
34
+
35
/* 'compatible' string for this CPU for Linux device trees */
36
const char *dtb_compatible;
37
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/target/arm/idau.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
25
+/*
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
26
+ * We store the bottom two bits of the CPAR as TB flags and handle
46
+ *
27
+ * checks on the other bits at runtime. This shares the same bits as
47
+ * Copyright (c) 2018 Linaro Ltd
28
+ * VECSTRIDE, which is OK as no XScale CPU has VFP.
48
+ *
49
+ * This program is free software; you can redistribute it and/or
50
+ * modify it under the terms of the GNU General Public License
51
+ * as published by the Free Software Foundation; either version 2
52
+ * of the License, or (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program; if not, see
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
62
+ *
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
64
+ * typically implemented in the SoC which provides board or SoC
65
+ * specific security attribution information for each address that
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
67
+ * QOM interface which is implemented by the board or SoC object and
68
+ * connected to the CPU using a link property.
69
+ */
29
+ */
70
+
30
+FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
71
+#ifndef TARGET_ARM_IDAU_H
31
/*
72
+#define TARGET_ARM_IDAU_H
32
* Indicates whether cp register reads and writes by guest code should access
73
+
33
* the secure or nonsecure bank of banked registers; note that this is not
74
+#include "qom/object.h"
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
75
+
35
FIELD(TBFLAG_A32, VFPEN, 7, 1)
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
36
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
77
+#define IDAU_INTERFACE(obj) \
37
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
38
-/* We store the bottom two bits of the CPAR as TB flags and handle
79
+#define IDAU_INTERFACE_CLASS(class) \
39
- * checks on the other bits at runtime
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
40
- */
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
41
-FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
42
/* For M profile only, Handler (ie not Thread) mode */
83
+
43
FIELD(TBFLAG_A32, HANDLER, 21, 1)
84
+typedef struct IDAUInterface {
44
/* For M profile only, whether we should generate stack-limit checks */
85
+ Object parent;
86
+} IDAUInterface;
87
+
88
+#define IREGION_NOTVALID -1
89
+
90
+typedef struct IDAUInterfaceClass {
91
+ InterfaceClass parent;
92
+
93
+ /* Check the specified address and return the IDAU security information
94
+ * for it by filling in iregion, exempt, ns and nsc:
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
96
+ * exempt: true if address is exempt from security attribution
97
+ * ns: true if the address is NonSecure
98
+ * nsc: true if the address is NonSecure-callable
99
+ */
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
101
+ bool *exempt, bool *ns, bool *nsc);
102
+} IDAUInterfaceClass;
103
+
104
+#endif
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
47
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
48
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
110
*/
50
set_feature(env, ARM_FEATURE_THUMB_DSP);
111
112
#include "qemu/osdep.h"
113
+#include "target/arm/idau.h"
114
#include "qemu/error-report.h"
115
#include "qapi/error.h"
116
#include "cpu.h"
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
118
}
119
}
51
}
120
52
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
53
+ /*
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
54
+ * We rely on no XScale CPU having VFP so we can use the same bits in the
123
+ qdev_prop_allow_set_link_before_realize,
55
+ * TB flags field for VECSTRIDE and XSCALE_CPAR.
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
56
+ */
125
+ &error_abort);
57
+ assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
126
+ }
58
+ arm_feature(env, ARM_FEATURE_XSCALE)));
127
+
59
+
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
60
if (arm_feature(env, ARM_FEATURE_V7) &&
129
&error_abort);
61
!arm_feature(env, ARM_FEATURE_M) &&
130
}
62
!arm_feature(env, ARM_FEATURE_PMSA)) {
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
132
.class_init = arm_cpu_class_init,
133
};
134
135
+static const TypeInfo idau_interface_type_info = {
136
+ .name = TYPE_IDAU_INTERFACE,
137
+ .parent = TYPE_INTERFACE,
138
+ .class_size = sizeof(IDAUInterfaceClass),
139
+};
140
+
141
static void arm_cpu_register_types(void)
142
{
143
const ARMCPUInfo *info = arm_cpus;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
65
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
66
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
155
#include "qemu/osdep.h"
68
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
156
+#include "target/arm/idau.h"
69
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
157
#include "trace.h"
70
}
158
#include "cpu.h"
71
- flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
159
#include "internals.h"
72
+ /* Note that XSCALE_CPAR shares bits with VECSTRIDE */
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
73
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
161
*/
74
+ flags = FIELD_DP32(flags, TBFLAG_A32,
162
ARMCPU *cpu = arm_env_get_cpu(env);
75
+ XSCALE_CPAR, env->cp15.c15_cpar);
163
int r;
76
+ }
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
77
}
165
+ int idau_region = IREGION_NOTVALID;
78
166
79
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
167
- /* TODO: implement IDAU */
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
168
+ if (cpu->idau) {
81
index XXXXXXX..XXXXXXX 100644
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
82
--- a/target/arm/translate.c
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
83
+++ b/target/arm/translate.c
171
+
84
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
85
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
173
+ &idau_nsc);
86
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
87
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
88
- dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
89
- dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
90
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
91
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
92
+ dc->vec_stride = 0;
93
+ } else {
94
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
95
+ dc->c15_cpar = 0;
174
+ }
96
+ }
175
97
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
98
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
99
regime_is_secure(env, dc->mmu_idx);
178
return;
179
}
180
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
184
return;
185
}
186
187
+ if (idau_region != IREGION_NOTVALID) {
188
+ sattrs->irvalid = true;
189
+ sattrs->iregion = idau_region;
190
+ }
191
+
192
switch (env->sau.ctrl & 3) {
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
194
break;
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
196
}
197
}
198
199
- /* TODO when we support the IDAU then it may override the result here */
200
+ /* The IDAU will override the SAU lookup results if it specifies
201
+ * higher security than the SAU does.
202
+ */
203
+ if (!idau_ns) {
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
205
+ sattrs->ns = false;
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
212
--
100
--
213
2.16.2
101
2.20.1
214
102
215
103
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
The M-profile FPCCR.S bit indicates the security status of
2
object which we can forward to the CPU object.
2
the floating point context. In the pseudocode ExecuteFPCheck()
3
function it is unconditionally set to match the current
4
security state whenever a floating point instruction is
5
executed.
6
7
Implement this by adding a new TB flag which tracks whether
8
FPCCR.S is different from the current security state, so
9
that we only need to emit the code to update it in the
10
less-common case when it is not already set correctly.
11
12
Note that we will add the handling for the other work done
13
by ExecuteFPCheck() in later commits.
3
14
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
17
Message-id: 20190416125744.27770-19-peter.maydell@linaro.org
7
---
18
---
8
include/hw/arm/armv7m.h | 2 ++
19
target/arm/cpu.h | 2 ++
9
hw/arm/armv7m.c | 9 +++++++++
20
target/arm/translate.h | 1 +
10
2 files changed, 11 insertions(+)
21
target/arm/helper.c | 5 +++++
22
target/arm/translate.c | 20 ++++++++++++++++++++
23
4 files changed, 28 insertions(+)
11
24
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
27
--- a/target/arm/cpu.h
15
+++ b/include/hw/arm/armv7m.h
28
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
29
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
30
FIELD(TBFLAG_A32, VFPEN, 7, 1)
18
* devices will be automatically layered on top of this view.)
31
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
19
* + Property "idau": IDAU interface (forwarded to CPU object)
32
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
33
+/* For M profile only, set if FPCCR.S does not match current security state */
21
*/
34
+FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
22
typedef struct ARMv7MState {
35
/* For M profile only, Handler (ie not Thread) mode */
23
/*< private >*/
36
FIELD(TBFLAG_A32, HANDLER, 21, 1)
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
37
/* For M profile only, whether we should generate stack-limit checks */
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
26
MemoryRegion *board_memory;
27
Object *idau;
28
+ uint32_t init_svtor;
29
} ARMv7MState;
30
31
#endif
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
40
--- a/target/arm/translate.h
35
+++ b/hw/arm/armv7m.c
41
+++ b/target/arm/translate.h
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
42
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
37
return;
43
bool v7m_handler_mode;
44
bool v8m_secure; /* true if v8M and we're in Secure mode */
45
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
46
+ bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
47
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
48
* so that top level loop can generate correct syndrome information.
49
*/
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.c
53
+++ b/target/arm/helper.c
54
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
55
flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
56
}
57
58
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
59
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
61
+ }
62
+
63
*pflags = flags;
64
*cs_base = 0;
65
}
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
38
}
71
}
39
}
72
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
73
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
74
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
42
+ "init-svtor", &err);
75
+ /* Handle M-profile lazy FP state mechanics */
43
+ if (err != NULL) {
76
+
44
+ error_propagate(errp, err);
77
+ /* Update ownership of FP context: set FPCCR.S to match current state */
45
+ return;
78
+ if (s->v8m_fpccr_s_wrong) {
79
+ TCGv_i32 tmp;
80
+
81
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
82
+ if (s->v8m_secure) {
83
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
84
+ } else {
85
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
86
+ }
87
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
88
+ /* Don't need to do this for any further FP insns in this TB */
89
+ s->v8m_fpccr_s_wrong = false;
46
+ }
90
+ }
47
+ }
91
+ }
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
92
+
49
if (err != NULL) {
93
if (extract32(insn, 28, 4) == 0xf) {
50
error_propagate(errp, err);
94
/*
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
95
* Encodings with T=1 (Thumb) or unconditional (ARM):
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
96
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
53
MemoryRegion *),
97
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
98
regime_is_secure(env, dc->mmu_idx);
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
99
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
56
DEFINE_PROP_END_OF_LIST(),
100
+ dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
57
};
101
dc->cp_regs = cpu->cp_regs;
102
dc->features = env->features;
58
103
59
--
104
--
60
2.16.2
105
2.20.1
61
106
62
107
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The M-profile FPCCR.ASPEN bit indicates that automatic floating-point
2
context preservation is enabled. Before executing any floating-point
3
instruction, if FPCCR.ASPEN is set and the CONTROL FPCA/SFPA bits
4
indicate that there is no active floating point context then we
5
must create a new context (by initializing FPSCR and setting
6
FPCA/SFPA to indicate that the context is now active). In the
7
pseudocode this is handled by ExecuteFPCheck().
2
8
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Implement this with a new TB flag which tracks whether we
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
need to create a new FP context.
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
11
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20190416125744.27770-20-peter.maydell@linaro.org
7
---
15
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
16
target/arm/cpu.h | 2 ++
9
1 file changed, 42 insertions(+), 4 deletions(-)
17
target/arm/translate.h | 1 +
18
target/arm/helper.c | 13 +++++++++++++
19
target/arm/translate.c | 29 +++++++++++++++++++++++++++++
20
4 files changed, 45 insertions(+)
10
21
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
27
FIELD(TBFLAG_A32, VFPEN, 7, 1)
28
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
29
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
30
+/* For M profile only, set if we must create a new FP context */
31
+FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
32
/* For M profile only, set if FPCCR.S does not match current security state */
33
FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
34
/* For M profile only, Handler (ie not Thread) mode */
35
diff --git a/target/arm/translate.h b/target/arm/translate.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate.h
38
+++ b/target/arm/translate.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
40
bool v8m_secure; /* true if v8M and we're in Secure mode */
41
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
42
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
43
+ bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
44
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
45
* so that top level loop can generate correct syndrome information.
46
*/
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
52
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
53
}
54
55
+ if (arm_feature(env, ARM_FEATURE_M) &&
56
+ (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
57
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
58
+ (env->v7m.secure &&
59
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
60
+ /*
61
+ * ASPEN is set, but FPCA/SFPA indicate that there is no active
62
+ * FP context; we must create a new FP context before executing
63
+ * any FP insn.
64
+ */
65
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
66
+ }
67
+
68
*pflags = flags;
69
*cs_base = 0;
70
}
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
71
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
73
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
74
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
75
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
76
/* Don't need to do this for any further FP insns in this TB */
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
77
s->v8m_fpccr_s_wrong = false;
18
78
}
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
21
+ TCGv_i32, TCGv_i32);
22
+
79
+
23
/* initialize TCG globals. */
80
+ if (s->v7m_new_fp_ctxt_needed) {
24
void arm_translate_init(void)
81
+ /*
25
{
82
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
83
+ * and the FPSCR.
27
}
84
+ */
28
neon_store_reg64(cpu_V0, rd + pass);
85
+ TCGv_i32 control, fpscr;
29
}
86
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
30
-
31
-
32
break;
33
- default: /* 14 and 15 are RESERVED */
34
- return 1;
35
+ case 14: /* VQRDMLAH scalar */
36
+ case 15: /* VQRDMLSH scalar */
37
+ {
38
+ NeonGenThreeOpEnvFn *fn;
39
+
87
+
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
88
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
41
+ return 1;
89
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
42
+ }
90
+ tcg_temp_free_i32(fpscr);
43
+ if (u && ((rd | rn) & 1)) {
91
+ /*
44
+ return 1;
92
+ * We don't need to arrange to end the TB, because the only
45
+ }
93
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
46
+ if (op == 14) {
94
+ * and VECSTRIDE, and those don't exist for M-profile.
47
+ if (size == 1) {
95
+ */
48
+ fn = gen_helper_neon_qrdmlah_s16;
49
+ } else {
50
+ fn = gen_helper_neon_qrdmlah_s32;
51
+ }
52
+ } else {
53
+ if (size == 1) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
55
+ } else {
56
+ fn = gen_helper_neon_qrdmlsh_s32;
57
+ }
58
+ }
59
+
96
+
60
+ tmp2 = neon_get_scalar(size, rm);
97
+ if (s->v8m_secure) {
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
98
+ bits |= R_V7M_CONTROL_SFPA_MASK;
62
+ tmp = neon_load_reg(rn, pass);
99
+ }
63
+ tmp3 = neon_load_reg(rd, pass);
100
+ control = load_cpu_field(v7m.control[M_REG_S]);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
101
+ tcg_gen_ori_i32(control, control, bits);
65
+ tcg_temp_free_i32(tmp3);
102
+ store_cpu_field(control, v7m.control[M_REG_S]);
66
+ neon_store_reg(rd, pass, tmp);
103
+ /* Don't need to do this for any further FP insns in this TB */
67
+ }
104
+ s->v7m_new_fp_ctxt_needed = false;
68
+ tcg_temp_free_i32(tmp2);
105
+ }
69
+ }
106
}
70
+ break;
107
71
+ default:
108
if (extract32(insn, 28, 4) == 0xf) {
72
+ g_assert_not_reached();
109
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
73
}
110
regime_is_secure(env, dc->mmu_idx);
74
}
111
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
75
} else { /* size == 3 */
112
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
113
+ dc->v7m_new_fp_ctxt_needed =
114
+ FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
115
dc->cp_regs = cpu->cp_regs;
116
dc->features = env->features;
117
76
--
118
--
77
2.16.2
119
2.20.1
78
120
79
121
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add a new helper function which returns the MMU index to use
2
for v7M, where the caller specifies all of the security
3
state, privilege level and whether the execution priority
4
is negative, and reimplement the existing
5
arm_v7m_mmu_idx_for_secstate_and_priv() in terms of it.
2
6
3
Not enabled anywhere yet.
7
We are going to need this for the lazy-FP-stacking code.
4
8
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190416125744.27770-21-peter.maydell@linaro.org
10
---
12
---
11
target/arm/cpu.h | 1 +
13
target/arm/cpu.h | 7 +++++++
12
linux-user/elfload.c | 1 +
14
target/arm/helper.c | 14 +++++++++++---
13
2 files changed, 2 insertions(+)
15
2 files changed, 18 insertions(+), 3 deletions(-)
14
16
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
21
@@ -XXX,XX +XXX,XX @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
22
}
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
23
}
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
24
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
25
+/*
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
26
+ * Return the MMU index for a v7M CPU with all relevant information
25
};
27
+ * manually specified.
26
28
+ */
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
29
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
30
+ bool secstate, bool priv, bool negpri);
31
+
32
/* Return the MMU index for a v7M CPU in the specified security and
33
* privilege state.
34
*/
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
37
--- a/target/arm/helper.c
30
+++ b/linux-user/elfload.c
38
+++ b/target/arm/helper.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
39
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
40
return 0;
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
41
}
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
42
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
43
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
36
#undef GET_FEATURE
44
- bool secstate, bool priv)
37
45
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
38
return hwcaps;
46
+ bool secstate, bool priv, bool negpri)
47
{
48
ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
49
50
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
51
mmu_idx |= ARM_MMU_IDX_M_PRIV;
52
}
53
54
- if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
55
+ if (negpri) {
56
mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
57
}
58
59
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
60
return mmu_idx;
61
}
62
63
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
64
+ bool secstate, bool priv)
65
+{
66
+ bool negpri = armv7m_nvic_neg_prio_requested(env->nvic, secstate);
67
+
68
+ return arm_v7m_mmu_idx_all(env, secstate, priv, negpri);
69
+}
70
+
71
/* Return the MMU index for a v7M CPU in the specified security state */
72
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
73
{
39
--
74
--
40
2.16.2
75
2.20.1
41
76
42
77
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
In the v7M architecture, if an exception is generated in the process
2
which is used to gate transactions to non-TZ-aware peripherals so
2
of doing the lazy stacking of FP registers, the handling of
3
that secure software can configure them to not be accessible to
3
possible escalation to HardFault is treated differently to the normal
4
non-secure software.
4
approach: it works based on the saved information about exception
5
readiness that was stored in the FPCCR when the stack frame was
6
created. Provide a new function armv7m_nvic_set_pending_lazyfp()
7
which pends exceptions during lazy stacking, and implements
8
this logic.
9
10
This corresponds to the pseudocode TakePreserveFPException().
5
11
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-15-peter.maydell@linaro.org
14
Message-id: 20190416125744.27770-22-peter.maydell@linaro.org
9
---
15
---
10
hw/misc/Makefile.objs | 2 +
16
target/arm/cpu.h | 12 ++++++
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
17
hw/intc/armv7m_nvic.c | 96 +++++++++++++++++++++++++++++++++++++++++++
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
18
2 files changed, 108 insertions(+)
13
default-configs/arm-softmmu.mak | 2 +
14
hw/misc/trace-events | 11 ++
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
19
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
22
--- a/target/arm/cpu.h
22
+++ b/hw/misc/Makefile.objs
23
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
24
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
25
* a different exception).
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
26
*/
26
27
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
28
+/**
29
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
30
+ * @opaque: the NVIC
31
+ * @irq: the exception number to mark pending
32
+ * @secure: false for non-banked exceptions or for the nonsecure
33
+ * version of a banked exception, true for the secure version of a banked
34
+ * exception.
35
+ *
36
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
37
+ * generated in the course of lazy stacking of FP registers.
38
+ */
39
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
40
/**
41
* armv7m_nvic_get_pending_irq_info: return highest priority pending
42
* exception, and whether it targets Secure state
43
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/armv7m_nvic.c
46
+++ b/hw/intc/armv7m_nvic.c
47
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
48
do_armv7m_nvic_set_pending(opaque, irq, secure, true);
49
}
50
51
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
52
+{
53
+ /*
54
+ * Pend an exception during lazy FP stacking. This differs
55
+ * from the usual exception pending because the logic for
56
+ * whether we should escalate depends on the saved context
57
+ * in the FPCCR register, not on the current state of the CPU/NVIC.
58
+ */
59
+ NVICState *s = (NVICState *)opaque;
60
+ bool banked = exc_is_banked(irq);
61
+ VecInfo *vec;
62
+ bool targets_secure;
63
+ bool escalate = false;
64
+ /*
65
+ * We will only look at bits in fpccr if this is a banked exception
66
+ * (in which case 'secure' tells us whether it is the S or NS version).
67
+ * All the bits for the non-banked exceptions are in fpccr_s.
68
+ */
69
+ uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S];
70
+ uint32_t fpccr = s->cpu->env.v7m.fpccr[secure];
28
+
71
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
72
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
73
+ assert(!secure || banked);
31
obj-$(CONFIG_AUX) += auxbus.o
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/tz-ppc.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM TrustZone peripheral protection controller emulation
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
74
+
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
51
+ * (DDI 0571G):
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
53
+ *
54
+ * The PPC sits in front of peripherals and allows secure software to
55
+ * configure it to either pass through or reject transactions.
56
+ * Rejected transactions may be configured to either be aborted, or to
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
58
+ *
59
+ * The PPC has no register interface -- it is configured purely by a
60
+ * collection of input signals from other hardware in the system. Typically
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
62
+ * the SoC that uses the PPC.
63
+ *
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
65
+ * since the only difference between them is that the AHB version has a
66
+ * "default" port which has no security checks applied. In QEMU the default
67
+ * port can be emulated simply by wiring its downstream devices directly
68
+ * into the parent address space, since the PPC does not need to intercept
69
+ * transactions there.
70
+ *
71
+ * In the hardware, selection of which downstream port to use is done by
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
74
+ * the desired addresses to implement the address decode.
75
+ *
76
+ * QEMU interface:
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
78
+ * of each of the 16 ports of the PPC
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
80
+ * for each of the 16 ports of the PPC
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
82
+ * accessible to NonSecure transactions
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
84
+ * accessible to non-privileged transactions
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
91
+ * the associated port do not have the TZ security check performed. (This
92
+ * corresponds to the hardware allowing this to be set as a Verilog
93
+ * parameter.)
94
+ */
95
+
76
+
96
+#ifndef TZ_PPC_H
77
+ targets_secure = banked ? secure : exc_targets_secure(s, irq);
97
+#define TZ_PPC_H
98
+
78
+
99
+#include "hw/sysbus.h"
79
+ switch (irq) {
100
+
80
+ case ARMV7M_EXCP_DEBUG:
101
+#define TYPE_TZ_PPC "tz-ppc"
81
+ if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) {
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
82
+ /* Ignore DebugMonitor exception */
103
+
83
+ return;
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
166
+ bool level = s->irq_status && s->irq_enable;
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
171
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
173
+{
174
+ TZPPC *s = TZ_PPC(opaque);
175
+
176
+ assert(n < TZ_NUM_PORTS);
177
+ trace_tz_ppc_cfg_nonsec(n, level);
178
+ s->cfg_nonsec[n] = level;
179
+}
180
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
182
+{
183
+ TZPPC *s = TZ_PPC(opaque);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
189
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
191
+{
192
+ TZPPC *s = TZ_PPC(opaque);
193
+
194
+ trace_tz_ppc_cfg_sec_resp(level);
195
+ s->cfg_sec_resp = level;
196
+}
197
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
199
+{
200
+ TZPPC *s = TZ_PPC(opaque);
201
+
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
218
+}
219
+
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
221
+{
222
+ /* Check whether to allow an access to port n; return true if
223
+ * the check passes, and false if the transaction must be blocked.
224
+ * If the latter, the caller must check cfg_sec_resp to determine
225
+ * whether to abort or RAZ/WI the transaction.
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
84
+ }
240
+ return false;
241
+ }
242
+ return true;
243
+}
244
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
246
+ unsigned size, MemTxAttrs attrs)
247
+{
248
+ TZPPCPort *p = opaque;
249
+ TZPPC *s = p->ppc;
250
+ int n = p - s->port;
251
+ AddressSpace *as = &p->downstream_as;
252
+ uint64_t data;
253
+ MemTxResult res;
254
+
255
+ if (!tz_ppc_check(s, n, attrs)) {
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
257
+ if (s->cfg_sec_resp) {
258
+ return MEMTX_ERROR;
259
+ } else {
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ }
263
+ }
264
+
265
+ switch (size) {
266
+ case 1:
267
+ data = address_space_ldub(as, addr, attrs, &res);
268
+ break;
85
+ break;
269
+ case 2:
86
+ case ARMV7M_EXCP_MEM:
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
87
+ escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK);
271
+ break;
88
+ break;
272
+ case 4:
89
+ case ARMV7M_EXCP_USAGE:
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
90
+ escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK);
274
+ break;
91
+ break;
275
+ case 8:
92
+ case ARMV7M_EXCP_BUS:
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
93
+ escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK);
94
+ break;
95
+ case ARMV7M_EXCP_SECURE:
96
+ escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK);
277
+ break;
97
+ break;
278
+ default:
98
+ default:
279
+ g_assert_not_reached();
99
+ g_assert_not_reached();
280
+ }
100
+ }
281
+ *pdata = data;
282
+ return res;
283
+}
284
+
101
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
102
+ if (escalate) {
286
+ unsigned size, MemTxAttrs attrs)
103
+ /*
287
+{
104
+ * Escalate to HardFault: faults that initially targeted Secure
288
+ TZPPCPort *p = opaque;
105
+ * continue to do so, even if HF normally targets NonSecure.
289
+ TZPPC *s = p->ppc;
106
+ */
290
+ AddressSpace *as = &p->downstream_as;
107
+ irq = ARMV7M_EXCP_HARD;
291
+ int n = p - s->port;
108
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
292
+ MemTxResult res;
109
+ (targets_secure ||
293
+
110
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) {
294
+ if (!tz_ppc_check(s, n, attrs)) {
111
+ vec = &s->sec_vectors[irq];
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
112
+ } else {
299
+ return MEMTX_OK;
113
+ vec = &s->vectors[irq];
300
+ }
114
+ }
301
+ }
115
+ }
302
+
116
+
303
+ switch (size) {
117
+ if (!vec->enabled ||
304
+ case 1:
118
+ nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) {
305
+ address_space_stb(as, addr, val, attrs, &res);
119
+ if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) {
306
+ break;
120
+ /*
307
+ case 2:
121
+ * We want to escalate to HardFault but the context the
308
+ address_space_stw_le(as, addr, val, attrs, &res);
122
+ * FP state belongs to prevents the exception pre-empting.
309
+ break;
123
+ */
310
+ case 4:
124
+ cpu_abort(&s->cpu->parent_obj,
311
+ address_space_stl_le(as, addr, val, attrs, &res);
125
+ "Lockup: can't escalate to HardFault during "
312
+ break;
126
+ "lazy FP register stacking\n");
313
+ case 8:
127
+ }
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
128
+ }
319
+ return res;
320
+}
321
+
129
+
322
+static const MemoryRegionOps tz_ppc_ops = {
130
+ if (escalate) {
323
+ .read_with_attrs = tz_ppc_read,
131
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
324
+ .write_with_attrs = tz_ppc_write,
132
+ }
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
133
+ if (!vec->pending) {
326
+};
134
+ vec->pending = 1;
327
+
135
+ /*
328
+static void tz_ppc_reset(DeviceState *dev)
136
+ * We do not call nvic_irq_update(), because we know our caller
329
+{
137
+ * is going to handle causing us to take the exception by
330
+ TZPPC *s = TZ_PPC(dev);
138
+ * raising EXCP_LAZYFP, so raising the IRQ line would be
331
+
139
+ * pointless extra work. We just need to recompute the
332
+ trace_tz_ppc_reset();
140
+ * priorities so that armv7m_nvic_can_take_pending_exception()
333
+ s->cfg_sec_resp = false;
141
+ * returns the right answer.
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
142
+ */
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
143
+ nvic_recompute_state(s);
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
144
+ }
381
+}
145
+}
382
+
146
+
383
+static const VMStateDescription tz_ppc_vmstate = {
147
/* Make pending IRQ active. */
384
+ .name = "tz-ppc",
148
void armv7m_nvic_acknowledge_irq(void *opaque)
385
+ .version_id = 1,
149
{
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
393
+ VMSTATE_BOOL(irq_status, TZPPC),
394
+ VMSTATE_END_OF_LIST()
395
+ }
396
+};
397
+
398
+#define DEFINE_PORT(N) \
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
150
--
480
2.16.2
151
2.20.1
481
152
482
153
diff view generated by jsdifflib
New patch
1
1
Pushing registers to the stack for v7M needs to handle three cases:
2
* the "normal" case where we pend exceptions
3
* an "ignore faults" case where we set FSR bits but
4
do not pend exceptions (this is used when we are
5
handling some kinds of derived exception on exception entry)
6
* a "lazy FP stacking" case, where different FSR bits
7
are set and the exception is pended differently
8
9
Implement this by changing the existing flag argument that
10
tells us whether to ignore faults or not into an enum that
11
specifies which of the 3 modes we should handle.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190416125744.27770-23-peter.maydell@linaro.org
16
---
17
target/arm/helper.c | 118 +++++++++++++++++++++++++++++---------------
18
1 file changed, 79 insertions(+), 39 deletions(-)
19
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
25
}
26
}
27
28
+/*
29
+ * What kind of stack write are we doing? This affects how exceptions
30
+ * generated during the stacking are treated.
31
+ */
32
+typedef enum StackingMode {
33
+ STACK_NORMAL,
34
+ STACK_IGNFAULTS,
35
+ STACK_LAZYFP,
36
+} StackingMode;
37
+
38
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
39
- ARMMMUIdx mmu_idx, bool ignfault)
40
+ ARMMMUIdx mmu_idx, StackingMode mode)
41
{
42
CPUState *cs = CPU(cpu);
43
CPUARMState *env = &cpu->env;
44
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
45
&attrs, &prot, &page_size, &fi, NULL)) {
46
/* MPU/SAU lookup failed */
47
if (fi.type == ARMFault_QEMU_SFault) {
48
- qemu_log_mask(CPU_LOG_INT,
49
- "...SecureFault with SFSR.AUVIOL during stacking\n");
50
- env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
51
+ if (mode == STACK_LAZYFP) {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...SecureFault with SFSR.LSPERR "
54
+ "during lazy stacking\n");
55
+ env->v7m.sfsr |= R_V7M_SFSR_LSPERR_MASK;
56
+ } else {
57
+ qemu_log_mask(CPU_LOG_INT,
58
+ "...SecureFault with SFSR.AUVIOL "
59
+ "during stacking\n");
60
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK;
61
+ }
62
+ env->v7m.sfsr |= R_V7M_SFSR_SFARVALID_MASK;
63
env->v7m.sfar = addr;
64
exc = ARMV7M_EXCP_SECURE;
65
exc_secure = false;
66
} else {
67
- qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
68
- env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
69
+ if (mode == STACK_LAZYFP) {
70
+ qemu_log_mask(CPU_LOG_INT,
71
+ "...MemManageFault with CFSR.MLSPERR\n");
72
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MLSPERR_MASK;
73
+ } else {
74
+ qemu_log_mask(CPU_LOG_INT,
75
+ "...MemManageFault with CFSR.MSTKERR\n");
76
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
77
+ }
78
exc = ARMV7M_EXCP_MEM;
79
exc_secure = secure;
80
}
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
82
attrs, &txres);
83
if (txres != MEMTX_OK) {
84
/* BusFault trying to write the data */
85
- qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
86
- env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
87
+ if (mode == STACK_LAZYFP) {
88
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.LSPERR\n");
89
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_LSPERR_MASK;
90
+ } else {
91
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
92
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
93
+ }
94
exc = ARMV7M_EXCP_BUS;
95
exc_secure = false;
96
goto pend_fault;
97
@@ -XXX,XX +XXX,XX @@ pend_fault:
98
* later if we have two derived exceptions.
99
* The only case when we must not pend the exception but instead
100
* throw it away is if we are doing the push of the callee registers
101
- * and we've already generated a derived exception. Even in this
102
- * case we will still update the fault status registers.
103
+ * and we've already generated a derived exception (this is indicated
104
+ * by the caller passing STACK_IGNFAULTS). Even in this case we will
105
+ * still update the fault status registers.
106
*/
107
- if (!ignfault) {
108
+ switch (mode) {
109
+ case STACK_NORMAL:
110
armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
111
+ break;
112
+ case STACK_LAZYFP:
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, exc, exc_secure);
114
+ break;
115
+ case STACK_IGNFAULTS:
116
+ break;
117
}
118
return false;
119
}
120
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
121
uint32_t limit;
122
bool want_psp;
123
uint32_t sig;
124
+ StackingMode smode = ignore_faults ? STACK_IGNFAULTS : STACK_NORMAL;
125
126
if (dotailchain) {
127
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
128
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
129
*/
130
sig = v7m_integrity_sig(env, lr);
131
stacked_ok =
132
- v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
133
- v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
134
- ignore_faults) &&
135
- v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
136
- ignore_faults) &&
137
- v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx,
138
- ignore_faults) &&
139
- v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx,
140
- ignore_faults) &&
141
- v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx,
142
- ignore_faults) &&
143
- v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx,
144
- ignore_faults) &&
145
- v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx,
146
- ignore_faults) &&
147
- v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
148
- ignore_faults);
149
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, smode) &&
150
+ v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx, smode) &&
151
+ v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx, smode) &&
152
+ v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx, smode) &&
153
+ v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx, smode) &&
154
+ v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx, smode) &&
155
+ v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx, smode) &&
156
+ v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx, smode) &&
157
+ v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx, smode);
158
159
/* Update SP regardless of whether any of the stack accesses failed. */
160
*frame_sp_p = frameptr;
161
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
162
* if it has higher priority).
163
*/
164
stacked_ok = stacked_ok &&
165
- v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
166
- v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
167
- v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
168
- v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
169
- v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
170
- v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
171
- v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
172
- v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
173
+ v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, STACK_NORMAL) &&
174
+ v7m_stack_write(cpu, frameptr + 4, env->regs[1],
175
+ mmu_idx, STACK_NORMAL) &&
176
+ v7m_stack_write(cpu, frameptr + 8, env->regs[2],
177
+ mmu_idx, STACK_NORMAL) &&
178
+ v7m_stack_write(cpu, frameptr + 12, env->regs[3],
179
+ mmu_idx, STACK_NORMAL) &&
180
+ v7m_stack_write(cpu, frameptr + 16, env->regs[12],
181
+ mmu_idx, STACK_NORMAL) &&
182
+ v7m_stack_write(cpu, frameptr + 20, env->regs[14],
183
+ mmu_idx, STACK_NORMAL) &&
184
+ v7m_stack_write(cpu, frameptr + 24, env->regs[15],
185
+ mmu_idx, STACK_NORMAL) &&
186
+ v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, STACK_NORMAL);
187
188
if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
189
/* FPU is active, try to save its registers */
190
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
191
faddr += 8; /* skip the slot for the FPSCR */
192
}
193
stacked_ok = stacked_ok &&
194
- v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
195
- v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
196
+ v7m_stack_write(cpu, faddr, slo,
197
+ mmu_idx, STACK_NORMAL) &&
198
+ v7m_stack_write(cpu, faddr + 4, shi,
199
+ mmu_idx, STACK_NORMAL);
200
}
201
stacked_ok = stacked_ok &&
202
v7m_stack_write(cpu, frameptr + 0x60,
203
- vfp_get_fpscr(env), mmu_idx, false);
204
+ vfp_get_fpscr(env), mmu_idx, STACK_NORMAL);
205
if (cpacr_pass) {
206
for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
207
*aa32_vfp_dreg(env, i / 2) = 0;
208
--
209
2.20.1
210
211
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The M-profile architecture floating point system supports
2
2
lazy FP state preservation, where FP registers are not
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
pushed to the stack when an exception occurs but are instead
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
4
only saved if and when the first FP instruction in the exception
5
handler is executed. Implement this in QEMU, corresponding
6
to the check of LSPACT in the pseudocode ExecuteFPCheck().
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
of the pseudocode in the Arm ARM]
10
Message-id: 20190416125744.27770-24-peter.maydell@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/helper.h | 11 ++++
12
target/arm/cpu.h | 3 ++
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
13
target/arm/helper.h | 2 +
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
14
target/arm/translate.h | 1 +
13
3 files changed, 246 insertions(+), 8 deletions(-)
15
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++
14
16
target/arm/translate.c | 22 ++++++++
17
5 files changed, 140 insertions(+)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@
24
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
25
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
26
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
27
+#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
29
30
#define ARMV7M_EXCP_RESET 1
31
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
32
FIELD(TBFLAG_A32, VFPEN, 7, 1)
33
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
34
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
35
+/* For M profile only, set if FPCCR.LSPACT is set */
36
+FIELD(TBFLAG_A32, LSPACT, 18, 1)
37
/* For M profile only, set if we must create a new FP context */
38
FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
39
/* For M profile only, set if FPCCR.S does not match current security state */
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
40
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
42
--- a/target/arm/helper.h
18
+++ b/target/arm/helper.h
43
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
44
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
45
21
void, ptr, ptr, ptr, ptr, i32)
46
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
22
47
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
48
+DEF_HELPER_1(v7m_preserve_fp_state, void, env)
24
+ void, ptr, ptr, ptr, ptr, i32)
49
+
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
50
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
26
+ void, ptr, ptr, ptr, ptr, i32)
51
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
52
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
28
+ void, ptr, ptr, ptr, ptr, i32)
53
diff --git a/target/arm/translate.h b/target/arm/translate.h
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
54
index XXXXXXX..XXXXXXX 100644
30
+ void, ptr, ptr, ptr, ptr, i32)
55
--- a/target/arm/translate.h
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
56
+++ b/target/arm/translate.h
32
+ void, ptr, ptr, ptr, ptr, i32)
57
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
33
+
58
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
34
#ifdef TARGET_AARCH64
59
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
35
#include "helper-a64.h"
60
bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
36
#endif
61
+ bool v7m_lspact; /* FPCCR.LSPACT set */
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
62
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
38
index XXXXXXX..XXXXXXX 100644
63
* so that top level loop can generate correct syndrome information.
39
--- a/target/arm/translate-a64.c
64
*/
40
+++ b/target/arm/translate-a64.c
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
66
index XXXXXXX..XXXXXXX 100644
42
}
67
--- a/target/arm/helper.c
43
feature = ARM_FEATURE_V8_RDM;
68
+++ b/target/arm/helper.c
44
break;
69
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
45
+ case 0x8: /* FCMLA, #0 */
70
g_assert_not_reached();
46
+ case 0x9: /* FCMLA, #90 */
71
}
47
+ case 0xa: /* FCMLA, #180 */
72
48
+ case 0xb: /* FCMLA, #270 */
73
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
49
case 0xc: /* FCADD, #90 */
74
+{
50
case 0xe: /* FCADD, #270 */
75
+ /* translate.c should never generate calls here in user-only mode */
51
if (size == 0
76
+ g_assert_not_reached();
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
77
+}
53
}
78
+
54
return;
79
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
55
80
{
56
+ case 0x8: /* FCMLA, #0 */
81
/* The TT instructions can be used by unprivileged code, but in
57
+ case 0x9: /* FCMLA, #90 */
82
@@ -XXX,XX +XXX,XX @@ pend_fault:
58
+ case 0xa: /* FCMLA, #180 */
83
return false;
59
+ case 0xb: /* FCMLA, #270 */
84
}
60
+ rot = extract32(opcode, 0, 2);
85
61
+ switch (size) {
86
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
62
+ case 1:
87
+{
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
88
+ /*
64
+ gen_helper_gvec_fcmlah);
89
+ * Preserve FP state (because LSPACT was set and we are about
65
+ break;
90
+ * to execute an FP instruction). This corresponds to the
66
+ case 2:
91
+ * PreserveFPState() pseudocode.
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
92
+ * We may throw an exception if the stacking fails.
68
+ gen_helper_gvec_fcmlas);
93
+ */
69
+ break;
94
+ ARMCPU *cpu = arm_env_get_cpu(env);
70
+ case 3:
95
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
96
+ bool negpri = !(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_HFRDY_MASK);
72
+ gen_helper_gvec_fcmlad);
97
+ bool is_priv = !(env->v7m.fpccr[is_secure] & R_V7M_FPCCR_USER_MASK);
73
+ break;
98
+ bool splimviol = env->v7m.fpccr[is_secure] & R_V7M_FPCCR_SPLIMVIOL_MASK;
74
+ default:
99
+ uint32_t fpcar = env->v7m.fpcar[is_secure];
75
+ g_assert_not_reached();
100
+ bool stacked_ok = true;
76
+ }
101
+ bool ts = is_secure && (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
77
+ return;
102
+ bool take_exception;
78
+
103
+
79
case 0xc: /* FCADD, #90 */
104
+ /* Take the iothread lock as we are going to touch the NVIC */
80
case 0xe: /* FCADD, #270 */
105
+ qemu_mutex_lock_iothread();
81
rot = extract32(opcode, 1, 1);
106
+
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
107
+ /* Check the background context had access to the FPU */
83
int rn = extract32(insn, 5, 5);
108
+ if (!v7m_cpacr_pass(env, is_secure, is_priv)) {
84
int rd = extract32(insn, 0, 5);
109
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, is_secure);
85
bool is_long = false;
110
+ env->v7m.cfsr[is_secure] |= R_V7M_CFSR_NOCP_MASK;
86
- bool is_fp = false;
111
+ stacked_ok = false;
87
+ int is_fp = 0;
112
+ } else if (!is_secure && !extract32(env->v7m.nsacr, 10, 1)) {
88
bool is_fp16 = false;
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
89
int index;
114
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
90
TCGv_ptr fpst;
115
+ stacked_ok = false;
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
116
+ }
92
case 0x05: /* FMLS */
117
+
93
case 0x09: /* FMUL */
118
+ if (!splimviol && stacked_ok) {
94
case 0x19: /* FMULX */
119
+ /* We only stack if the stack limit wasn't violated */
95
- is_fp = true;
120
+ int i;
96
+ is_fp = 1;
121
+ ARMMMUIdx mmu_idx;
97
break;
122
+
98
case 0x1d: /* SQRDMLAH */
123
+ mmu_idx = arm_v7m_mmu_idx_all(env, is_secure, is_priv, negpri);
99
case 0x1f: /* SQRDMLSH */
124
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
125
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
126
+ uint32_t faddr = fpcar + 4 * i;
127
+ uint32_t slo = extract64(dn, 0, 32);
128
+ uint32_t shi = extract64(dn, 32, 32);
129
+
130
+ if (i >= 16) {
131
+ faddr += 8; /* skip the slot for the FPSCR */
132
+ }
133
+ stacked_ok = stacked_ok &&
134
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, STACK_LAZYFP) &&
135
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, STACK_LAZYFP);
136
+ }
137
+
138
+ stacked_ok = stacked_ok &&
139
+ v7m_stack_write(cpu, fpcar + 0x40,
140
+ vfp_get_fpscr(env), mmu_idx, STACK_LAZYFP);
141
+ }
142
+
143
+ /*
144
+ * We definitely pended an exception, but it's possible that it
145
+ * might not be able to be taken now. If its priority permits us
146
+ * to take it now, then we must not update the LSPACT or FP regs,
147
+ * but instead jump out to take the exception immediately.
148
+ * If it's just pending and won't be taken until the current
149
+ * handler exits, then we do update LSPACT and the FP regs.
150
+ */
151
+ take_exception = !stacked_ok &&
152
+ armv7m_nvic_can_take_pending_exception(env->nvic);
153
+
154
+ qemu_mutex_unlock_iothread();
155
+
156
+ if (take_exception) {
157
+ raise_exception_ra(env, EXCP_LAZYFP, 0, 1, GETPC());
158
+ }
159
+
160
+ env->v7m.fpccr[is_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
161
+
162
+ if (ts) {
163
+ /* Clear s0 to s31 and the FPSCR */
164
+ int i;
165
+
166
+ for (i = 0; i < 32; i += 2) {
167
+ *aa32_vfp_dreg(env, i / 2) = 0;
168
+ }
169
+ vfp_set_fpscr(env, 0);
170
+ }
171
+ /*
172
+ * Otherwise s0 to s15 and FPSCR are UNKNOWN; we choose to leave them
173
+ * unchanged.
174
+ */
175
+}
176
+
177
/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
178
* This may change the current stack pointer between Main and Process
179
* stack pointers if it is done for the CONTROL register for the current
180
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
181
[EXCP_NOCP] = "v7M NOCP UsageFault",
182
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
183
[EXCP_STKOF] = "v8M STKOF UsageFault",
184
+ [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
185
};
186
187
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
188
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
101
return;
189
return;
102
}
190
}
103
break;
191
break;
104
+ case 0x11: /* FCMLA #0 */
192
+ case EXCP_LAZYFP:
105
+ case 0x13: /* FCMLA #90 */
193
+ /*
106
+ case 0x15: /* FCMLA #180 */
194
+ * We already pended the specific exception in the NVIC in the
107
+ case 0x17: /* FCMLA #270 */
195
+ * v7m_preserve_fp_state() helper function.
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
196
+ */
109
+ unallocated_encoding(s);
110
+ return;
111
+ }
112
+ is_fp = 2;
113
+ break;
197
+ break;
114
default:
198
default:
115
unallocated_encoding(s);
199
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
116
return;
200
return; /* Never happens. Keep compiler happy. */
201
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
202
flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
117
}
203
}
118
204
119
- if (is_fp) {
205
+ if (arm_feature(env, ARM_FEATURE_M)) {
120
+ switch (is_fp) {
206
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
121
+ case 1: /* normal fp */
207
+
122
/* convert insn encoded size to TCGMemOp size */
208
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
123
switch (size) {
209
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
124
case 0: /* half-precision */
210
+ }
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
211
+ }
126
- unallocated_encoding(s);
212
+
127
- return;
213
*pflags = flags;
128
- }
214
*cs_base = 0;
129
size = MO_16;
215
}
130
+ is_fp16 = true;
216
diff --git a/target/arm/translate.c b/target/arm/translate.c
131
break;
217
index XXXXXXX..XXXXXXX 100644
132
case MO_32: /* single precision */
218
--- a/target/arm/translate.c
133
case MO_64: /* double precision */
219
+++ b/target/arm/translate.c
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
220
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
221
if (arm_dc_feature(s, ARM_FEATURE_M)) {
136
return;
222
/* Handle M-profile lazy FP state mechanics */
137
}
223
138
- } else {
224
+ /* Trigger lazy-state preservation if necessary */
139
+ break;
225
+ if (s->v7m_lspact) {
140
+
226
+ /*
141
+ case 2: /* complex fp */
227
+ * Lazy state saving affects external memory and also the NVIC,
142
+ /* Each indexable element is a complex pair. */
228
+ * so we must mark it as an IO operation for icount.
143
+ size <<= 1;
229
+ */
144
+ switch (size) {
230
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
145
+ case MO_32:
231
+ gen_io_start();
146
+ if (h && !is_q) {
147
+ unallocated_encoding(s);
148
+ return;
149
+ }
232
+ }
150
+ is_fp16 = true;
233
+ gen_helper_v7m_preserve_fp_state(cpu_env);
151
+ break;
234
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
152
+ case MO_64:
235
+ gen_io_end();
153
+ break;
236
+ }
154
+ default:
237
+ /*
155
+ unallocated_encoding(s);
238
+ * If the preserve_fp_state helper doesn't throw an exception
156
+ return;
239
+ * then it will clear LSPACT; we don't need to repeat this for
157
+ }
240
+ * any further FP insns in this TB.
158
+ break;
241
+ */
159
+
242
+ s->v7m_lspact = false;
160
+ default: /* integer */
243
+ }
161
switch (size) {
244
+
162
case MO_8:
245
/* Update ownership of FP context: set FPCCR.S to match current state */
163
case MO_64:
246
if (s->v8m_fpccr_s_wrong) {
164
unallocated_encoding(s);
247
TCGv_i32 tmp;
165
return;
248
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
166
}
249
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
167
+ break;
250
dc->v7m_new_fp_ctxt_needed =
168
+ }
251
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
252
+ dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
170
+ unallocated_encoding(s);
253
dc->cp_regs = cpu->cp_regs;
171
+ return;
254
dc->features = env->features;
172
}
255
173
174
/* Given TCGMemOp size, adjust register and indexing. */
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
176
fpst = NULL;
177
}
178
179
+ switch (16 * u + opcode) {
180
+ case 0x11: /* FCMLA #0 */
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
195
+
196
if (size == 3) {
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
198
int pass;
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/vec_helper.c
202
+++ b/target/arm/vec_helper.c
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
204
}
205
clear_tail(d, opr_sz, simd_maxsz(desc));
206
}
207
+
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
209
+ void *vfpst, uint32_t desc)
210
+{
211
+ uintptr_t opr_sz = simd_oprsz(desc);
212
+ float16 *d = vd;
213
+ float16 *n = vn;
214
+ float16 *m = vm;
215
+ float_status *fpst = vfpst;
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
218
+ uint32_t neg_real = flip ^ neg_imag;
219
+ uintptr_t i;
220
+
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
222
+ neg_real <<= 15;
223
+ neg_imag <<= 15;
224
+
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
226
+ float16 e2 = n[H2(i + flip)];
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
228
+ float16 e4 = e2;
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
230
+
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
233
+ }
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
235
+}
236
+
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
238
+ void *vfpst, uint32_t desc)
239
+{
240
+ uintptr_t opr_sz = simd_oprsz(desc);
241
+ float16 *d = vd;
242
+ float16 *n = vn;
243
+ float16 *m = vm;
244
+ float_status *fpst = vfpst;
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
247
+ uint32_t neg_real = flip ^ neg_imag;
248
+ uintptr_t i;
249
+ float16 e1 = m[H2(flip)];
250
+ float16 e3 = m[H2(1 - flip)];
251
+
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
253
+ neg_real <<= 15;
254
+ neg_imag <<= 15;
255
+ e1 ^= neg_real;
256
+ e3 ^= neg_imag;
257
+
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
259
+ float16 e2 = n[H2(i + flip)];
260
+ float16 e4 = e2;
261
+
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
264
+ }
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
256
--
357
2.16.2
257
2.20.1
358
258
359
259
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
Implement the VLSTM instruction for v7M for the FPU present case.
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
3
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
5
and is intended be extended by adding extra devices to form a
6
complete system. It is used in the MPS2 board's AN505 image for the
7
Cortex-M33.
8
2
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
5
Message-id: 20190416125744.27770-25-peter.maydell@linaro.org
12
---
6
---
13
hw/arm/Makefile.objs | 1 +
7
target/arm/cpu.h | 2 +
14
include/hw/arm/iotkit.h | 109 ++++++++
8
target/arm/helper.h | 2 +
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
9
target/arm/helper.c | 84 ++++++++++++++++++++++++++++++++++++++++++
16
default-configs/arm-softmmu.mak | 1 +
10
target/arm/translate.c | 15 +++++++-
17
4 files changed, 709 insertions(+)
11
4 files changed, 102 insertions(+), 1 deletion(-)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
12
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
15
--- a/target/arm/cpu.h
24
+++ b/hw/arm/Makefile.objs
16
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
27
obj-$(CONFIG_MPS2) += mps2.o
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/arm/iotkit.h
35
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
36
+/*
18
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
37
+ * ARM IoT Kit
19
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
38
+ *
20
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
39
+ * Copyright (c) 2018 Linaro Limited
21
+#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
40
+ * Written by Peter Maydell
22
+#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
41
+ *
23
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
42
+ * This program is free software; you can redistribute it and/or modify
24
43
+ * it under the terms of the GNU General Public License version 2 or
25
#define ARMV7M_EXCP_RESET 1
44
+ * (at your option) any later version.
26
diff --git a/target/arm/helper.h b/target/arm/helper.h
45
+ */
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper.h
29
+++ b/target/arm/helper.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
31
32
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
33
34
+DEF_HELPER_2(v7m_vlstm, void, env, i32)
46
+
35
+
47
+/* This is a model of the Arm IoT Kit which is documented in
36
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
37
49
+ * It contains:
38
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
50
+ * a Cortex-M33
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
+ * the IDAU
40
index XXXXXXX..XXXXXXX 100644
52
+ * some timers and watchdogs
41
--- a/target/arm/helper.c
53
+ * two peripheral protection controllers
42
+++ b/target/arm/helper.c
54
+ * a memory protection controller
43
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
55
+ * a security controller
44
g_assert_not_reached();
56
+ * a bus fabric which arranges that some parts of the address
45
}
57
+ * space are secure and non-secure aliases of each other
46
58
+ *
47
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
59
+ * QEMU interface:
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
61
+ * by the board model.
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
65
+ * are wired to the NVIC lines 32 .. n+32
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
67
+ * might provide:
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
74
+ * might provide:
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
80
+ */
81
+
82
+#ifndef IOTKIT_H
83
+#define IOTKIT_H
84
+
85
+#include "hw/sysbus.h"
86
+#include "hw/arm/armv7m.h"
87
+#include "hw/misc/iotkit-secctl.h"
88
+#include "hw/misc/tz-ppc.h"
89
+#include "hw/timer/cmsdk-apb-timer.h"
90
+#include "hw/misc/unimp.h"
91
+#include "hw/or-irq.h"
92
+#include "hw/core/split-irq.h"
93
+
94
+#define TYPE_IOTKIT "iotkit"
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
96
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
98
+ * and the 2 internal PPCs
99
+ */
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+
103
+typedef struct IoTKit {
104
+ /*< private >*/
105
+ SysBusDevice parent_obj;
106
+
107
+ /*< public >*/
108
+ ARMv7MState armv7m;
109
+ IoTKitSecCtl secctl;
110
+ TZPPC apb_ppc0;
111
+ TZPPC apb_ppc1;
112
+ CMSDKAPBTIMER timer0;
113
+ CMSDKAPBTIMER timer1;
114
+ qemu_or_irq ppc_irq_orgate;
115
+ SplitIRQ sec_resp_splitter;
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
117
+
118
+ UnimplementedDeviceState dualtimer;
119
+ UnimplementedDeviceState s32ktimer;
120
+
121
+ MemoryRegion container;
122
+ MemoryRegion alias1;
123
+ MemoryRegion alias2;
124
+ MemoryRegion alias3;
125
+ MemoryRegion sram0;
126
+
127
+ qemu_irq *exp_irqs;
128
+ qemu_irq ppc0_irq;
129
+ qemu_irq ppc1_irq;
130
+ qemu_irq sec_resp_cfg;
131
+ qemu_irq sec_resp_cfg_in;
132
+ qemu_irq nsc_cfg_in;
133
+
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
135
+
136
+ uint32_t nsccfg;
137
+
138
+ /* Properties */
139
+ MemoryRegion *board_memory;
140
+ uint32_t exp_numirq;
141
+ uint32_t mainclk_frq;
142
+} IoTKit;
143
+
144
+#endif
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
146
new file mode 100644
147
index XXXXXXX..XXXXXXX
148
--- /dev/null
149
+++ b/hw/arm/iotkit.c
150
@@ -XXX,XX +XXX,XX @@
151
+/*
152
+ * Arm IoT Kit
153
+ *
154
+ * Copyright (c) 2018 Linaro Limited
155
+ * Written by Peter Maydell
156
+ *
157
+ * This program is free software; you can redistribute it and/or modify
158
+ * it under the terms of the GNU General Public License version 2 or
159
+ * (at your option) any later version.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "qapi/error.h"
165
+#include "trace.h"
166
+#include "hw/sysbus.h"
167
+#include "hw/registerfields.h"
168
+#include "hw/arm/iotkit.h"
169
+#include "hw/misc/unimp.h"
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
48
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
49
+ /* translate.c should never generate calls here in user-only mode */
179
+ /* The alias is even lower priority than unimplemented_device regions */
50
+ g_assert_not_reached();
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
51
+}
182
+
52
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
53
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
184
+ void *child, size_t childsize,
54
{
185
+ const char *childtype)
55
/* The TT instructions can be used by unprivileged code, but in
56
@@ -XXX,XX +XXX,XX @@ static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
57
}
58
}
59
60
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
186
+{
61
+{
187
+ object_initialize(child, childsize, childtype);
62
+ /* fptr is the value of Rn, the frame pointer we store the FP regs to */
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
63
+ bool s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
64
+ bool lspact = env->v7m.fpccr[s] & R_V7M_FPCCR_LSPACT_MASK;
190
+}
191
+
65
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
66
+ assert(env->v7m.secure);
193
+{
194
+ qemu_irq destirq = opaque;
195
+
67
+
196
+ qemu_set_irq(destirq, level);
68
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
215
+ DeviceState *iotkitdev = DEVICE(s);
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
69
+ return;
331
+ }
70
+ }
332
+
71
+
333
+ if (!s->mainclk_frq) {
72
+ /* Check access to the coprocessor is permitted */
334
+ error_setg(errp, "MAINCLK property was not set");
73
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
335
+ return;
74
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
336
+ }
75
+ }
337
+
76
+
338
+ /* Handling of which devices should be available only to secure
77
+ if (lspact) {
339
+ * code is usually done differently for M profile than for A profile.
78
+ /* LSPACT should not be active when there is active FP state */
340
+ * Instead of putting some devices only into the secure address space,
79
+ raise_exception_ra(env, EXCP_LSERR, 0, 1, GETPC());
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
373
+
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
375
+
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
378
+ * register in the IoT Kit System Control Register block, and the
379
+ * initial value of that is in turn specifiable by the FPGA that
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
382
+ */
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
80
+ }
400
+
81
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
82
+ if (fptr & 7) {
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
83
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
84
+ }
485
+
85
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
86
+ /*
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
87
+ * Note that we do not use v7m_stack_write() here, because the
488
+ if (err) {
88
+ * accesses should not set the FSR bits for stacking errors if they
489
+ error_propagate(errp, err);
89
+ * fail. (In pseudocode terms, they are AccType_NORMAL, not AccType_STACK
490
+ return;
90
+ * or AccType_LAZYFP). Faults in cpu_stl_data() will throw exceptions
491
+ }
91
+ * and longjmp out.
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
92
+ */
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
93
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
94
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
95
+ int i;
496
+ if (err) {
96
+
497
+ error_propagate(errp, err);
97
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
498
+ return;
98
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
99
+ uint32_t faddr = fptr + 4 * i;
100
+ uint32_t slo = extract64(dn, 0, 32);
101
+ uint32_t shi = extract64(dn, 32, 32);
102
+
103
+ if (i >= 16) {
104
+ faddr += 8; /* skip the slot for the FPSCR */
105
+ }
106
+ cpu_stl_data(env, faddr, slo);
107
+ cpu_stl_data(env, faddr + 4, shi);
108
+ }
109
+ cpu_stl_data(env, fptr + 0x40, vfp_get_fpscr(env));
110
+
111
+ /*
112
+ * If TS is 0 then s0 to s15 and FPSCR are UNKNOWN; we choose to
113
+ * leave them unchanged, matching our choice in v7m_preserve_fp_state.
114
+ */
115
+ if (ts) {
116
+ for (i = 0; i < 32; i += 2) {
117
+ *aa32_vfp_dreg(env, i / 2) = 0;
118
+ }
119
+ vfp_set_fpscr(env, 0);
120
+ }
121
+ } else {
122
+ v7m_update_fpccr(env, fptr, false);
499
+ }
123
+ }
500
+
124
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
125
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
637
+ if (err) {
638
+ error_propagate(errp, err);
639
+ return;
640
+ }
641
+ }
642
+
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
645
+
646
+ iotkit_forward_ppc(s, ppcname, i);
647
+ g_free(ppcname);
648
+ }
649
+
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
652
+
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
654
+ g_free(ppcname);
655
+ }
656
+
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
658
+ /* Wire up IRQ splitter for internal PPCs */
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
661
+ i - NUM_EXTERNAL_PPCS);
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
663
+
664
+ qdev_connect_gpio_out(devs, 0,
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
666
+ qdev_connect_gpio_out(devs, 1,
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
669
+ qdev_get_gpio_in(devs, 0));
670
+ }
671
+
672
+ iotkit_forward_sec_resp_cfg(s);
673
+
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
675
+}
126
+}
676
+
127
+
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
128
static bool v7m_push_stack(ARMCPU *cpu)
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
129
{
679
+{
130
/* Do the "set up stack frame" part of exception entry,
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
131
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
132
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
682
+ * NSCCFG register in the security controller.
133
[EXCP_STKOF] = "v8M STKOF UsageFault",
683
+ */
134
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
684
+ IoTKit *s = IOTKIT(ii);
135
+ [EXCP_LSERR] = "v8M LSERR UsageFault",
685
+ int region = extract32(address, 28, 4);
136
+ [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
137
};
138
139
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
140
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
141
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
142
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
143
break;
144
+ case EXCP_LSERR:
145
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
146
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
147
+ break;
148
+ case EXCP_UNALIGNED:
149
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
150
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
151
+ break;
152
case EXCP_SWI:
153
/* The PC already points to the next instruction. */
154
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
155
diff --git a/target/arm/translate.c b/target/arm/translate.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/translate.c
158
+++ b/target/arm/translate.c
159
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
160
if (!s->v8m_secure || (insn & 0x0040f0ff)) {
161
goto illegal_op;
162
}
163
- /* Just NOP since FP support is not implemented */
686
+
164
+
687
+ *ns = !(region & 1);
165
+ if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
166
+ TCGv_i32 fptr = load_reg(s, rn);
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
691
+ *iregion = region;
692
+}
693
+
167
+
694
+static const VMStateDescription iotkit_vmstate = {
168
+ if (extract32(insn, 20, 1)) {
695
+ .name = "iotkit",
169
+ /* VLLDM */
696
+ .version_id = 1,
170
+ } else {
697
+ .minimum_version_id = 1,
171
+ gen_helper_v7m_vlstm(cpu_env, fptr);
698
+ .fields = (VMStateField[]) {
172
+ }
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
173
+ tcg_temp_free_i32(fptr);
700
+ VMSTATE_END_OF_LIST()
701
+ }
702
+};
703
+
174
+
704
+static Property iotkit_properties[] = {
175
+ /* End the TB, because we have updated FP control bits */
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
176
+ s->base.is_jmp = DISAS_UPDATE;
706
+ MemoryRegion *),
177
+ }
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
178
break;
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
179
}
709
+ DEFINE_PROP_END_OF_LIST()
180
if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
710
+};
711
+
712
+static void iotkit_reset(DeviceState *dev)
713
+{
714
+ IoTKit *s = IOTKIT(dev);
715
+
716
+ s->nsccfg = 0;
717
+}
718
+
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
720
+{
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
752
+++ b/default-configs/arm-softmmu.mak
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
754
CONFIG_MPS2_SCC=y
755
756
CONFIG_TZ_PPC=y
757
+CONFIG_IOTKIT=y
758
CONFIG_IOTKIT_SECCTL=y
759
760
CONFIG_VERSATILE_PCI=y
761
--
181
--
762
2.16.2
182
2.20.1
763
183
764
184
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the VLLDM instruction for v7M for the FPU present cas.
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-26-peter.maydell@linaro.org
7
---
6
---
8
target/arm/helper.h | 9 +++++
7
target/arm/helper.h | 1 +
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
8
target/arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++++++++
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
9
target/arm/translate.c | 2 +-
11
3 files changed, 166 insertions(+)
10
3 files changed, 56 insertions(+), 1 deletion(-)
12
11
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
14
--- a/target/arm/helper.h
16
+++ b/target/arm/helper.h
15
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
17
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
18
20
19
DEF_HELPER_2(v7m_vlstm, void, env, i32)
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
20
+DEF_HELPER_2(v7m_vlldm, void, env, i32)
22
+ void, ptr, ptr, ptr, ptr, i32)
21
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
22
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
24
+ void, ptr, ptr, ptr, ptr, i32)
23
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+
30
#ifdef TARGET_AARCH64
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
26
--- a/target/arm/helper.c
36
+++ b/target/arm/translate-a64.c
27
+++ b/target/arm/helper.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
28
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
38
vec_full_reg_size(s), gvec_op);
29
g_assert_not_reached();
39
}
30
}
40
31
41
+/* Expand a 3-operand + env pointer operation using
32
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
42
+ * an out-of-line helper.
43
+ */
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
46
+{
33
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
34
+ /* translate.c should never generate calls here in user-only mode */
48
+ vec_full_reg_offset(s, rn),
35
+ g_assert_not_reached();
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
36
+}
52
+
37
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
38
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
54
* than the 32 bit equivalent.
39
{
55
*/
40
/* The TT instructions can be used by unprivileged code, but in
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
41
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
57
clear_vec_high(s, is_q, rd);
42
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
58
}
43
}
59
44
60
+/* AdvSIMD three same extra
45
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
46
+{
68
+ int rd = extract32(insn, 0, 5);
47
+ /* fptr is the value of Rn, the frame pointer we load the FP regs from */
69
+ int rn = extract32(insn, 5, 5);
48
+ assert(env->v7m.secure);
70
+ int opcode = extract32(insn, 11, 4);
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
49
+
77
+ switch (u * 16 + opcode) {
50
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
78
+ case 0x10: /* SQRDMLAH (vector) */
79
+ case 0x11: /* SQRDMLSH (vector) */
80
+ if (size != 1 && size != 2) {
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ feature = ARM_FEATURE_V8_RDM;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
90
+ if (!arm_dc_feature(s, feature)) {
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
51
+ return;
96
+ }
52
+ }
97
+
53
+
98
+ switch (opcode) {
54
+ /* Check access to the coprocessor is permitted */
99
+ case 0x0: /* SQRDMLAH (vector) */
55
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
100
+ switch (size) {
56
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
101
+ case 1:
57
+ }
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
58
+
103
+ break;
59
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
104
+ case 2:
60
+ /* State in FP is still valid */
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
61
+ env->v7m.fpccr[M_REG_S] &= ~R_V7M_FPCCR_LSPACT_MASK;
106
+ break;
62
+ } else {
107
+ default:
63
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
108
+ g_assert_not_reached();
64
+ int i;
65
+ uint32_t fpscr;
66
+
67
+ if (fptr & 7) {
68
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
109
+ }
69
+ }
110
+ return;
111
+
70
+
112
+ case 0x1: /* SQRDMLSH (vector) */
71
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
113
+ switch (size) {
72
+ uint32_t slo, shi;
114
+ case 1:
73
+ uint64_t dn;
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
74
+ uint32_t faddr = fptr + 4 * i;
116
+ break;
75
+
117
+ case 2:
76
+ if (i >= 16) {
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
77
+ faddr += 8; /* skip the slot for the FPSCR */
119
+ break;
78
+ }
120
+ default:
79
+
121
+ g_assert_not_reached();
80
+ slo = cpu_ldl_data(env, faddr);
81
+ shi = cpu_ldl_data(env, faddr + 4);
82
+
83
+ dn = (uint64_t) shi << 32 | slo;
84
+ *aa32_vfp_dreg(env, i / 2) = dn;
122
+ }
85
+ }
123
+ return;
86
+ fpscr = cpu_ldl_data(env, fptr + 0x40);
87
+ vfp_set_fpscr(env, fpscr);
88
+ }
124
+
89
+
125
+ default:
90
+ env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
126
+ g_assert_not_reached();
127
+ }
128
+}
91
+}
129
+
92
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
93
static bool v7m_push_stack(ARMCPU *cpu)
131
int size, int rn, int rd)
132
{
94
{
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
95
/* Do the "set up stack frame" part of exception entry,
134
static const AArch64DecodeTable data_proc_simd[] = {
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
135
/* pattern , mask , fn */
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
142
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
98
--- a/target/arm/translate.c
144
+++ b/target/arm/vec_helper.c
99
+++ b/target/arm/translate.c
145
@@ -XXX,XX +XXX,XX @@
100
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
146
101
TCGv_i32 fptr = load_reg(s, rn);
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
102
148
103
if (extract32(insn, 20, 1)) {
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
104
- /* VLLDM */
150
+{
105
+ gen_helper_v7m_vlldm(cpu_env, fptr);
151
+ uint64_t *d = vd + opr_sz;
106
} else {
152
+ uintptr_t i;
107
gen_helper_v7m_vlstm(cpu_env, fptr);
153
+
108
}
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
157
+}
158
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
161
int16_t src2, int16_t src3)
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
163
return deposit32(e1, 16, 16, e2);
164
}
165
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
167
+ void *ve, uint32_t desc)
168
+{
169
+ uintptr_t opr_sz = simd_oprsz(desc);
170
+ int16_t *d = vd;
171
+ int16_t *n = vn;
172
+ int16_t *m = vm;
173
+ CPUARMState *env = ve;
174
+ uintptr_t i;
175
+
176
+ for (i = 0; i < opr_sz / 2; ++i) {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
178
+ }
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
180
+}
181
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
184
int16_t src2, int16_t src3)
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
186
return deposit32(e1, 16, 16, e2);
187
}
188
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
190
+ void *ve, uint32_t desc)
191
+{
192
+ uintptr_t opr_sz = simd_oprsz(desc);
193
+ int16_t *d = vd;
194
+ int16_t *n = vn;
195
+ int16_t *m = vm;
196
+ CPUARMState *env = ve;
197
+ uintptr_t i;
198
+
199
+ for (i = 0; i < opr_sz / 2; ++i) {
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
201
+ }
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
203
+}
204
+
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
207
int32_t src2, int32_t src3)
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
209
return ret;
210
}
211
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
213
+ void *ve, uint32_t desc)
214
+{
215
+ uintptr_t opr_sz = simd_oprsz(desc);
216
+ int32_t *d = vd;
217
+ int32_t *n = vn;
218
+ int32_t *m = vm;
219
+ CPUARMState *env = ve;
220
+ uintptr_t i;
221
+
222
+ for (i = 0; i < opr_sz / 4; ++i) {
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
227
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
230
int32_t src2, int32_t src3)
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
232
}
233
return ret;
234
}
235
+
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
237
+ void *ve, uint32_t desc)
238
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
240
+ int32_t *d = vd;
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
248
+ }
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
250
+}
251
--
109
--
252
2.16.2
110
2.20.1
253
111
254
112
diff view generated by jsdifflib
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
1
Enable the FPU by default for the Cortex-M4 and Cortex-M33.
2
which implements the ARM v8M architecture, including the
3
M profile Security Extension.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-9-peter.maydell@linaro.org
5
Message-id: 20190416125744.27770-27-peter.maydell@linaro.org
8
---
6
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
7
target/arm/cpu.c | 8 ++++++++
10
1 file changed, 31 insertions(+)
8
1 file changed, 8 insertions(+)
11
9
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
10
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
12
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
13
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
14
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
17
cpu->id_isar5 = 0x00000000;
15
set_feature(&cpu->env, ARM_FEATURE_M);
18
}
16
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
19
17
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
20
+static void cortex_m33_initfn(Object *obj)
18
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
21
+{
19
cpu->midr = 0x410fc240; /* r0p0 */
22
+ ARMCPU *cpu = ARM_CPU(obj);
20
cpu->pmsav7_dregion = 8;
23
+
21
+ cpu->isar.mvfr0 = 0x10110021;
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
22
+ cpu->isar.mvfr1 = 0x11000011;
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
23
+ cpu->isar.mvfr2 = 0x00000000;
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
24
cpu->id_pfr0 = 0x00000030;
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
25
cpu->id_pfr1 = 0x00000200;
28
+ cpu->midr = 0x410fd213; /* r0p3 */
26
cpu->id_dfr0 = 0x00100000;
29
+ cpu->pmsav7_dregion = 16;
27
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
30
+ cpu->sau_sregion = 8;
28
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
31
+ cpu->id_pfr0 = 0x00000030;
29
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
32
+ cpu->id_pfr1 = 0x00000210;
30
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
33
+ cpu->id_dfr0 = 0x00200000;
31
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
34
+ cpu->id_afr0 = 0x00000000;
32
cpu->midr = 0x410fd213; /* r0p3 */
35
+ cpu->id_mmfr0 = 0x00101F40;
33
cpu->pmsav7_dregion = 16;
36
+ cpu->id_mmfr1 = 0x00000000;
34
cpu->sau_sregion = 8;
37
+ cpu->id_mmfr2 = 0x01000000;
35
+ cpu->isar.mvfr0 = 0x10110021;
38
+ cpu->id_mmfr3 = 0x00000000;
36
+ cpu->isar.mvfr1 = 0x11000011;
39
+ cpu->id_isar0 = 0x01101110;
37
+ cpu->isar.mvfr2 = 0x00000040;
40
+ cpu->id_isar1 = 0x02212000;
38
cpu->id_pfr0 = 0x00000030;
41
+ cpu->id_isar2 = 0x20232232;
39
cpu->id_pfr1 = 0x00000210;
42
+ cpu->id_isar3 = 0x01111131;
40
cpu->id_dfr0 = 0x00200000;
43
+ cpu->id_isar4 = 0x01310132;
44
+ cpu->id_isar5 = 0x00000000;
45
+ cpu->clidr = 0x00000000;
46
+ cpu->ctr = 0x8000c000;
47
+}
48
+
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
50
{
51
CPUClass *cc = CPU_CLASS(oc);
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
53
.class_init = arm_v7m_class_init },
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
55
.class_init = arm_v7m_class_init },
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
57
+ .class_init = arm_v7m_class_init },
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
61
--
41
--
62
2.16.2
42
2.20.1
63
43
64
44
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
This device is used by both ARM (BCM2836, for raspi2) and AArch64
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
(BCM2837, for raspi3) targets, and is not CPU-specific.
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
5
Move it to common object, so we build it once for all targets.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190427133028.12874-1-philmd@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
12
hw/dma/Makefile.objs | 2 +-
9
1 file changed, 29 insertions(+)
13
1 file changed, 1 insertion(+), 1 deletion(-)
10
14
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
17
--- a/hw/dma/Makefile.objs
14
+++ b/target/arm/translate-a64.c
18
+++ b/hw/dma/Makefile.objs
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o
16
case 0x19: /* FMULX */
20
17
is_fp = true;
21
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
18
break;
22
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
19
+ case 0x1d: /* SQRDMLAH */
23
-obj-$(CONFIG_RASPI) += bcm2835_dma.o
20
+ case 0x1f: /* SQRDMLSH */
24
+common-obj-$(CONFIG_RASPI) += bcm2835_dma.o
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
22
+ unallocated_encoding(s);
23
+ return;
24
+ }
25
+ break;
26
default:
27
unallocated_encoding(s);
28
return;
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
30
tcg_op, tcg_idx);
31
}
32
break;
33
+ case 0x1d: /* SQRDMLAH */
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
35
+ is_scalar ? size : MO_32);
36
+ if (size == 1) {
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
38
+ tcg_op, tcg_idx, tcg_res);
39
+ } else {
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
41
+ tcg_op, tcg_idx, tcg_res);
42
+ }
43
+ break;
44
+ case 0x1f: /* SQRDMLSH */
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
46
+ is_scalar ? size : MO_32);
47
+ if (size == 1) {
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
49
+ tcg_op, tcg_idx, tcg_res);
50
+ } else {
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
58
--
25
--
59
2.16.2
26
2.20.1
60
27
61
28
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Cédric Le Goater <clg@kaod.org>
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190412165416.7977-2-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/helper.h | 7 ++++
10
hw/arm/aspeed.c | 13 +++++++++----
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
11
1 file changed, 9 insertions(+), 4 deletions(-)
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 151 insertions(+), 1 deletion(-)
12
12
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
15
--- a/hw/arm/aspeed.c
16
+++ b/target/arm/helper.h
16
+++ b/hw/arm/aspeed.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
17
@@ -XXX,XX +XXX,XX @@
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
18
#include "hw/arm/aspeed_soc.h"
19
void, ptr, ptr, ptr, ptr, i32)
19
#include "hw/boards.h"
20
20
#include "hw/i2c/smbus_eeprom.h"
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
21
+#include "hw/misc/pca9552.h"
22
+ void, ptr, ptr, ptr, ptr, i32)
22
+#include "hw/misc/tmp105.h"
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
23
#include "qemu/log.h"
24
+ void, ptr, ptr, ptr, ptr, i32)
24
#include "sysemu/block-backend.h"
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
25
#include "hw/loader.h"
26
+ void, ptr, ptr, ptr, ptr, i32)
26
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
27
+
27
eeprom_buf);
28
#ifdef TARGET_AARCH64
28
29
#include "helper-a64.h"
29
/* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
30
#endif
30
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
31
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7),
32
index XXXXXXX..XXXXXXX 100644
32
+ TYPE_TMP105, 0x4d);
33
--- a/target/arm/translate-a64.c
33
34
+++ b/target/arm/translate-a64.c
34
/* The AST2500 EVB does not have an RTC. Let's pretend that one is
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
35
* plugged on the I2C bus header */
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
36
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
37
AspeedSoCState *soc = &bmc->soc;
38
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
39
40
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60);
41
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
42
+ 0x60);
43
44
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
45
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
46
47
/* The Witherspoon expects a TMP275 but a TMP105 is compatible */
48
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp105", 0x4a);
49
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), TYPE_TMP105,
50
+ 0x4a);
51
52
/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
53
* good enough */
54
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
55
56
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
57
eeprom_buf);
58
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "pca9552",
59
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
60
0x60);
37
}
61
}
38
62
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
40
+ * an out-of-line helper.
41
+ */
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
43
+ int rm, bool is_fp16, int data,
44
+ gen_helper_gvec_3_ptr *fn)
45
+{
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), fpst,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
51
+ tcg_temp_free_ptr(fpst);
52
+}
53
+
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
55
* than the 32 bit equivalent.
56
*/
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
58
int size = extract32(insn, 22, 2);
59
bool u = extract32(insn, 29, 1);
60
bool is_q = extract32(insn, 30, 1);
61
- int feature;
62
+ int feature, rot;
63
64
switch (u * 16 + opcode) {
65
case 0x10: /* SQRDMLAH (vector) */
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
}
68
feature = ARM_FEATURE_V8_RDM;
69
break;
70
+ case 0xc: /* FCADD, #90 */
71
+ case 0xe: /* FCADD, #270 */
72
+ if (size == 0
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
74
+ || (size == 3 && !is_q)) {
75
+ unallocated_encoding(s);
76
+ return;
77
+ }
78
+ feature = ARM_FEATURE_V8_FCMA;
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
84
}
85
return;
86
87
+ case 0xc: /* FCADD, #90 */
88
+ case 0xe: /* FCADD, #270 */
89
+ rot = extract32(opcode, 1, 1);
90
+ switch (size) {
91
+ case 1:
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
93
+ gen_helper_gvec_fcaddh);
94
+ break;
95
+ case 2:
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
97
+ gen_helper_gvec_fcadds);
98
+ break;
99
+ case 3:
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
101
+ gen_helper_gvec_fcaddd);
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
+ }
106
+ return;
107
+
108
default:
109
g_assert_not_reached();
110
}
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
141
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
143
+ void *vfpst, uint32_t desc)
144
+{
145
+ uintptr_t opr_sz = simd_oprsz(desc);
146
+ float16 *d = vd;
147
+ float16 *n = vn;
148
+ float16 *m = vm;
149
+ float_status *fpst = vfpst;
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
151
+ uint32_t neg_imag = neg_real ^ 1;
152
+ uintptr_t i;
153
+
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
155
+ neg_real <<= 15;
156
+ neg_imag <<= 15;
157
+
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
159
+ float16 e0 = n[H2(i)];
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
161
+ float16 e2 = n[H2(i + 1)];
162
+ float16 e3 = m[H2(i)] ^ neg_real;
163
+
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
169
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
171
+ void *vfpst, uint32_t desc)
172
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
174
+ float32 *d = vd;
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
197
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
199
+ void *vfpst, uint32_t desc)
200
+{
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
63
--
226
2.16.2
64
2.20.1
227
65
228
66
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
Suggested-by: Markus Armbruster <armbru@redhat.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
At present we can of course invoke an invalid insn exception from within
5
Message-id: 20190412165416.7977-3-philmd@redhat.com
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
8
---
15
scripts/decodetree.py | 5 ++---
9
hw/arm/nseries.c | 3 ++-
16
1 file changed, 2 insertions(+), 3 deletions(-)
10
1 file changed, 2 insertions(+), 1 deletion(-)
17
11
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
12
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
19
index XXXXXXX..XXXXXXX 100755
13
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/decodetree.py
14
--- a/hw/arm/nseries.c
21
+++ b/scripts/decodetree.py
15
+++ b/hw/arm/nseries.c
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
16
@@ -XXX,XX +XXX,XX @@
23
global translate_prefix
17
#include "hw/boards.h"
24
output('typedef ', self.base.base.struct_name(),
18
#include "hw/i2c/i2c.h"
25
' arg_', self.name, ';\n')
19
#include "hw/devices.h"
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
20
+#include "hw/misc/tmp105.h"
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
21
#include "hw/block/flash.h"
28
'(DisasContext *ctx, arg_', self.name,
22
#include "hw/hw.h"
29
' *a, ', insntype, ' insn);\n')
23
#include "hw/bt.h"
30
24
@@ -XXX,XX +XXX,XX @@ static void n8x0_i2c_setup(struct n800_s *s)
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
25
qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
26
33
for n, f in self.fields.items():
27
/* Attach a TMP105 PM chip (A0 wired to ground) */
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
28
- dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
35
- output(ind, translate_prefix, '_', self.name,
29
+ dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR);
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
30
qdev_connect_gpio_out(dev, 0, tmp_irq);
37
'(ctx, &u.f_', arg, ', insn);\n')
31
}
38
- output(ind, 'return true;\n')
39
# end Pattern
40
41
32
42
--
33
--
43
2.16.2
34
2.20.1
44
35
45
36
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
No code used the tc6393xb_gpio_in_get() and tc6393xb_gpio_out_set()
4
functions since their introduction in commit 88d2c950b002. Time to
5
remove them.
4
6
5
This includes adding a trace event to debug the new time.
7
Suggested-by: Markus Armbruster <armbru@redhat.com>
6
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
9
Message-id: 20190412165416.7977-4-philmd@redhat.com
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
13
include/hw/devices.h | 3 ---
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
14
hw/display/tc6393xb.c | 16 ----------------
14
hw/timer/trace-events | 3 ++
15
2 files changed, 19 deletions(-)
15
3 files changed, 63 insertions(+)
16
16
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
19
--- a/include/hw/devices.h
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
20
+++ b/include/hw/devices.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
21
@@ -XXX,XX +XXX,XX @@ void retu_key_event(void *retu, int state);
22
qemu_irq irq_rtc_int;
22
typedef struct TC6393xbState TC6393xbState;
23
qemu_irq irq_addr_error_int;
23
TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
24
24
uint32_t base, qemu_irq irq);
25
+ uint32_t tick_offset;
25
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
26
+
26
- qemu_irq handler);
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
27
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
28
qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
29
} XlnxZynqMPRTC;
29
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
30
#endif
31
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
31
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
33
--- a/hw/display/tc6393xb.c
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
34
+++ b/hw/display/tc6393xb.c
34
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@ struct TC6393xbState {
35
#include "hw/register.h"
36
blanked : 1;
36
#include "qemu/bitops.h"
37
};
37
#include "qemu/log.h"
38
38
+#include "hw/ptimer.h"
39
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
39
+#include "qemu/cutils.h"
40
-{
40
+#include "sysemu/sysemu.h"
41
- return s->gpio_in;
41
+#include "trace.h"
42
-}
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
43
-
43
44
static void tc6393xb_gpio_set(void *opaque, int line, int level)
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
45
{
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
46
// TC6393xbState *s = opaque;
46
qemu_set_irq(s->irq_addr_error_int, pending);
47
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_gpio_set(void *opaque, int line, int level)
48
// FIXME: how does the chip reflect the GPIO input level change?
47
}
49
}
48
50
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
51
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
50
+{
52
- qemu_irq handler)
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
53
-{
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
54
- if (line >= TC6393XB_GPIOS) {
53
+}
55
- fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line);
54
+
56
- return;
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
57
- }
56
+{
58
-
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
59
- s->handler[line] = handler;
58
+
60
-}
59
+ return rtc_get_count(s);
61
-
60
+}
62
static void tc6393xb_gpio_handler_update(TC6393xbState *s)
61
+
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
63
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
64
uint32_t level, diff;
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
66
67
static const RegisterAccessInfo rtc_regs_info[] = {
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
71
.ro = 0xffffffff,
72
+ .post_read = current_time_postr,
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
76
.ro = 0x1fffff,
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
78
.ro = 0xffffffff,
79
+ .post_read = current_time_postr,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
129
130
static const VMStateDescription vmstate_rtc = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
143
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
150
+
151
+# hw/timer/xlnx-zynqmp-rtc.c
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
153
--
65
--
154
2.16.2
66
2.20.1
155
67
156
68
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
containing a Cortex-M33. Since the FPGA images for TrustZone
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
4
significantly different layout of devices to the non-TrustZone
5
images, we use a new source file rather than shoehorning them
6
into the existing mps2.c.
7
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20190412165416.7977-5-philmd@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
11
---
7
---
12
hw/arm/Makefile.objs | 1 +
8
include/hw/devices.h | 6 ------
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
9
include/hw/display/tc6393xb.h | 24 ++++++++++++++++++++++++
14
2 files changed, 504 insertions(+)
10
hw/arm/tosa.c | 2 +-
15
create mode 100644 hw/arm/mps2-tz.c
11
hw/display/tc6393xb.c | 2 +-
12
MAINTAINERS | 1 +
13
5 files changed, 27 insertions(+), 8 deletions(-)
14
create mode 100644 include/hw/display/tc6393xb.h
16
15
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
18
--- a/include/hw/devices.h
20
+++ b/hw/arm/Makefile.objs
19
+++ b/include/hw/devices.h
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
20
@@ -XXX,XX +XXX,XX @@ void *tahvo_init(qemu_irq irq, int betty);
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
21
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
22
void retu_key_event(void *retu, int state);
24
obj-$(CONFIG_MPS2) += mps2.o
23
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
24
-/* tc6393xb.c */
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
25
-typedef struct TC6393xbState TC6393xbState;
27
obj-$(CONFIG_IOTKIT) += iotkit.o
26
-TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
- uint32_t base, qemu_irq irq);
28
-qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
29
-
30
#endif
31
diff --git a/include/hw/display/tc6393xb.h b/include/hw/display/tc6393xb.h
29
new file mode 100644
32
new file mode 100644
30
index XXXXXXX..XXXXXXX
33
index XXXXXXX..XXXXXXX
31
--- /dev/null
34
--- /dev/null
32
+++ b/hw/arm/mps2-tz.c
35
+++ b/include/hw/display/tc6393xb.h
33
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
34
+/*
37
+/*
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
38
+ * Toshiba TC6393XB I/O Controller.
39
+ * Found in Sharp Zaurus SL-6000 (tosa) or some
40
+ * Toshiba e-Series PDAs.
36
+ *
41
+ *
37
+ * Copyright (c) 2017 Linaro Limited
42
+ * Copyright (c) 2007 Hervé Poussineau
38
+ * Written by Peter Maydell
39
+ *
43
+ *
40
+ * This program is free software; you can redistribute it and/or modify
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
41
+ * it under the terms of the GNU General Public License version 2 or
45
+ * See the COPYING file in the top-level directory.
42
+ * (at your option) any later version.
43
+ */
46
+ */
44
+
47
+
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
48
+#ifndef HW_DISPLAY_TC6393XB_H
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
49
+#define HW_DISPLAY_TC6393XB_H
47
+ * and most of the devices are in the FPGA, the details of the board
48
+ * as seen by the guest depend significantly on the FPGA image.
49
+ * This source file covers the following FPGA images, for TrustZone cores:
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
51
+ *
52
+ * Links to the TRM for the board itself and to the various Application
53
+ * Notes which document the FPGA images can be found here:
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
55
+ *
56
+ * Board TRM:
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
58
+ * Application Note AN505:
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
60
+ *
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
62
+ * (ARM ECM0601256) for the details of some of the device layout:
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
64
+ */
65
+
50
+
66
+#include "qemu/osdep.h"
51
+#include "exec/memory.h"
67
+#include "qapi/error.h"
52
+#include "hw/irq.h"
68
+#include "qemu/error-report.h"
69
+#include "hw/arm/arm.h"
70
+#include "hw/arm/armv7m.h"
71
+#include "hw/or-irq.h"
72
+#include "hw/boards.h"
73
+#include "exec/address-spaces.h"
74
+#include "sysemu/sysemu.h"
75
+#include "hw/misc/unimp.h"
76
+#include "hw/char/cmsdk-apb-uart.h"
77
+#include "hw/timer/cmsdk-apb-timer.h"
78
+#include "hw/misc/mps2-scc.h"
79
+#include "hw/misc/mps2-fpgaio.h"
80
+#include "hw/arm/iotkit.h"
81
+#include "hw/devices.h"
82
+#include "net/net.h"
83
+#include "hw/core/split-irq.h"
84
+
53
+
85
+typedef enum MPS2TZFPGAType {
54
+typedef struct TC6393xbState TC6393xbState;
86
+ FPGA_AN505,
87
+} MPS2TZFPGAType;
88
+
55
+
89
+typedef struct {
56
+TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
90
+ MachineClass parent;
57
+ uint32_t base, qemu_irq irq);
91
+ MPS2TZFPGAType fpga_type;
58
+qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
92
+ uint32_t scc_id;
93
+} MPS2TZMachineClass;
94
+
59
+
95
+typedef struct {
60
+#endif
96
+ MachineState parent;
61
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
97
+
62
index XXXXXXX..XXXXXXX 100644
98
+ IoTKit iotkit;
63
--- a/hw/arm/tosa.c
99
+ MemoryRegion psram;
64
+++ b/hw/arm/tosa.c
100
+ MemoryRegion ssram1;
65
@@ -XXX,XX +XXX,XX @@
101
+ MemoryRegion ssram1_m;
66
#include "hw/hw.h"
102
+ MemoryRegion ssram23;
67
#include "hw/arm/pxa.h"
103
+ MPS2SCC scc;
68
#include "hw/arm/arm.h"
104
+ MPS2FPGAIO fpgaio;
69
-#include "hw/devices.h"
105
+ TZPPC ppc[5];
70
#include "hw/arm/sharpsl.h"
106
+ UnimplementedDeviceState ssram_mpc[3];
71
#include "hw/pcmcia.h"
107
+ UnimplementedDeviceState spi[5];
72
#include "hw/boards.h"
108
+ UnimplementedDeviceState i2c[4];
73
+#include "hw/display/tc6393xb.h"
109
+ UnimplementedDeviceState i2s_audio;
74
#include "hw/i2c/i2c.h"
110
+ UnimplementedDeviceState gpio[5];
75
#include "hw/ssi/ssi.h"
111
+ UnimplementedDeviceState dma[4];
76
#include "hw/sysbus.h"
112
+ UnimplementedDeviceState gfx;
77
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
113
+ CMSDKAPBUART uart[5];
78
index XXXXXXX..XXXXXXX 100644
114
+ SplitIRQ sec_resp_splitter;
79
--- a/hw/display/tc6393xb.c
115
+ qemu_or_irq uart_irq_orgate;
80
+++ b/hw/display/tc6393xb.c
116
+} MPS2TZMachineState;
81
@@ -XXX,XX +XXX,XX @@
117
+
82
#include "qapi/error.h"
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
83
#include "qemu/host-utils.h"
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
84
#include "hw/hw.h"
120
+
85
-#include "hw/devices.h"
121
+#define MPS2TZ_MACHINE(obj) \
86
+#include "hw/display/tc6393xb.h"
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
87
#include "hw/block/flash.h"
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
88
#include "ui/console.h"
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
89
#include "ui/pixel_ops.h"
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
90
diff --git a/MAINTAINERS b/MAINTAINERS
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
91
index XXXXXXX..XXXXXXX 100644
127
+
92
--- a/MAINTAINERS
128
+/* Main SYSCLK frequency in Hz */
93
+++ b/MAINTAINERS
129
+#define SYSCLK_FRQ 20000000
94
@@ -XXX,XX +XXX,XX @@ F: hw/misc/mst_fpga.c
130
+
95
F: hw/misc/max111x.c
131
+/* Initialize the auxiliary RAM region @mr and map it into
96
F: include/hw/arm/pxa.h
132
+ * the memory map at @base.
97
F: include/hw/arm/sharpsl.h
133
+ */
98
+F: include/hw/display/tc6393xb.h
134
+static void make_ram(MemoryRegion *mr, const char *name,
99
135
+ hwaddr base, hwaddr size)
100
SABRELITE / i.MX6
136
+{
101
M: Peter Maydell <peter.maydell@linaro.org>
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
139
+}
140
+
141
+/* Create an alias of an entire original MemoryRegion @orig
142
+ * located at @base in the memory map.
143
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
145
+ MemoryRegion *orig, hwaddr base)
146
+{
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
148
+ memory_region_size(orig));
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
150
+}
151
+
152
+static void init_sysbus_child(Object *parent, const char *childname,
153
+ void *child, size_t childsize,
154
+ const char *childtype)
155
+{
156
+ object_initialize(child, childsize, childtype);
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
159
+
160
+}
161
+
162
+/* Most of the devices in the AN505 FPGA image sit behind
163
+ * Peripheral Protection Controllers. These data structures
164
+ * define the layout of which devices sit behind which PPCs.
165
+ * The devfn for each port is a function which creates, configures
166
+ * and initializes the device, returning the MemoryRegion which
167
+ * needs to be plugged into the downstream end of the PPC port.
168
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
170
+ const char *name, hwaddr size);
171
+
172
+typedef struct PPCPortInfo {
173
+ const char *name;
174
+ MakeDevFn *devfn;
175
+ void *opaque;
176
+ hwaddr addr;
177
+ hwaddr size;
178
+} PPCPortInfo;
179
+
180
+typedef struct PPCInfo {
181
+ const char *name;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
183
+} PPCInfo;
184
+
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
186
+ void *opaque,
187
+ const char *name, hwaddr size)
188
+{
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
190
+ * and return a pointer to its MemoryRegion.
191
+ */
192
+ UnimplementedDeviceState *uds = opaque;
193
+
194
+ init_sysbus_child(OBJECT(mms), name, uds,
195
+ sizeof(UnimplementedDeviceState),
196
+ TYPE_UNIMPLEMENTED_DEVICE);
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
201
+}
202
+
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
204
+ const char *name, hwaddr size)
205
+{
206
+ CMSDKAPBUART *uart = opaque;
207
+ int i = uart - &mms->uart[0];
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
209
+ int rxirqno = i * 2;
210
+ int txirqno = i * 2 + 1;
211
+ int combirqno = i + 10;
212
+ SysBusDevice *s;
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
215
+
216
+ init_sysbus_child(OBJECT(mms), name, uart,
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
221
+ s = SYS_BUS_DEVICE(uart);
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
223
+ "EXP_IRQ", txirqno));
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
225
+ "EXP_IRQ", rxirqno));
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
229
+ "EXP_IRQ", combirqno));
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
231
+}
232
+
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
234
+ const char *name, hwaddr size)
235
+{
236
+ MPS2SCC *scc = opaque;
237
+ DeviceState *sccdev;
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
239
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
241
+ sccdev = DEVICE(scc);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
248
+}
249
+
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
251
+ const char *name, hwaddr size)
252
+{
253
+ MPS2FPGAIO *fpgaio = opaque;
254
+
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
259
+}
260
+
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
290
+ TYPE_SPLIT_IRQ);
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
294
+ "num-lines", &error_fatal);
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
296
+ "realized", &error_fatal);
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
299
+ qdev_get_gpio_in(dev_splitter, 0));
300
+
301
+ /* The IoTKit sets up much of the memory layout, including
302
+ * the aliases between secure and non-secure regions in the
303
+ * address space. The FPGA itself contains:
304
+ *
305
+ * 0x00000000..0x003fffff SSRAM1
306
+ * 0x00400000..0x007fffff alias of SSRAM1
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
310
+ */
311
+
312
+ /* The FPGA images have an odd combination of different RAMs,
313
+ * because in hardware they are different implementations and
314
+ * connected to different buses, giving varying performance/size
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
316
+ * call the 16MB our "system memory", as it's the largest lump.
317
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
319
+ NULL, "mps.ram", 0x01000000);
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
321
+
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
323
+ * but we don't implement that yet.
324
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
327
+
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
329
+
330
+ /* The overflow IRQs for all UARTs are ORed together.
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
332
+ * Create the OR gate for this.
333
+ */
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
335
+ TYPE_OR_IRQ);
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
412
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
414
+ const PPCInfo *ppcinfo = &ppcs[i];
415
+ TZPPC *ppc = &mms->ppc[i];
416
+ DeviceState *ppcdev;
417
+ int port;
418
+ char *gpioname;
419
+
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
422
+ ppcdev = DEVICE(ppc);
423
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
426
+ MemoryRegion *mr;
427
+ char *portname;
428
+
429
+ if (!pinfo->devfn) {
430
+ continue;
431
+ }
432
+
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
434
+ portname = g_strdup_printf("port[%d]", port);
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
436
+ portname, &error_fatal);
437
+ g_free(portname);
438
+ }
439
+
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
441
+
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
444
+
445
+ if (!pinfo->devfn) {
446
+ continue;
447
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
449
+
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
452
+ qdev_get_gpio_in_named(ppcdev,
453
+ "cfg_nonsec",
454
+ port));
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
458
+ qdev_get_gpio_in_named(ppcdev,
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
102
--
538
2.16.2
103
2.20.1
539
104
540
105
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Add an entries the Blizzard device in MAINTAINERS.
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
5
Reviewed-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190412165416.7977-6-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/Makefile.objs | 2 +-
11
include/hw/devices.h | 7 -------
9
target/arm/helper.h | 4 ++
12
include/hw/display/blizzard.h | 22 ++++++++++++++++++++++
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
13
hw/arm/nseries.c | 1 +
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
14
hw/display/blizzard.c | 2 +-
12
4 files changed, 198 insertions(+), 1 deletion(-)
15
MAINTAINERS | 2 ++
13
create mode 100644 target/arm/vec_helper.c
16
5 files changed, 26 insertions(+), 8 deletions(-)
17
create mode 100644 include/hw/display/blizzard.h
14
18
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
19
diff --git a/include/hw/devices.h b/include/hw/devices.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
21
--- a/include/hw/devices.h
18
+++ b/target/arm/Makefile.objs
22
+++ b/include/hw/devices.h
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
23
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
24
/* stellaris_input.c */
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
25
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
22
obj-y += translate.o op_helper.o helper.o cpu.o
26
23
-obj-y += neon_helper.o iwmmxt_helper.o
27
-/* blizzard.c */
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
28
-void *s1d13745_init(qemu_irq gpio_int);
25
obj-y += gdbstub.o
29
-void s1d13745_write(void *opaque, int dc, uint16_t value);
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
30
-void s1d13745_write_block(void *opaque, int dc,
27
obj-y += crypto_helper.o
31
- void *buf, size_t len, int pitch);
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
32
-uint16_t s1d13745_read(void *opaque, int dc);
29
index XXXXXXX..XXXXXXX 100644
33
-
30
--- a/target/arm/helper.h
34
/* cbus.c */
31
+++ b/target/arm/helper.h
35
typedef struct {
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
36
qemu_irq clk;
33
37
diff --git a/include/hw/display/blizzard.h b/include/hw/display/blizzard.h
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
42
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
48
+++ b/target/arm/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
50
tcg_temp_free_ptr(fpst);
51
}
52
53
+/* AdvSIMD scalar three same extra
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
58
+ */
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
60
+ uint32_t insn)
61
+{
62
+ int rd = extract32(insn, 0, 5);
63
+ int rn = extract32(insn, 5, 5);
64
+ int opcode = extract32(insn, 11, 4);
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
72
+ switch (u * 16 + opcode) {
73
+ case 0x10: /* SQRDMLAH (vector) */
74
+ case 0x11: /* SQRDMLSH (vector) */
75
+ if (size != 1 && size != 2) {
76
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ feature = ARM_FEATURE_V8_RDM;
80
+ break;
81
+ default:
82
+ unallocated_encoding(s);
83
+ return;
84
+ }
85
+ if (!arm_dc_feature(s, feature)) {
86
+ unallocated_encoding(s);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
92
+
93
+ /* Do a single operation on the lowest element in the vector.
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
95
+ * with no side effects for all these operations.
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
114
+ break;
115
+ case 0x1: /* SQRDMLSH */
116
+ if (size == 1) {
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
118
+ } else {
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
135
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
148
new file mode 100644
38
new file mode 100644
149
index XXXXXXX..XXXXXXX
39
index XXXXXXX..XXXXXXX
150
--- /dev/null
40
--- /dev/null
151
+++ b/target/arm/vec_helper.c
41
+++ b/include/hw/display/blizzard.h
152
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
153
+/*
43
+/*
154
+ * ARM AdvSIMD / SVE Vector Operations
44
+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
155
+ *
45
+ *
156
+ * Copyright (c) 2018 Linaro
46
+ * Copyright (C) 2008 Nokia Corporation
47
+ * Written by Andrzej Zaborowski
157
+ *
48
+ *
158
+ * This library is free software; you can redistribute it and/or
49
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
159
+ * modify it under the terms of the GNU Lesser General Public
50
+ * See the COPYING file in the top-level directory.
160
+ * License as published by the Free Software Foundation; either
161
+ * version 2 of the License, or (at your option) any later version.
162
+ *
163
+ * This library is distributed in the hope that it will be useful,
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ * Lesser General Public License for more details.
167
+ *
168
+ * You should have received a copy of the GNU Lesser General Public
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
51
+ */
171
+
52
+
172
+#include "qemu/osdep.h"
53
+#ifndef HW_DISPLAY_BLIZZARD_H
173
+#include "cpu.h"
54
+#define HW_DISPLAY_BLIZZARD_H
174
+#include "exec/exec-all.h"
175
+#include "exec/helper-proto.h"
176
+#include "tcg/tcg-gvec-desc.h"
177
+
55
+
56
+#include "hw/irq.h"
178
+
57
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
58
+void *s1d13745_init(qemu_irq gpio_int);
59
+void s1d13745_write(void *opaque, int dc, uint16_t value);
60
+void s1d13745_write_block(void *opaque, int dc,
61
+ void *buf, size_t len, int pitch);
62
+uint16_t s1d13745_read(void *opaque, int dc);
180
+
63
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
64
+#endif
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
65
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
183
+ int16_t src2, int16_t src3)
66
index XXXXXXX..XXXXXXX 100644
184
+{
67
--- a/hw/arm/nseries.c
185
+ /* Simplify:
68
+++ b/hw/arm/nseries.c
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
69
@@ -XXX,XX +XXX,XX @@
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
70
#include "hw/boards.h"
188
+ */
71
#include "hw/i2c/i2c.h"
189
+ int32_t ret = (int32_t)src1 * src2;
72
#include "hw/devices.h"
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
73
+#include "hw/display/blizzard.h"
191
+ ret >>= 15;
74
#include "hw/misc/tmp105.h"
192
+ if (ret != (int16_t)ret) {
75
#include "hw/block/flash.h"
193
+ SET_QC();
76
#include "hw/hw.h"
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
77
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
195
+ }
78
index XXXXXXX..XXXXXXX 100644
196
+ return ret;
79
--- a/hw/display/blizzard.c
197
+}
80
+++ b/hw/display/blizzard.c
198
+
81
@@ -XXX,XX +XXX,XX @@
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
82
#include "qemu/osdep.h"
200
+ uint32_t src2, uint32_t src3)
83
#include "qemu-common.h"
201
+{
84
#include "ui/console.h"
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
85
-#include "hw/devices.h"
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
86
+#include "hw/display/blizzard.h"
204
+ return deposit32(e1, 16, 16, e2);
87
#include "ui/pixel_ops.h"
205
+}
88
206
+
89
typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
90
diff --git a/MAINTAINERS b/MAINTAINERS
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
91
index XXXXXXX..XXXXXXX 100644
209
+ int16_t src2, int16_t src3)
92
--- a/MAINTAINERS
210
+{
93
+++ b/MAINTAINERS
211
+ /* Similarly, using subtraction:
94
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
95
L: qemu-arm@nongnu.org
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
96
S: Odd Fixes
214
+ */
97
F: hw/arm/nseries.c
215
+ int32_t ret = (int32_t)src1 * src2;
98
+F: hw/display/blizzard.c
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
99
F: hw/input/lm832x.c
217
+ ret >>= 15;
100
F: hw/input/tsc2005.c
218
+ if (ret != (int16_t)ret) {
101
F: hw/misc/cbus.c
219
+ SET_QC();
102
F: hw/timer/twl92230.c
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
103
+F: include/hw/display/blizzard.h
221
+ }
104
222
+ return ret;
105
Palm
223
+}
106
M: Andrzej Zaborowski <balrogg@gmail.com>
224
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
226
+ uint32_t src2, uint32_t src3)
227
+{
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
230
+ return deposit32(e1, 16, 16, e2);
231
+}
232
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
235
+ int32_t src2, int32_t src3)
236
+{
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
238
+ int64_t ret = (int64_t)src1 * src2;
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
240
+ ret >>= 31;
241
+ if (ret != (int32_t)ret) {
242
+ SET_QC();
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
244
+ }
245
+ return ret;
246
+}
247
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
250
+ int32_t src2, int32_t src3)
251
+{
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
107
--
263
2.16.2
108
2.20.1
264
109
265
110
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
which is a small set of registers handling LEDs, buttons
3
and some counters.
4
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190412165416.7977-7-philmd@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
8
---
9
hw/misc/Makefile.objs | 1 +
9
include/hw/devices.h | 14 --------------
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
10
include/hw/misc/cbus.h | 32 ++++++++++++++++++++++++++++++++
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
11
hw/arm/nseries.c | 1 +
12
default-configs/arm-softmmu.mak | 1 +
12
hw/misc/cbus.c | 2 +-
13
hw/misc/trace-events | 6 ++
13
MAINTAINERS | 1 +
14
5 files changed, 227 insertions(+)
14
5 files changed, 35 insertions(+), 15 deletions(-)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
15
create mode 100644 include/hw/misc/cbus.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
16
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
19
--- a/include/hw/devices.h
21
+++ b/hw/misc/Makefile.objs
20
+++ b/include/hw/devices.h
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
21
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
22
/* stellaris_input.c */
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
23
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
24
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
25
-/* cbus.c */
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
26
-typedef struct {
28
27
- qemu_irq clk;
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
28
- qemu_irq dat;
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
29
- qemu_irq sel;
30
-} CBus;
31
-CBus *cbus_init(qemu_irq dat_out);
32
-void cbus_attach(CBus *bus, void *slave_opaque);
33
-
34
-void *retu_init(qemu_irq irq, int vilma);
35
-void *tahvo_init(qemu_irq irq, int betty);
36
-
37
-void retu_key_event(void *retu, int state);
38
-
39
#endif
40
diff --git a/include/hw/misc/cbus.h b/include/hw/misc/cbus.h
31
new file mode 100644
41
new file mode 100644
32
index XXXXXXX..XXXXXXX
42
index XXXXXXX..XXXXXXX
33
--- /dev/null
43
--- /dev/null
34
+++ b/include/hw/misc/mps2-fpgaio.h
44
+++ b/include/hw/misc/cbus.h
35
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@
36
+/*
46
+/*
37
+ * ARM MPS2 FPGAIO emulation
47
+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
48
+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
49
+ * Based on reverse-engineering of a linux driver.
38
+ *
50
+ *
39
+ * Copyright (c) 2018 Linaro Limited
51
+ * Copyright (C) 2008 Nokia Corporation
40
+ * Written by Peter Maydell
52
+ * Written by Andrzej Zaborowski
41
+ *
53
+ *
42
+ * This program is free software; you can redistribute it and/or modify
54
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
+ * it under the terms of the GNU General Public License version 2 or
55
+ * See the COPYING file in the top-level directory.
44
+ * (at your option) any later version.
45
+ */
56
+ */
46
+
57
+
47
+/* This is a model of the FPGAIO register block in the AN505
58
+#ifndef HW_MISC_CBUS_H
48
+ * FPGA image for the MPS2 dev board; it is documented in the
59
+#define HW_MISC_CBUS_H
49
+ * application note:
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
51
+ *
52
+ * QEMU interface:
53
+ * + sysbus MMIO region 0: the register bank
54
+ */
55
+
60
+
56
+#ifndef MPS2_FPGAIO_H
61
+#include "hw/irq.h"
57
+#define MPS2_FPGAIO_H
58
+
59
+#include "hw/sysbus.h"
60
+
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
62
+
64
+typedef struct {
63
+typedef struct {
65
+ /*< private >*/
64
+ qemu_irq clk;
66
+ SysBusDevice parent_obj;
65
+ qemu_irq dat;
66
+ qemu_irq sel;
67
+} CBus;
67
+
68
+
68
+ /*< public >*/
69
+CBus *cbus_init(qemu_irq dat_out);
69
+ MemoryRegion iomem;
70
+void cbus_attach(CBus *bus, void *slave_opaque);
70
+
71
+
71
+ uint32_t led0;
72
+void *retu_init(qemu_irq irq, int vilma);
72
+ uint32_t prescale;
73
+void *tahvo_init(qemu_irq irq, int betty);
73
+ uint32_t misc;
74
+
74
+
75
+ uint32_t prescale_clk;
75
+void retu_key_event(void *retu, int state);
76
+} MPS2FPGAIO;
77
+
76
+
78
+#endif
77
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
78
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
80
new file mode 100644
79
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX
80
--- a/hw/arm/nseries.c
82
--- /dev/null
81
+++ b/hw/arm/nseries.c
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
82
@@ -XXX,XX +XXX,XX @@
85
+/*
83
#include "hw/i2c/i2c.h"
86
+ * ARM MPS2 AN505 FPGAIO emulation
84
#include "hw/devices.h"
87
+ *
85
#include "hw/display/blizzard.h"
88
+ * Copyright (c) 2018 Linaro Limited
86
+#include "hw/misc/cbus.h"
89
+ * Written by Peter Maydell
87
#include "hw/misc/tmp105.h"
90
+ *
88
#include "hw/block/flash.h"
91
+ * This program is free software; you can redistribute it and/or modify
89
#include "hw/hw.h"
92
+ * it under the terms of the GNU General Public License version 2 or
90
diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
122
+ uint64_t r;
123
+
124
+ switch (offset) {
125
+ case A_LED0:
126
+ r = s->led0;
127
+ break;
128
+ case A_BUTTON:
129
+ /* User-pressable board buttons. We don't model that, so just return
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
148
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
153
+ }
154
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
156
+ return r;
157
+}
158
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
160
+ unsigned size)
161
+{
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
163
+
164
+ trace_mps2_fpgaio_write(offset, value, size);
165
+
166
+ switch (offset) {
167
+ case A_LED0:
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
169
+ * a mechanism for displaying this graphically, so use a trace event.
170
+ */
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
172
+ value & 0x01 ? '*' : '.');
173
+ s->led0 = value & 0x3;
174
+ break;
175
+ case A_PRESCALE:
176
+ s->prescale = value;
177
+ break;
178
+ case A_MISC:
179
+ /* These are control bits for some of the other devices on the
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
181
+ * make the bits read as written.
182
+ */
183
+ qemu_log_mask(LOG_UNIMP,
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
185
+ s->misc = value;
186
+ break;
187
+ default:
188
+ qemu_log_mask(LOG_GUEST_ERROR,
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
190
+ break;
191
+ }
192
+}
193
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
195
+ .read = mps2_fpgaio_read,
196
+ .write = mps2_fpgaio_write,
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
198
+};
199
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
201
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
203
+
204
+ trace_mps2_fpgaio_reset();
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
209
+
210
+static void mps2_fpgaio_init(Object *obj)
211
+{
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
231
+
232
+static Property mps2_fpgaio_properties[] = {
233
+ /* Frequency of the prescale counter */
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
235
+ DEFINE_PROP_END_OF_LIST(),
236
+};
237
+
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
92
--- a/hw/misc/cbus.c
264
+++ b/default-configs/arm-softmmu.mak
93
+++ b/hw/misc/cbus.c
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
94
@@ -XXX,XX +XXX,XX @@
266
CONFIG_CMSDK_APB_TIMER=y
95
#include "qemu/osdep.h"
267
CONFIG_CMSDK_APB_UART=y
96
#include "hw/hw.h"
268
97
#include "hw/irq.h"
269
+CONFIG_MPS2_FPGAIO=y
98
-#include "hw/devices.h"
270
CONFIG_MPS2_SCC=y
99
+#include "hw/misc/cbus.h"
271
100
#include "sysemu/sysemu.h"
272
CONFIG_VERSATILE_PCI=y
101
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
102
//#define DEBUG
103
diff --git a/MAINTAINERS b/MAINTAINERS
274
index XXXXXXX..XXXXXXX 100644
104
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
105
--- a/MAINTAINERS
276
+++ b/hw/misc/trace-events
106
+++ b/MAINTAINERS
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
107
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
108
F: hw/misc/cbus.c
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
109
F: hw/timer/twl92230.c
280
110
F: include/hw/display/blizzard.h
281
+# hw/misc/mps2_fpgaio.c
111
+F: include/hw/misc/cbus.h
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
112
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
113
Palm
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
114
M: Andrzej Zaborowski <balrogg@gmail.com>
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
115
--
291
2.16.2
116
2.20.1
292
117
293
118
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
collection of registers for controlling the PPCs and other bits of
3
glue in the system. This commit provides the initial skeleton of the
4
device, implementing just the ID registers, and a couple of read-only
5
read-as-zero registers.
6
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20190412165416.7977-8-philmd@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
10
---
7
---
11
hw/misc/Makefile.objs | 1 +
8
include/hw/devices.h | 3 ---
12
include/hw/misc/iotkit-secctl.h | 39 ++++
9
include/hw/input/gamepad.h | 19 +++++++++++++++++++
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
10
hw/arm/stellaris.c | 2 +-
14
default-configs/arm-softmmu.mak | 1 +
11
hw/input/stellaris_input.c | 2 +-
15
hw/misc/trace-events | 7 +
12
MAINTAINERS | 1 +
16
5 files changed, 496 insertions(+)
13
5 files changed, 22 insertions(+), 5 deletions(-)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
14
create mode 100644 include/hw/input/gamepad.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
15
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
18
--- a/include/hw/devices.h
23
+++ b/hw/misc/Makefile.objs
19
+++ b/include/hw/devices.h
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
20
@@ -XXX,XX +XXX,XX @@ void *tsc2005_init(qemu_irq pintdav);
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
21
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
26
22
void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
23
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
24
-/* stellaris_input.c */
29
25
-void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
26
-
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
27
#endif
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
28
diff --git a/include/hw/input/gamepad.h b/include/hw/input/gamepad.h
33
new file mode 100644
29
new file mode 100644
34
index XXXXXXX..XXXXXXX
30
index XXXXXXX..XXXXXXX
35
--- /dev/null
31
--- /dev/null
36
+++ b/include/hw/misc/iotkit-secctl.h
32
+++ b/include/hw/input/gamepad.h
37
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
38
+/*
34
+/*
39
+ * ARM IoT Kit security controller
35
+ * Gamepad style buttons connected to IRQ/GPIO lines
40
+ *
36
+ *
41
+ * Copyright (c) 2018 Linaro Limited
37
+ * Copyright (c) 2007 CodeSourcery.
42
+ * Written by Peter Maydell
38
+ * Written by Paul Brook
43
+ *
39
+ *
44
+ * This program is free software; you can redistribute it and/or modify
40
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
+ * it under the terms of the GNU General Public License version 2 or
41
+ * See the COPYING file in the top-level directory.
46
+ * (at your option) any later version.
47
+ */
42
+ */
48
+
43
+
49
+/* This is a model of the security controller which is part of the
44
+#ifndef HW_INPUT_GAMEPAD_H
50
+ * Arm IoT Kit and documented in
45
+#define HW_INPUT_GAMEPAD_H
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
52
+ *
53
+ * QEMU interface:
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
56
+ */
57
+
46
+
58
+#ifndef IOTKIT_SECCTL_H
47
+#include "hw/irq.h"
59
+#define IOTKIT_SECCTL_H
60
+
48
+
61
+#include "hw/sysbus.h"
49
+/* stellaris_input.c */
62
+
50
+void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
65
+
66
+typedef struct IoTKitSecCtl {
67
+ /*< private >*/
68
+ SysBusDevice parent_obj;
69
+
70
+ /*< public >*/
71
+
72
+ MemoryRegion s_regs;
73
+ MemoryRegion ns_regs;
74
+} IoTKitSecCtl;
75
+
51
+
76
+#endif
52
+#endif
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
53
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
78
new file mode 100644
54
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX
55
--- a/hw/arm/stellaris.c
80
--- /dev/null
56
+++ b/hw/arm/stellaris.c
81
+++ b/hw/misc/iotkit-secctl.c
82
@@ -XXX,XX +XXX,XX @@
57
@@ -XXX,XX +XXX,XX @@
83
+/*
58
#include "hw/sysbus.h"
84
+ * Arm IoT Kit security controller
59
#include "hw/ssi/ssi.h"
85
+ *
60
#include "hw/arm/arm.h"
86
+ * Copyright (c) 2018 Linaro Limited
61
-#include "hw/devices.h"
87
+ * Written by Peter Maydell
62
#include "qemu/timer.h"
88
+ *
63
#include "hw/i2c/i2c.h"
89
+ * This program is free software; you can redistribute it and/or modify
64
#include "net/net.h"
90
+ * it under the terms of the GNU General Public License version 2 or
65
@@ -XXX,XX +XXX,XX @@
91
+ * (at your option) any later version.
66
#include "sysemu/sysemu.h"
92
+ */
67
#include "hw/arm/armv7m.h"
93
+
68
#include "hw/char/pl011.h"
94
+#include "qemu/osdep.h"
69
+#include "hw/input/gamepad.h"
95
+#include "qemu/log.h"
70
#include "hw/watchdog/cmsdk-apb-watchdog.h"
96
+#include "qapi/error.h"
71
#include "hw/misc/unimp.h"
97
+#include "trace.h"
72
#include "cpu.h"
98
+#include "hw/sysbus.h"
73
diff --git a/hw/input/stellaris_input.c b/hw/input/stellaris_input.c
99
+#include "hw/registerfields.h"
100
+#include "hw/misc/iotkit-secctl.h"
101
+
102
+/* Registers in the secure privilege control block */
103
+REG32(SECRESPCFG, 0x10)
104
+REG32(NSCCFG, 0x14)
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
170
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
172
+ 0x04, 0x00, 0x00, 0x00,
173
+ 0x53, 0xb8, 0x0b, 0x00,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
175
+};
176
+
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
178
+ uint64_t *pdata,
179
+ unsigned size, MemTxAttrs attrs)
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
252
+
253
+ if (size != 4) {
254
+ /* None of our registers are access-sensitive, so just pull the right
255
+ * byte out of the word read result.
256
+ */
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
258
+ }
259
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
261
+ *pdata = r;
262
+ return MEMTX_OK;
263
+}
264
+
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
266
+ uint64_t value,
267
+ unsigned size, MemTxAttrs attrs)
268
+{
269
+ uint32_t offset = addr;
270
+
271
+ trace_iotkit_secctl_s_write(offset, value, size);
272
+
273
+ if (size != 4) {
274
+ /* Byte and halfword writes are ignored */
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
277
+ return MEMTX_OK;
278
+ }
279
+
280
+ switch (offset) {
281
+ case A_SECRESPCFG:
282
+ case A_NSCCFG:
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
342
+
343
+ return MEMTX_OK;
344
+}
345
+
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
347
+ uint64_t *pdata,
348
+ unsigned size, MemTxAttrs attrs)
349
+{
350
+ uint64_t r;
351
+ uint32_t offset = addr & ~0x3;
352
+
353
+ switch (offset) {
354
+ case A_AHBNSPPPC0:
355
+ r = 0;
356
+ break;
357
+ case A_AHBNSPPPCEXP0:
358
+ case A_AHBNSPPPCEXP1:
359
+ case A_AHBNSPPPCEXP2:
360
+ case A_AHBNSPPPCEXP3:
361
+ case A_APBNSPPPC0:
362
+ case A_APBNSPPPC1:
363
+ case A_APBNSPPPCEXP0:
364
+ case A_APBNSPPPCEXP1:
365
+ case A_APBNSPPPCEXP2:
366
+ case A_APBNSPPPCEXP3:
367
+ qemu_log_mask(LOG_UNIMP,
368
+ "IoTKit SecCtl NS block read: "
369
+ "unimplemented offset 0x%x\n", offset);
370
+ break;
371
+ case A_PID4:
372
+ case A_PID5:
373
+ case A_PID6:
374
+ case A_PID7:
375
+ case A_PID0:
376
+ case A_PID1:
377
+ case A_PID2:
378
+ case A_PID3:
379
+ case A_CID0:
380
+ case A_CID1:
381
+ case A_CID2:
382
+ case A_CID3:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
384
+ break;
385
+ default:
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
388
+ offset);
389
+ r = 0;
390
+ break;
391
+ }
392
+
393
+ if (size != 4) {
394
+ /* None of our registers are access-sensitive, so just pull the right
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
75
--- a/hw/input/stellaris_input.c
534
+++ b/default-configs/arm-softmmu.mak
76
+++ b/hw/input/stellaris_input.c
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
77
@@ -XXX,XX +XXX,XX @@
536
CONFIG_MPS2_SCC=y
78
*/
537
79
#include "qemu/osdep.h"
538
CONFIG_TZ_PPC=y
80
#include "hw/hw.h"
539
+CONFIG_IOTKIT_SECCTL=y
81
-#include "hw/devices.h"
540
82
+#include "hw/input/gamepad.h"
541
CONFIG_VERSATILE_PCI=y
83
#include "ui/console.h"
542
CONFIG_VERSATILE_I2C=y
84
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
85
typedef struct {
86
diff --git a/MAINTAINERS b/MAINTAINERS
544
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
88
--- a/MAINTAINERS
546
+++ b/hw/misc/trace-events
89
+++ b/MAINTAINERS
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
90
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
91
L: qemu-arm@nongnu.org
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
92
S: Maintained
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
93
F: hw/*/stellaris*
551
+
94
+F: include/hw/input/gamepad.h
552
+# hw/misc/iotkit-secctl.c
95
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
96
Versatile Express
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
97
M: Peter Maydell <peter.maydell@linaro.org>
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
98
--
559
2.16.2
99
2.20.1
560
100
561
101
diff view generated by jsdifflib
New patch
1
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
3
Since uWireSlave is only used in this new header, there is no
4
need to expose it via "qemu/typedefs.h".
5
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190412165416.7977-9-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/omap.h | 6 +-----
12
include/hw/devices.h | 15 ---------------
13
include/hw/input/tsc2xxx.h | 36 ++++++++++++++++++++++++++++++++++++
14
include/qemu/typedefs.h | 1 -
15
hw/arm/nseries.c | 2 +-
16
hw/arm/palm.c | 2 +-
17
hw/input/tsc2005.c | 2 +-
18
hw/input/tsc210x.c | 4 ++--
19
MAINTAINERS | 2 ++
20
9 files changed, 44 insertions(+), 26 deletions(-)
21
create mode 100644 include/hw/input/tsc2xxx.h
22
23
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/omap.h
26
+++ b/include/hw/arm/omap.h
27
@@ -XXX,XX +XXX,XX @@
28
#include "exec/memory.h"
29
# define hw_omap_h        "omap.h"
30
#include "hw/irq.h"
31
+#include "hw/input/tsc2xxx.h"
32
#include "target/arm/cpu-qom.h"
33
#include "qemu/log.h"
34
35
@@ -XXX,XX +XXX,XX @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
36
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
37
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
38
39
-struct uWireSlave {
40
- uint16_t (*receive)(void *opaque);
41
- void (*send)(void *opaque, uint16_t data);
42
- void *opaque;
43
-};
44
struct omap_uwire_s;
45
void omap_uwire_attach(struct omap_uwire_s *s,
46
uWireSlave *slave, int chipselect);
47
diff --git a/include/hw/devices.h b/include/hw/devices.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/devices.h
50
+++ b/include/hw/devices.h
51
@@ -XXX,XX +XXX,XX @@
52
/* Devices that have nowhere better to go. */
53
54
#include "hw/hw.h"
55
-#include "ui/console.h"
56
57
/* smc91c111.c */
58
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
59
@@ -XXX,XX +XXX,XX @@ void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
60
/* lan9118.c */
61
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
62
63
-/* tsc210x.c */
64
-uWireSlave *tsc2102_init(qemu_irq pint);
65
-uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
66
-I2SCodec *tsc210x_codec(uWireSlave *chip);
67
-uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
68
-void tsc210x_set_transform(uWireSlave *chip,
69
- MouseTransformInfo *info);
70
-void tsc210x_key_event(uWireSlave *chip, int key, int down);
71
-
72
-/* tsc2005.c */
73
-void *tsc2005_init(qemu_irq pintdav);
74
-uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
75
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
76
-
77
#endif
78
diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h
79
new file mode 100644
80
index XXXXXXX..XXXXXXX
81
--- /dev/null
82
+++ b/include/hw/input/tsc2xxx.h
83
@@ -XXX,XX +XXX,XX @@
84
+/*
85
+ * TI touchscreen controller
86
+ *
87
+ * Copyright (c) 2006 Andrzej Zaborowski
88
+ * Copyright (C) 2008 Nokia Corporation
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+#ifndef HW_INPUT_TSC2XXX_H
95
+#define HW_INPUT_TSC2XXX_H
96
+
97
+#include "hw/irq.h"
98
+#include "ui/console.h"
99
+
100
+typedef struct uWireSlave {
101
+ uint16_t (*receive)(void *opaque);
102
+ void (*send)(void *opaque, uint16_t data);
103
+ void *opaque;
104
+} uWireSlave;
105
+
106
+/* tsc210x.c */
107
+uWireSlave *tsc2102_init(qemu_irq pint);
108
+uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
109
+I2SCodec *tsc210x_codec(uWireSlave *chip);
110
+uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
111
+void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
112
+void tsc210x_key_event(uWireSlave *chip, int key, int down);
113
+
114
+/* tsc2005.c */
115
+void *tsc2005_init(qemu_irq pintdav);
116
+uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
117
+void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
118
+
119
+#endif
120
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
121
index XXXXXXX..XXXXXXX 100644
122
--- a/include/qemu/typedefs.h
123
+++ b/include/qemu/typedefs.h
124
@@ -XXX,XX +XXX,XX @@ typedef struct RAMBlock RAMBlock;
125
typedef struct Range Range;
126
typedef struct SHPCDevice SHPCDevice;
127
typedef struct SSIBus SSIBus;
128
-typedef struct uWireSlave uWireSlave;
129
typedef struct VirtIODevice VirtIODevice;
130
typedef struct Visitor Visitor;
131
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
132
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/nseries.c
135
+++ b/hw/arm/nseries.c
136
@@ -XXX,XX +XXX,XX @@
137
#include "ui/console.h"
138
#include "hw/boards.h"
139
#include "hw/i2c/i2c.h"
140
-#include "hw/devices.h"
141
#include "hw/display/blizzard.h"
142
+#include "hw/input/tsc2xxx.h"
143
#include "hw/misc/cbus.h"
144
#include "hw/misc/tmp105.h"
145
#include "hw/block/flash.h"
146
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/palm.c
149
+++ b/hw/arm/palm.c
150
@@ -XXX,XX +XXX,XX @@
151
#include "hw/arm/omap.h"
152
#include "hw/boards.h"
153
#include "hw/arm/arm.h"
154
-#include "hw/devices.h"
155
+#include "hw/input/tsc2xxx.h"
156
#include "hw/loader.h"
157
#include "exec/address-spaces.h"
158
#include "cpu.h"
159
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/input/tsc2005.c
162
+++ b/hw/input/tsc2005.c
163
@@ -XXX,XX +XXX,XX @@
164
#include "hw/hw.h"
165
#include "qemu/timer.h"
166
#include "ui/console.h"
167
-#include "hw/devices.h"
168
+#include "hw/input/tsc2xxx.h"
169
#include "trace.h"
170
171
#define TSC_CUT_RESOLUTION(value, p)    ((value) >> (16 - (p ? 12 : 10)))
172
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/hw/input/tsc210x.c
175
+++ b/hw/input/tsc210x.c
176
@@ -XXX,XX +XXX,XX @@
177
#include "audio/audio.h"
178
#include "qemu/timer.h"
179
#include "ui/console.h"
180
-#include "hw/arm/omap.h"    /* For I2SCodec and uWireSlave */
181
-#include "hw/devices.h"
182
+#include "hw/arm/omap.h" /* For I2SCodec */
183
+#include "hw/input/tsc2xxx.h"
184
185
#define TSC_DATA_REGISTERS_PAGE        0x0
186
#define TSC_CONTROL_REGISTERS_PAGE    0x1
187
diff --git a/MAINTAINERS b/MAINTAINERS
188
index XXXXXXX..XXXXXXX 100644
189
--- a/MAINTAINERS
190
+++ b/MAINTAINERS
191
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
192
F: hw/misc/cbus.c
193
F: hw/timer/twl92230.c
194
F: include/hw/display/blizzard.h
195
+F: include/hw/input/tsc2xxx.h
196
F: include/hw/misc/cbus.h
197
198
Palm
199
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
200
S: Odd Fixes
201
F: hw/arm/palm.c
202
F: hw/input/tsc210x.c
203
+F: include/hw/input/tsc2xxx.h
204
205
Raspberry Pi
206
M: Peter Maydell <peter.maydell@linaro.org>
207
--
208
2.20.1
209
210
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
so that one input can feed multiple outputs. We currently have
3
qemu_irq_split() for this, but that has several deficiencies:
4
* it can only handle splitting a line into two
5
* it unavoidably leaks memory, so it can't be used
6
in a device that can be deleted
7
2
8
Implement a qdev device that encapsulates splitting of IRQs, with a
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
9
configurable number of outputs. (This is in some ways the inverse of
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
the TYPE_OR_IRQ device.)
5
Message-id: 20190412165416.7977-10-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
include/hw/devices.h | 3 ---
9
include/hw/net/lan9118.h | 19 +++++++++++++++++++
10
hw/arm/kzm.c | 2 +-
11
hw/arm/mps2.c | 2 +-
12
hw/arm/realview.c | 1 +
13
hw/arm/vexpress.c | 2 +-
14
hw/net/lan9118.c | 2 +-
15
7 files changed, 24 insertions(+), 7 deletions(-)
16
create mode 100644 include/hw/net/lan9118.h
11
17
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
diff --git a/include/hw/devices.h b/include/hw/devices.h
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
15
---
16
hw/core/Makefile.objs | 1 +
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
18
include/hw/irq.h | 4 +-
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
20
4 files changed, 150 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/core/split-irq.h
22
create mode 100644 hw/core/split-irq.c
23
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/Makefile.objs
20
--- a/include/hw/devices.h
27
+++ b/hw/core/Makefile.objs
21
+++ b/include/hw/devices.h
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
22
@@ -XXX,XX +XXX,XX @@
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
23
/* smc91c111.c */
30
common-obj-$(CONFIG_SOFTMMU) += register.o
24
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
25
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
26
-/* lan9118.c */
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
27
-void lan9118_init(NICInfo *, uint32_t, qemu_irq);
34
28
-
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
29
#endif
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
30
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
37
new file mode 100644
31
new file mode 100644
38
index XXXXXXX..XXXXXXX
32
index XXXXXXX..XXXXXXX
39
--- /dev/null
33
--- /dev/null
40
+++ b/include/hw/core/split-irq.h
34
+++ b/include/hw/net/lan9118.h
41
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
42
+/*
36
+/*
43
+ * IRQ splitter device.
37
+ * SMSC LAN9118 Ethernet interface emulation
44
+ *
38
+ *
45
+ * Copyright (c) 2018 Linaro Limited.
39
+ * Copyright (c) 2009 CodeSourcery, LLC.
46
+ * Written by Peter Maydell
40
+ * Written by Paul Brook
47
+ *
41
+ *
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
49
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * See the COPYING file in the top-level directory.
50
+ * in the Software without restriction, including without limitation the rights
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ * copies of the Software, and to permit persons to whom the Software is
53
+ * furnished to do so, subject to the following conditions:
54
+ *
55
+ * The above copyright notice and this permission notice shall be included in
56
+ * all copies or substantial portions of the Software.
57
+ *
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64
+ * THE SOFTWARE.
65
+ */
44
+ */
66
+
45
+
67
+/* This is a simple device which has one GPIO input line and multiple
46
+#ifndef HW_NET_LAN9118_H
68
+ * GPIO output lines. Any change on the input line is forwarded to all
47
+#define HW_NET_LAN9118_H
69
+ * of the outputs.
70
+ *
71
+ * QEMU interface:
72
+ * + one unnamed GPIO input: the input line
73
+ * + N unnamed GPIO outputs: the output lines
74
+ * + QOM property "num-lines": sets the number of output lines
75
+ */
76
+#ifndef HW_SPLIT_IRQ_H
77
+#define HW_SPLIT_IRQ_H
78
+
48
+
79
+#include "hw/irq.h"
49
+#include "hw/irq.h"
80
+#include "hw/sysbus.h"
50
+#include "net/net.h"
81
+#include "qom/object.h"
82
+
51
+
83
+#define TYPE_SPLIT_IRQ "split-irq"
52
+void lan9118_init(NICInfo *, uint32_t, qemu_irq);
84
+
85
+#define MAX_SPLIT_LINES 16
86
+
87
+typedef struct SplitIRQ SplitIRQ;
88
+
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
90
+
91
+struct SplitIRQ {
92
+ DeviceState parent_obj;
93
+
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
95
+ uint16_t num_lines;
96
+};
97
+
53
+
98
+#endif
54
+#endif
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
55
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
100
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
101
--- a/include/hw/irq.h
57
--- a/hw/arm/kzm.c
102
+++ b/include/hw/irq.h
58
+++ b/hw/arm/kzm.c
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
104
/* Returns a new IRQ with opposite polarity. */
105
qemu_irq qemu_irq_invert(qemu_irq irq);
106
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
110
+ */
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
112
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
115
new file mode 100644
116
index XXXXXXX..XXXXXXX
117
--- /dev/null
118
+++ b/hw/core/split-irq.c
119
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
120
+/*
60
#include "qemu/error-report.h"
121
+ * IRQ splitter device.
61
#include "exec/address-spaces.h"
122
+ *
62
#include "net/net.h"
123
+ * Copyright (c) 2018 Linaro Limited.
63
-#include "hw/devices.h"
124
+ * Written by Peter Maydell
64
+#include "hw/net/lan9118.h"
125
+ *
65
#include "hw/char/serial.h"
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
66
#include "sysemu/qtest.h"
127
+ * of this software and associated documentation files (the "Software"), to deal
67
128
+ * in the Software without restriction, including without limitation the rights
68
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69
index XXXXXXX..XXXXXXX 100644
130
+ * copies of the Software, and to permit persons to whom the Software is
70
--- a/hw/arm/mps2.c
131
+ * furnished to do so, subject to the following conditions:
71
+++ b/hw/arm/mps2.c
132
+ *
72
@@ -XXX,XX +XXX,XX @@
133
+ * The above copyright notice and this permission notice shall be included in
73
#include "hw/timer/cmsdk-apb-timer.h"
134
+ * all copies or substantial portions of the Software.
74
#include "hw/timer/cmsdk-apb-dualtimer.h"
135
+ *
75
#include "hw/misc/mps2-scc.h"
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76
-#include "hw/devices.h"
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77
+#include "hw/net/lan9118.h"
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
78
#include "net/net.h"
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80
typedef enum MPS2FPGAType {
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
142
+ * THE SOFTWARE.
82
index XXXXXXX..XXXXXXX 100644
143
+ */
83
--- a/hw/arm/realview.c
144
+
84
+++ b/hw/arm/realview.c
145
+#include "qemu/osdep.h"
85
@@ -XXX,XX +XXX,XX @@
146
+#include "hw/core/split-irq.h"
86
#include "hw/arm/arm.h"
147
+#include "qapi/error.h"
87
#include "hw/arm/primecell.h"
148
+
88
#include "hw/devices.h"
149
+static void split_irq_handler(void *opaque, int n, int level)
89
+#include "hw/net/lan9118.h"
150
+{
90
#include "hw/pci/pci.h"
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
91
#include "net/net.h"
152
+ int i;
92
#include "sysemu/sysemu.h"
153
+
93
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
154
+ for (i = 0; i < s->num_lines; i++) {
94
index XXXXXXX..XXXXXXX 100644
155
+ qemu_set_irq(s->out_irq[i], level);
95
--- a/hw/arm/vexpress.c
156
+ }
96
+++ b/hw/arm/vexpress.c
157
+}
97
@@ -XXX,XX +XXX,XX @@
158
+
98
#include "hw/sysbus.h"
159
+static void split_irq_init(Object *obj)
99
#include "hw/arm/arm.h"
160
+{
100
#include "hw/arm/primecell.h"
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
101
-#include "hw/devices.h"
162
+}
102
+#include "hw/net/lan9118.h"
163
+
103
#include "hw/i2c/i2c.h"
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
104
#include "net/net.h"
165
+{
105
#include "sysemu/sysemu.h"
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
106
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
167
+
107
index XXXXXXX..XXXXXXX 100644
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
108
--- a/hw/net/lan9118.c
169
+ error_setg(errp,
109
+++ b/hw/net/lan9118.c
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
110
@@ -XXX,XX +XXX,XX @@
171
+ s->num_lines, MAX_SPLIT_LINES);
111
#include "hw/sysbus.h"
172
+ return;
112
#include "net/net.h"
173
+ }
113
#include "net/eth.h"
174
+
114
-#include "hw/devices.h"
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
115
+#include "hw/net/lan9118.h"
176
+}
116
#include "sysemu/sysemu.h"
177
+
117
#include "hw/ptimer.h"
178
+static Property split_irq_properties[] = {
118
#include "qemu/log.h"
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
180
+ DEFINE_PROP_END_OF_LIST(),
181
+};
182
+
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
184
+{
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
186
+
187
+ /* No state to reset or migrate */
188
+ dc->props = split_irq_properties;
189
+ dc->realize = split_irq_realize;
190
+
191
+ /* Reason: Needs to be wired up to work */
192
+ dc->user_creatable = false;
193
+}
194
+
195
+static const TypeInfo split_irq_type_info = {
196
+ .name = TYPE_SPLIT_IRQ,
197
+ .parent = TYPE_DEVICE,
198
+ .instance_size = sizeof(SplitIRQ),
199
+ .instance_init = split_irq_init,
200
+ .class_init = split_irq_class_init,
201
+};
202
+
203
+static void split_irq_register_types(void)
204
+{
205
+ type_register_static(&split_irq_type_info);
206
+}
207
+
208
+type_init(split_irq_register_types)
209
--
119
--
210
2.16.2
120
2.20.1
211
121
212
122
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
multiple inclusion, which means compilation fails if it gets
3
included twice. Fix the omission.
4
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190412165416.7977-11-philmd@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
8
---
10
include/hw/or-irq.h | 5 +++++
9
include/hw/net/ne2000-isa.h | 6 ++++++
11
1 file changed, 5 insertions(+)
10
1 file changed, 6 insertions(+)
12
11
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
12
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
14
--- a/include/hw/net/ne2000-isa.h
16
+++ b/include/hw/or-irq.h
15
+++ b/include/hw/net/ne2000-isa.h
17
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
18
* THE SOFTWARE.
17
* This work is licensed under the terms of the GNU GPL, version 2 or later.
18
* See the COPYING file in the top-level directory.
19
*/
19
*/
20
21
+#ifndef HW_OR_IRQ_H
22
+#define HW_OR_IRQ_H
23
+
20
+
24
#include "hw/irq.h"
21
+#ifndef HW_NET_NE2K_ISA_H
25
#include "hw/sysbus.h"
22
+#define HW_NET_NE2K_ISA_H
26
#include "qom/object.h"
23
+
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
24
#include "hw/hw.h"
28
bool levels[MAX_OR_LINES];
25
#include "hw/qdev.h"
29
uint16_t num_lines;
26
#include "hw/isa/isa.h"
30
};
27
@@ -XXX,XX +XXX,XX @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
28
}
29
return d;
30
}
31
+
31
+
32
+#endif
32
+#endif
33
--
33
--
34
2.16.2
34
2.20.1
35
35
36
36
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Include the U bit in the switches rather than testing separately.
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190412165416.7977-12-philmd@redhat.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
7
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
8
include/hw/net/lan9118.h | 2 ++
11
1 file changed, 61 insertions(+), 68 deletions(-)
9
hw/arm/exynos4_boards.c | 3 ++-
10
hw/arm/mps2-tz.c | 3 ++-
11
hw/net/lan9118.c | 1 -
12
4 files changed, 6 insertions(+), 3 deletions(-)
12
13
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
--- a/include/hw/net/lan9118.h
16
+++ b/target/arm/translate-a64.c
17
+++ b/include/hw/net/lan9118.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@
18
int index;
19
#include "hw/irq.h"
19
TCGv_ptr fpst;
20
#include "net/net.h"
20
21
21
- switch (opcode) {
22
+#define TYPE_LAN9118 "lan9118"
22
- case 0x0: /* MLA */
23
+
23
- case 0x4: /* MLS */
24
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
24
- if (!u || is_scalar) {
25
25
+ switch (16 * u + opcode) {
26
#endif
26
+ case 0x08: /* MUL */
27
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
27
+ case 0x10: /* MLA */
28
index XXXXXXX..XXXXXXX 100644
28
+ case 0x14: /* MLS */
29
--- a/hw/arm/exynos4_boards.c
29
+ if (is_scalar) {
30
+++ b/hw/arm/exynos4_boards.c
30
unallocated_encoding(s);
31
@@ -XXX,XX +XXX,XX @@
31
return;
32
#include "hw/arm/arm.h"
32
}
33
#include "exec/address-spaces.h"
33
break;
34
#include "hw/arm/exynos4210.h"
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
35
+#include "hw/net/lan9118.h"
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
36
#include "hw/boards.h"
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
37
37
+ case 0x02: /* SMLAL, SMLAL2 */
38
#undef DEBUG
38
+ case 0x12: /* UMLAL, UMLAL2 */
39
@@ -XXX,XX +XXX,XX @@ static void lan9215_init(uint32_t base, qemu_irq irq)
39
+ case 0x06: /* SMLSL, SMLSL2 */
40
/* This should be a 9215 but the 9118 is close enough */
40
+ case 0x16: /* UMLSL, UMLSL2 */
41
if (nd_table[0].used) {
41
+ case 0x0a: /* SMULL, SMULL2 */
42
qemu_check_nic_model(&nd_table[0], "lan9118");
42
+ case 0x1a: /* UMULL, UMULL2 */
43
- dev = qdev_create(NULL, "lan9118");
43
if (is_scalar) {
44
+ dev = qdev_create(NULL, TYPE_LAN9118);
44
unallocated_encoding(s);
45
qdev_set_nic_properties(dev, &nd_table[0]);
45
return;
46
qdev_prop_set_uint32(dev, "mode_16bit", 1);
46
}
47
qdev_init_nofail(dev);
47
is_long = true;
48
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
48
break;
49
index XXXXXXX..XXXXXXX 100644
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
50
--- a/hw/arm/mps2-tz.c
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
51
+++ b/hw/arm/mps2-tz.c
51
- case 0xb: /* SQDMULL, SQDMULL2 */
52
@@ -XXX,XX +XXX,XX @@
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
53
#include "hw/arm/armsse.h"
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
54
#include "hw/dma/pl080.h"
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
55
#include "hw/ssi/pl022.h"
55
is_long = true;
56
+#include "hw/net/lan9118.h"
56
- /* fall through */
57
#include "net/net.h"
57
- case 0xc: /* SQDMULH */
58
#include "hw/core/split-irq.h"
58
- case 0xd: /* SQRDMULH */
59
59
- if (u) {
60
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
60
- unallocated_encoding(s);
61
* except that it doesn't support the checksum-offload feature.
61
- return;
62
*/
62
- }
63
qemu_check_nic_model(nd, "lan9118");
63
break;
64
- mms->lan9118 = qdev_create(NULL, "lan9118");
64
- case 0x8: /* MUL */
65
+ mms->lan9118 = qdev_create(NULL, TYPE_LAN9118);
65
- if (u || is_scalar) {
66
qdev_set_nic_properties(mms->lan9118, nd);
66
- unallocated_encoding(s);
67
qdev_init_nofail(mms->lan9118);
67
- return;
68
68
- }
69
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
69
+ case 0x0c: /* SQDMULH */
70
index XXXXXXX..XXXXXXX 100644
70
+ case 0x0d: /* SQRDMULH */
71
--- a/hw/net/lan9118.c
71
break;
72
+++ b/hw/net/lan9118.c
72
- case 0x1: /* FMLA */
73
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_packet = {
73
- case 0x5: /* FMLS */
74
}
74
- if (u) {
75
};
75
- unallocated_encoding(s);
76
76
- return;
77
-#define TYPE_LAN9118 "lan9118"
77
- }
78
#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
78
- /* fall through */
79
79
- case 0x9: /* FMUL, FMULX */
80
typedef struct {
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
136
- case 0x5: /* FMLS */
137
- case 0x1: /* FMLA */
138
+ case 0x05: /* FMLS */
139
+ case 0x01: /* FMLA */
140
read_vec_element_i32(s, tcg_res, rd, pass,
141
is_scalar ? size : MO_32);
142
switch (size) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
144
g_assert_not_reached();
145
}
146
break;
147
- case 0x9: /* FMUL, FMULX */
148
+ case 0x09: /* FMUL */
149
switch (size) {
150
case 1:
151
- if (u) {
152
- if (is_scalar) {
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
154
- tcg_idx, fpst);
155
- } else {
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
157
- tcg_idx, fpst);
158
- }
159
+ if (is_scalar) {
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
161
+ tcg_idx, fpst);
162
} else {
163
- if (is_scalar) {
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
165
- tcg_idx, fpst);
166
- } else {
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
185
break;
186
- case 0xc: /* SQDMULH */
187
+ case 0x19: /* FMULX */
188
+ switch (size) {
189
+ case 1:
190
+ if (is_scalar) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
192
+ tcg_idx, fpst);
193
+ } else {
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
195
+ tcg_idx, fpst);
196
+ }
197
+ break;
198
+ case 2:
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
200
+ break;
201
+ default:
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
212
break;
213
- case 0xd: /* SQRDMULH */
214
+ case 0x0d: /* SQRDMULH */
215
if (size == 1) {
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
217
tcg_op, tcg_idx);
218
--
81
--
219
2.16.2
82
2.20.1
220
83
221
84
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Initial commit of the ZynqMP RTC device.
3
This commit finally deletes "hw/devices.h".
4
4
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190412165416.7977-13-philmd@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
---
9
hw/timer/Makefile.objs | 1 +
10
include/hw/devices.h | 11 -----------
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
11
include/hw/net/smc91c111.h | 19 +++++++++++++++++++
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
12
hw/arm/gumstix.c | 2 +-
12
3 files changed, 299 insertions(+)
13
hw/arm/integratorcp.c | 2 +-
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
14
hw/arm/mainstone.c | 2 +-
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
15
hw/arm/realview.c | 2 +-
16
hw/arm/versatilepb.c | 2 +-
17
hw/net/smc91c111.c | 2 +-
18
8 files changed, 25 insertions(+), 17 deletions(-)
19
delete mode 100644 include/hw/devices.h
20
create mode 100644 include/hw/net/smc91c111.h
15
21
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
22
diff --git a/include/hw/devices.h b/include/hw/devices.h
17
index XXXXXXX..XXXXXXX 100644
23
deleted file mode 100644
18
--- a/hw/timer/Makefile.objs
24
index XXXXXXX..XXXXXXX
19
+++ b/hw/timer/Makefile.objs
25
--- a/include/hw/devices.h
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
26
+++ /dev/null
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
27
@@ -XXX,XX +XXX,XX @@
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
28
-#ifndef QEMU_DEVICES_H
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
29
-#define QEMU_DEVICES_H
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
30
-
25
31
-/* Devices that have nowhere better to go. */
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
32
-
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
33
-#include "hw/hw.h"
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
34
-
35
-/* smc91c111.c */
36
-void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
37
-
38
-#endif
39
diff --git a/include/hw/net/smc91c111.h b/include/hw/net/smc91c111.h
29
new file mode 100644
40
new file mode 100644
30
index XXXXXXX..XXXXXXX
41
index XXXXXXX..XXXXXXX
31
--- /dev/null
42
--- /dev/null
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
43
+++ b/include/hw/net/smc91c111.h
33
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
34
+/*
45
+/*
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
46
+ * SMSC 91C111 Ethernet interface emulation
36
+ *
47
+ *
37
+ * Copyright (c) 2017 Xilinx Inc.
48
+ * Copyright (c) 2005 CodeSourcery, LLC.
49
+ * Written by Paul Brook
38
+ *
50
+ *
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
40
+ *
52
+ * See the COPYING file in the top-level directory.
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * in the Software without restriction, including without limitation the rights
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * furnished to do so, subject to the following conditions:
47
+ *
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
53
+ */
59
+
54
+
60
+#include "hw/register.h"
55
+#ifndef HW_NET_SMC91C111_H
56
+#define HW_NET_SMC91C111_H
61
+
57
+
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
58
+#include "hw/irq.h"
59
+#include "net/net.h"
63
+
60
+
64
+#define XLNX_ZYNQMP_RTC(obj) \
61
+void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
66
+
62
+
67
+REG32(SET_TIME_WRITE, 0x0)
63
+#endif
68
+REG32(SET_TIME_READ, 0x4)
64
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
69
+REG32(CALIB_WRITE, 0x8)
65
index XXXXXXX..XXXXXXX 100644
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
66
--- a/hw/arm/gumstix.c
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
67
+++ b/hw/arm/gumstix.c
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
73
+REG32(CALIB_READ, 0xc)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
77
+REG32(CURRENT_TIME, 0x10)
78
+REG32(CURRENT_TICK, 0x14)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
80
+REG32(ALARM, 0x18)
81
+REG32(RTC_INT_STATUS, 0x20)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
87
+REG32(RTC_INT_EN, 0x28)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
101
+REG32(CONTROL, 0x40)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
105
+REG32(SAFETY_CHK, 0x50)
106
+
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxZynqMPRTC {
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion iomem;
112
+ qemu_irq irq_rtc_int;
113
+ qemu_irq irq_addr_error_int;
114
+
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
117
+} XlnxZynqMPRTC;
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
123
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@
124
+/*
69
#include "hw/arm/pxa.h"
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
70
#include "net/net.h"
126
+ *
71
#include "hw/block/flash.h"
127
+ * Copyright (c) 2017 Xilinx Inc.
72
-#include "hw/devices.h"
128
+ *
73
+#include "hw/net/smc91c111.h"
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
74
#include "hw/boards.h"
130
+ *
75
#include "exec/address-spaces.h"
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
#include "sysemu/qtest.h"
132
+ * of this software and associated documentation files (the "Software"), to deal
77
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
133
+ * in the Software without restriction, including without limitation the rights
78
index XXXXXXX..XXXXXXX 100644
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
--- a/hw/arm/integratorcp.c
135
+ * copies of the Software, and to permit persons to whom the Software is
80
+++ b/hw/arm/integratorcp.c
136
+ * furnished to do so, subject to the following conditions:
81
@@ -XXX,XX +XXX,XX @@
137
+ *
82
#include "qemu-common.h"
138
+ * The above copyright notice and this permission notice shall be included in
83
#include "cpu.h"
139
+ * all copies or substantial portions of the Software.
84
#include "hw/sysbus.h"
140
+ *
85
-#include "hw/devices.h"
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
#include "hw/boards.h"
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
#include "hw/arm/arm.h"
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
#include "hw/misc/arm_integrator_debug.h"
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+#include "hw/net/smc91c111.h"
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
#include "net/net.h"
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
#include "exec/address-spaces.h"
147
+ * THE SOFTWARE.
92
#include "sysemu/sysemu.h"
148
+ */
93
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
149
+
94
index XXXXXXX..XXXXXXX 100644
150
+#include "qemu/osdep.h"
95
--- a/hw/arm/mainstone.c
151
+#include "hw/sysbus.h"
96
+++ b/hw/arm/mainstone.c
152
+#include "hw/register.h"
97
@@ -XXX,XX +XXX,XX @@
153
+#include "qemu/bitops.h"
98
#include "hw/arm/pxa.h"
154
+#include "qemu/log.h"
99
#include "hw/arm/arm.h"
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
100
#include "net/net.h"
156
+
101
-#include "hw/devices.h"
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
102
+#include "hw/net/smc91c111.h"
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
103
#include "hw/boards.h"
159
+#endif
104
#include "hw/block/flash.h"
160
+
105
#include "hw/sysbus.h"
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
106
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
162
+{
107
index XXXXXXX..XXXXXXX 100644
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
108
--- a/hw/arm/realview.c
164
+ qemu_set_irq(s->irq_rtc_int, pending);
109
+++ b/hw/arm/realview.c
165
+}
110
@@ -XXX,XX +XXX,XX @@
166
+
111
#include "hw/sysbus.h"
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
112
#include "hw/arm/arm.h"
168
+{
113
#include "hw/arm/primecell.h"
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
114
-#include "hw/devices.h"
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
115
#include "hw/net/lan9118.h"
171
+}
116
+#include "hw/net/smc91c111.h"
172
+
117
#include "hw/pci/pci.h"
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
118
#include "net/net.h"
174
+{
119
#include "sysemu/sysemu.h"
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
120
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
176
+ rtc_int_update_irq(s);
121
index XXXXXXX..XXXXXXX 100644
177
+}
122
--- a/hw/arm/versatilepb.c
178
+
123
+++ b/hw/arm/versatilepb.c
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
124
@@ -XXX,XX +XXX,XX @@
180
+{
125
#include "cpu.h"
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
126
#include "hw/sysbus.h"
182
+
127
#include "hw/arm/arm.h"
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
128
-#include "hw/devices.h"
184
+ rtc_int_update_irq(s);
129
+#include "hw/net/smc91c111.h"
185
+ return 0;
130
#include "net/net.h"
186
+}
131
#include "sysemu/sysemu.h"
187
+
132
#include "hw/pci/pci.h"
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
133
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
189
+{
134
index XXXXXXX..XXXXXXX 100644
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
135
--- a/hw/net/smc91c111.c
191
+
136
+++ b/hw/net/smc91c111.c
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
137
@@ -XXX,XX +XXX,XX @@
193
+ rtc_int_update_irq(s);
138
#include "qemu/osdep.h"
194
+ return 0;
139
#include "hw/sysbus.h"
195
+}
140
#include "net/net.h"
196
+
141
-#include "hw/devices.h"
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
142
+#include "hw/net/smc91c111.h"
198
+{
143
#include "qemu/log.h"
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
144
/* For crc32 */
200
+ addr_error_int_update_irq(s);
145
#include <zlib.h>
201
+}
202
+
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
204
+{
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
206
+
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
208
+ addr_error_int_update_irq(s);
209
+ return 0;
210
+}
211
+
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
213
+{
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
215
+
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
217
+ addr_error_int_update_irq(s);
218
+ return 0;
219
+}
220
+
221
+static const RegisterAccessInfo rtc_regs_info[] = {
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
227
+ .ro = 0x1fffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
229
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
231
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
234
+ .w1c = 0x3,
235
+ .post_write = rtc_int_status_postw,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
237
+ .reset = 0x3,
238
+ .ro = 0x3,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
240
+ .pre_write = rtc_int_en_prew,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
242
+ .pre_write = rtc_int_dis_prew,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
244
+ .w1c = 0x1,
245
+ .post_write = addr_error_postw,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
247
+ .reset = 0x1,
248
+ .ro = 0x1,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
250
+ .pre_write = addr_error_int_en_prew,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
252
+ .pre_write = addr_error_int_dis_prew,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
254
+ .reset = 0x1000000,
255
+ .rsvd = 0x70fffffe,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
257
+ }
258
+};
259
+
260
+static void rtc_reset(DeviceState *dev)
261
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
263
+ unsigned int i;
264
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
267
+ }
268
+
269
+ rtc_int_update_irq(s);
270
+ addr_error_int_update_irq(s);
271
+}
272
+
273
+static const MemoryRegionOps rtc_ops = {
274
+ .read = register_read_memory,
275
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+};
282
+
283
+static void rtc_init(Object *obj)
284
+{
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
287
+ RegisterInfoArray *reg_array;
288
+
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
291
+ reg_array =
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
293
+ ARRAY_SIZE(rtc_regs_info),
294
+ s->regs_info, s->regs,
295
+ &rtc_ops,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
298
+ memory_region_add_subregion(&s->iomem,
299
+ 0x0,
300
+ &reg_array->mem);
301
+ sysbus_init_mmio(sbd, &s->iomem);
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
304
+}
305
+
306
+static const VMStateDescription vmstate_rtc = {
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
312
+ VMSTATE_END_OF_LIST(),
313
+ }
314
+};
315
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
317
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+
320
+ dc->reset = rtc_reset;
321
+ dc->vmsd = &vmstate_rtc;
322
+}
323
+
324
+static const TypeInfo rtc_info = {
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
326
+ .parent = TYPE_SYS_BUS_DEVICE,
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
328
+ .class_init = rtc_class_init,
329
+ .instance_init = rtc_init,
330
+};
331
+
332
+static void rtc_register_types(void)
333
+{
334
+ type_register_static(&rtc_info);
335
+}
336
+
337
+type_init(rtc_register_types)
338
--
146
--
339
2.16.2
147
2.20.1
340
148
341
149
diff view generated by jsdifflib