1
ARM queu; includes all the NVIC rewrite patches.
1
Big pullreq this week, though none of the new features are
2
The QOMify-armv7m patchset hasn't got enough review just
2
particularly earthshaking. Most of the bulk is from code cleanup
3
yet but I may be able to sneak it in before freeze
3
patches from me or rth.
4
tomorrow if it gets review. Didn't want to hold this lot
5
up waiting, anyway.
6
4
7
thanks
5
thanks
8
-- PMM
6
-- PMM
9
7
8
The following changes since commit b651b80822fa8cb66ca30087ac7fbc75507ae5d2:
10
9
11
The following changes since commit 8f2d7c341184a95d05476ea3c45dbae2b9ddbe51:
10
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0-pull-request' into staging (2020-02-20 17:35:42 +0000)
12
11
13
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-02-27-1' into staging (2017-02-27 15:33:21 +0000)
12
are available in the Git repository at:
14
13
15
are available in the git repository at:
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200221
16
15
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170227
16
for you to fetch changes up to 270a679b3f950d7c4c600f324aab8bff292d0971:
18
17
19
for you to fetch changes up to 94d5bcf5a7f3799660b62098a5183f161aad0601:
18
target/arm: Add missing checks for fpsp_v2 (2020-02-21 12:54:25 +0000)
20
21
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID (2017-02-27 17:23:16 +0000)
22
19
23
----------------------------------------------------------------
20
----------------------------------------------------------------
24
target-arm queue:
21
target-arm queue:
25
* raspi2: implement RNG module, GPIO and new SD card controller
22
* aspeed/scu: Implement chip ID register
26
(sufficient to boot new raspbian kernels)
23
* hw/misc/iotkit-secctl: Fix writing to 'PPC Interrupt Clear' register
27
* sdhci: bugfixes for block transfers
24
* mainstone: Make providing flash images non-mandatory
28
* virt: fix cpu object reference leak
25
* z2: Make providing flash images non-mandatory
29
* Add missing fp_access_check() to aarch64 crypto instructions
26
* Fix failures to flush SVE high bits after AdvSIMD INS/ZIP/UZP/TRN/TBL/TBX/EXT
30
* cputlb: Don't assume do_unassigned_access() never returns
27
* Minor performance improvement: spend less time recalculating hflags values
31
* virt: Add a user option to disallow ITS instantiation
28
* Code cleanup to isar_feature function tests
32
* i.MX timers: fix reset handling
29
* Implement ARMv8.1-PMU and ARMv8.4-PMU extensions
33
* ARMv7M NVIC: rewrite to fix broken priority handling and masking
30
* Bugfix: correct handling of PMCR_EL0.LC bit
34
* exynos: Fix proper mapping of CPUs by providing real cluster ID
31
* Bugfix: correct definition of PMCRDP
35
* exynos: Fix Linux kernel division by zero for PLLs
32
* Correctly implement ACTLR2, HACTLR2
33
* allwinner: Wire up USB ports
34
* Vectorize emulation of USHL, SSHL, PMUL*
35
* xilinx_spips: Correct the number of dummy cycles for the FAST_READ_4 cmd
36
* sh4: Fix PCI ISA IO memory subregion
37
* Code cleanup to use more isar_feature tests and fewer ARM_FEATURE_* tests
36
38
37
----------------------------------------------------------------
39
----------------------------------------------------------------
38
Clement Deschamps (4):
40
Francisco Iglesias (1):
39
bcm2835_sdhost: add bcm2835 sdhost controller
41
xilinx_spips: Correct the number of dummy cycles for the FAST_READ_4 cmd
40
hw/sd: add card-reparenting function
41
bcm2835_gpio: add bcm2835 gpio controller
42
bcm2835: add sdhost and gpio controllers
43
42
44
Eric Auger (1):
43
Guenter Roeck (6):
45
hw/arm/virt: Add a user option to disallow ITS instantiation
44
mainstone: Make providing flash images non-mandatory
45
z2: Make providing flash images non-mandatory
46
hw: usb: hcd-ohci: Move OHCISysBusState and TYPE_SYSBUS_OHCI to include file
47
hcd-ehci: Introduce "companion-enable" sysbus property
48
arm: allwinner: Wire up USB ports
49
sh4: Fix PCI ISA IO memory subregion
46
50
47
Igor Mammedov (1):
51
Joel Stanley (2):
48
hw/arm/virt: fix cpu object reference leak
52
aspeed/scu: Create separate write callbacks
53
aspeed/scu: Implement chip ID register
49
54
50
Krzysztof Kozlowski (2):
55
Peter Maydell (21):
51
hw/arm/exynos: Fix Linux kernel division by zero for PLLs
56
target/arm: Add _aa32_ to isar_feature functions testing 32-bit ID registers
52
hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID
57
target/arm: Check aa32_pan in take_aarch32_exception(), not aa64_pan
58
target/arm: Add isar_feature_any_fp16 and document naming/usage conventions
59
target/arm: Define and use any_predinv isar_feature test
60
target/arm: Factor out PMU register definitions
61
target/arm: Add and use FIELD definitions for ID_AA64DFR0_EL1
62
target/arm: Use FIELD macros for clearing ID_DFR0 PERFMON field
63
target/arm: Define an aa32_pmu_8_1 isar feature test function
64
target/arm: Add _aa64_ and _any_ versions of pmu_8_1 isar checks
65
target/arm: Stop assuming DBGDIDR always exists
66
target/arm: Move DBGDIDR into ARMISARegisters
67
target/arm: Read debug-related ID registers from KVM
68
target/arm: Implement ARMv8.1-PMU extension
69
target/arm: Implement ARMv8.4-PMU extension
70
target/arm: Provide ARMv8.4-PMU in '-cpu max'
71
target/arm: Correct definition of PMCRDP
72
target/arm: Correct handling of PMCR_EL0.LC bit
73
target/arm: Test correct register in aa32_pan and aa32_ats1e1 checks
74
target/arm: Use isar_feature function for testing AA32HPD feature
75
target/arm: Use FIELD_EX32 for testing 32-bit fields
76
target/arm: Correctly implement ACTLR2, HACTLR2
53
77
54
Kurban Mallachiev (1):
78
Philippe Mathieu-Daudé (1):
55
ARM i.MX timers: fix reset handling
79
hw/misc/iotkit-secctl: Fix writing to 'PPC Interrupt Clear' register
56
80
57
Marcin Chojnacki (1):
81
Richard Henderson (21):
58
target-arm: Implement BCM2835 hardware RNG
82
target/arm: Flush high bits of sve register after AdvSIMD EXT
83
target/arm: Flush high bits of sve register after AdvSIMD TBL/TBX
84
target/arm: Flush high bits of sve register after AdvSIMD ZIP/UZP/TRN
85
target/arm: Flush high bits of sve register after AdvSIMD INS
86
target/arm: Use bit 55 explicitly for pauth
87
target/arm: Fix select for aa64_va_parameters_both
88
target/arm: Remove ttbr1_valid check from get_phys_addr_lpae
89
target/arm: Split out aa64_va_parameter_tbi, aa64_va_parameter_tbid
90
target/arm: Vectorize USHL and SSHL
91
target/arm: Convert PMUL.8 to gvec
92
target/arm: Convert PMULL.64 to gvec
93
target/arm: Convert PMULL.8 to gvec
94
target/arm: Rename isar_feature_aa32_simd_r32
95
target/arm: Use isar_feature_aa32_simd_r32 more places
96
target/arm: Set MVFR0.FPSP for ARMv5 cpus
97
target/arm: Add isar_feature_aa32_simd_r16
98
target/arm: Rename isar_feature_aa32_fpdp_v2
99
target/arm: Add isar_feature_aa32_{fpsp_v2, fpsp_v3, fpdp_v3}
100
target/arm: Perform fpdp_v2 check first
101
target/arm: Replace ARM_FEATURE_VFP3 checks with fp{sp, dp}_v3
102
target/arm: Add missing checks for fpsp_v2
59
103
60
Michael Davidsaver (5):
104
hw/usb/hcd-ohci.h | 16 ++
61
armv7m: Rewrite NVIC to not use any GIC code
105
include/hw/arm/allwinner-a10.h | 6 +
62
arm: gic: Remove references to NVIC
106
target/arm/cpu.h | 173 ++++++++++++---
63
armv7m: Escalate exceptions to HardFault if necessary
107
target/arm/helper-sve.h | 2 +
64
armv7m: Simpler and faster exception start
108
target/arm/helper.h | 21 +-
65
armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE
109
target/arm/internals.h | 47 +++-
110
target/arm/translate.h | 6 +
111
hw/arm/allwinner-a10.c | 43 ++++
112
hw/arm/mainstone.c | 11 +-
113
hw/arm/z2.c | 6 -
114
hw/intc/armv7m_nvic.c | 30 +--
115
hw/misc/aspeed_scu.c | 93 ++++++--
116
hw/misc/iotkit-secctl.c | 2 +-
117
hw/sh4/sh_pci.c | 11 +-
118
hw/ssi/xilinx_spips.c | 2 +-
119
hw/usb/hcd-ehci-sysbus.c | 2 +
120
hw/usb/hcd-ohci.c | 15 --
121
linux-user/arm/signal.c | 4 +-
122
linux-user/elfload.c | 4 +-
123
target/arm/arch_dump.c | 11 +-
124
target/arm/cpu.c | 175 +++++++--------
125
target/arm/cpu64.c | 58 +++--
126
target/arm/debug_helper.c | 6 +-
127
target/arm/helper.c | 472 +++++++++++++++++++++++------------------
128
target/arm/kvm32.c | 25 +++
129
target/arm/kvm64.c | 46 ++++
130
target/arm/m_helper.c | 11 +-
131
target/arm/machine.c | 3 +-
132
target/arm/neon_helper.c | 117 ----------
133
target/arm/pauth_helper.c | 3 +-
134
target/arm/translate-a64.c | 92 ++++----
135
target/arm/translate-vfp.inc.c | 263 ++++++++++++++---------
136
target/arm/translate.c | 356 ++++++++++++++++++++++++++-----
137
target/arm/vec_helper.c | 211 ++++++++++++++++++
138
target/arm/vfp_helper.c | 2 +-
139
35 files changed, 1564 insertions(+), 781 deletions(-)
66
140
67
Nick Reilly (1):
68
Add missing fp_access_check() to aarch64 crypto instructions
69
70
Peter Maydell (10):
71
bcm2835_rng: Use qcrypto_random_bytes() rather than rand()
72
cputlb: Don't assume do_unassigned_access() never returns
73
armv7m: Rename nvic_state to NVICState
74
armv7m: Implement reading and writing of PRIGROUP
75
armv7m: Fix condition check for taking exceptions
76
armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value
77
armv7m: Extract "exception taken" code into functions
78
armv7m: Check exception return consistency
79
armv7m: Raise correct kind of UsageFault for attempts to execute ARM code
80
armv7m: Allow SHCSR writes to change pending and active bits
81
82
Prasad J Pandit (4):
83
sd: sdhci: mask transfer mode register value
84
sd: sdhci: check transfer mode register in multi block transfer
85
sd: sdhci: conditionally invoke multi block transfer
86
sd: sdhci: Remove block count enable check in single block transfers
87
88
hw/gpio/Makefile.objs | 1 +
89
hw/misc/Makefile.objs | 3 +-
90
hw/sd/Makefile.objs | 1 +
91
hw/intc/gic_internal.h | 7 +-
92
include/hw/arm/bcm2835_peripherals.h | 6 +
93
include/hw/arm/virt.h | 1 +
94
include/hw/gpio/bcm2835_gpio.h | 39 ++
95
include/hw/misc/bcm2835_rng.h | 27 ++
96
include/hw/sd/bcm2835_sdhost.h | 48 ++
97
include/hw/sd/sd.h | 11 +
98
target/arm/cpu.h | 23 +-
99
cputlb.c | 15 +-
100
hw/arm/bcm2835_peripherals.c | 58 ++-
101
hw/arm/exynos4210.c | 18 +
102
hw/arm/virt.c | 32 +-
103
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++++
104
hw/intc/arm_gic.c | 31 +-
105
hw/intc/arm_gic_common.c | 23 +-
106
hw/intc/armv7m_nvic.c | 885 ++++++++++++++++++++++++++++-------
107
hw/misc/bcm2835_rng.c | 149 ++++++
108
hw/misc/exynos4210_clk.c | 164 +++++++
109
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++
110
hw/sd/core.c | 30 ++
111
hw/sd/sdhci.c | 25 +-
112
hw/timer/imx_gpt.c | 33 +-
113
linux-user/main.c | 1 +
114
target/arm/cpu.c | 16 +-
115
target/arm/helper.c | 245 +++++++---
116
target/arm/translate-a64.c | 12 +
117
target/arm/translate.c | 8 +-
118
hw/intc/trace-events | 15 +
119
31 files changed, 2376 insertions(+), 333 deletions(-)
120
create mode 100644 include/hw/gpio/bcm2835_gpio.h
121
create mode 100644 include/hw/misc/bcm2835_rng.h
122
create mode 100644 include/hw/sd/bcm2835_sdhost.h
123
create mode 100644 hw/gpio/bcm2835_gpio.c
124
create mode 100644 hw/misc/bcm2835_rng.c
125
create mode 100644 hw/misc/exynos4210_clk.c
126
create mode 100644 hw/sd/bcm2835_sdhost.c
127
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Joel Stanley <joel@jms.id.au>
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
This splits the common write callback into separate ast2400 and ast2500
4
a card from a SDBus to another one.
4
implementations. This makes it clearer when implementing differing
5
behaviour.
5
6
6
This function is required by the raspi platform, where the two SD
7
Signed-off-by: Joel Stanley <joel@jms.id.au>
7
controllers can be dynamically switched.
8
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
8
9
Reviewed-by: Cédric Le Goater <clg@kaod.org>
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
11
Message-id: 20200121013302.43839-2-joel@jms.id.au
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: added a doc comment to the header file]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
include/hw/sd/sd.h | 11 +++++++++++
14
hw/misc/aspeed_scu.c | 80 +++++++++++++++++++++++++++++++-------------
16
hw/sd/core.c | 30 ++++++++++++++++++++++++++++++
15
1 file changed, 57 insertions(+), 23 deletions(-)
17
2 files changed, 41 insertions(+)
18
16
19
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
17
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/sd/sd.h
19
--- a/hw/misc/aspeed_scu.c
22
+++ b/include/hw/sd/sd.h
20
+++ b/hw/misc/aspeed_scu.c
23
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
21
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
24
bool sdbus_data_ready(SDBus *sd);
22
return s->regs[reg];
25
bool sdbus_get_inserted(SDBus *sd);
26
bool sdbus_get_readonly(SDBus *sd);
27
+/**
28
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
29
+ * @from: controller bus to remove card from
30
+ * @to: controller bus to move card to
31
+ *
32
+ * Reparent an SD card, effectively unplugging it from one controller
33
+ * and inserting it into another. This is useful for SoCs like the
34
+ * bcm2835 which have two SD controllers and connect a single SD card
35
+ * to them, selected by the guest reprogramming GPIO line routing.
36
+ */
37
+void sdbus_reparent_card(SDBus *from, SDBus *to);
38
39
/* Functions to be used by SD devices to report back to qdevified controllers */
40
void sdbus_set_inserted(SDBus *sd, bool inserted);
41
diff --git a/hw/sd/core.c b/hw/sd/core.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/sd/core.c
44
+++ b/hw/sd/core.c
45
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
46
}
47
}
23
}
48
24
49
+void sdbus_reparent_card(SDBus *from, SDBus *to)
25
-static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
26
- unsigned size)
27
+static void aspeed_ast2400_scu_write(void *opaque, hwaddr offset,
28
+ uint64_t data, unsigned size)
50
+{
29
+{
51
+ BusChild *kid = QTAILQ_FIRST(&from->qbus.children);
30
+ AspeedSCUState *s = ASPEED_SCU(opaque);
52
+ SDState *card;
31
+ int reg = TO_REG(offset);
53
+ SDCardClass *sc;
54
+ bool readonly;
55
+
32
+
56
+ /* We directly reparent the card object rather than implementing this
33
+ if (reg >= ASPEED_SCU_NR_REGS) {
57
+ * as a hotpluggable connection because we don't want to expose SD cards
34
+ qemu_log_mask(LOG_GUEST_ERROR,
58
+ * to users as being hotpluggable, and we can get away with it in this
35
+ "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
59
+ * limited use case. This could perhaps be implemented more cleanly in
36
+ __func__, offset);
60
+ * future by adding support to the hotplug infrastructure for "device
61
+ * can be hotplugged only via code, not by user".
62
+ */
63
+
64
+ if (!kid) {
65
+ return;
37
+ return;
66
+ }
38
+ }
67
+
39
+
68
+ card = SD_CARD(kid->child);
40
+ if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
69
+ sc = SD_CARD_GET_CLASS(card);
41
+ !s->regs[PROT_KEY]) {
70
+ readonly = sc->get_readonly(card);
42
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
43
+ }
71
+
44
+
72
+ sdbus_set_inserted(from, false);
45
+ trace_aspeed_scu_write(offset, size, data);
73
+ object_unparent(OBJECT(kid));
46
+
74
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
47
+ switch (reg) {
75
+ sdbus_set_inserted(to, true);
48
+ case PROT_KEY:
76
+ sdbus_set_readonly(to, readonly);
49
+ s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
50
+ return;
51
+ case SILICON_REV:
52
+ case FREQ_CNTR_EVAL:
53
+ case VGA_SCRATCH1 ... VGA_SCRATCH8:
54
+ case RNG_DATA:
55
+ case FREE_CNTR4:
56
+ case FREE_CNTR4_EXT:
57
+ qemu_log_mask(LOG_GUEST_ERROR,
58
+ "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
59
+ __func__, offset);
60
+ return;
61
+ }
62
+
63
+ s->regs[reg] = data;
77
+}
64
+}
78
+
65
+
79
static const TypeInfo sd_bus_info = {
66
+static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
80
.name = TYPE_SD_BUS,
67
+ uint64_t data, unsigned size)
81
.parent = TYPE_BUS,
68
{
69
AspeedSCUState *s = ASPEED_SCU(opaque);
70
int reg = TO_REG(offset);
71
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
72
case PROT_KEY:
73
s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
74
return;
75
- case CLK_SEL:
76
- s->regs[reg] = data;
77
- break;
78
case HW_STRAP1:
79
- if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
80
- s->regs[HW_STRAP1] |= data;
81
- return;
82
- }
83
- /* Jump to assignment below */
84
- break;
85
+ s->regs[HW_STRAP1] |= data;
86
+ return;
87
case SILICON_REV:
88
- if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
89
- s->regs[HW_STRAP1] &= ~data;
90
- } else {
91
- qemu_log_mask(LOG_GUEST_ERROR,
92
- "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
93
- __func__, offset);
94
- }
95
- /* Avoid assignment below, we've handled everything */
96
+ s->regs[HW_STRAP1] &= ~data;
97
return;
98
case FREQ_CNTR_EVAL:
99
case VGA_SCRATCH1 ... VGA_SCRATCH8:
100
@@ -XXX,XX +XXX,XX @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
101
s->regs[reg] = data;
102
}
103
104
-static const MemoryRegionOps aspeed_scu_ops = {
105
+static const MemoryRegionOps aspeed_ast2400_scu_ops = {
106
.read = aspeed_scu_read,
107
- .write = aspeed_scu_write,
108
+ .write = aspeed_ast2400_scu_write,
109
+ .endianness = DEVICE_LITTLE_ENDIAN,
110
+ .valid.min_access_size = 4,
111
+ .valid.max_access_size = 4,
112
+ .valid.unaligned = false,
113
+};
114
+
115
+static const MemoryRegionOps aspeed_ast2500_scu_ops = {
116
+ .read = aspeed_scu_read,
117
+ .write = aspeed_ast2500_scu_write,
118
.endianness = DEVICE_LITTLE_ENDIAN,
119
.valid.min_access_size = 4,
120
.valid.max_access_size = 4,
121
@@ -XXX,XX +XXX,XX @@ static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
122
asc->calc_hpll = aspeed_2400_scu_calc_hpll;
123
asc->apb_divider = 2;
124
asc->nr_regs = ASPEED_SCU_NR_REGS;
125
- asc->ops = &aspeed_scu_ops;
126
+ asc->ops = &aspeed_ast2400_scu_ops;
127
}
128
129
static const TypeInfo aspeed_2400_scu_info = {
130
@@ -XXX,XX +XXX,XX @@ static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
131
asc->calc_hpll = aspeed_2500_scu_calc_hpll;
132
asc->apb_divider = 4;
133
asc->nr_regs = ASPEED_SCU_NR_REGS;
134
- asc->ops = &aspeed_scu_ops;
135
+ asc->ops = &aspeed_ast2500_scu_ops;
136
}
137
138
static const TypeInfo aspeed_2500_scu_info = {
82
--
139
--
83
2.7.4
140
2.20.1
84
141
85
142
diff view generated by jsdifflib
1
Implement the NVIC SHCSR write behaviour which allows pending and
1
From: Joel Stanley <joel@jms.id.au>
2
active status of some exceptions to be changed.
3
2
3
This returns a fixed but non-zero value for the chip id.
4
5
Signed-off-by: Joel Stanley <joel@jms.id.au>
6
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200121013302.43839-3-joel@jms.id.au
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
---
11
---
7
hw/intc/armv7m_nvic.c | 13 +++++++++++--
12
hw/misc/aspeed_scu.c | 13 +++++++++++++
8
1 file changed, 11 insertions(+), 2 deletions(-)
13
1 file changed, 13 insertions(+)
9
14
10
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
15
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
11
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/intc/armv7m_nvic.c
17
--- a/hw/misc/aspeed_scu.c
13
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/hw/misc/aspeed_scu.c
14
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
19
@@ -XXX,XX +XXX,XX @@
15
cpu->env.v7m.ccr = value;
20
#define CPU2_BASE_SEG4 TO_REG(0x110)
16
break;
21
#define CPU2_BASE_SEG5 TO_REG(0x114)
17
case 0xd24: /* System Handler Control. */
22
#define CPU2_CACHE_CTRL TO_REG(0x118)
18
- /* TODO: Real hardware allows you to set/clear the active bits
23
+#define CHIP_ID0 TO_REG(0x150)
19
- under some circumstances. We don't implement this. */
24
+#define CHIP_ID1 TO_REG(0x154)
20
+ s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
25
#define UART_HPLL_CLK TO_REG(0x160)
21
+ s->vectors[ARMV7M_EXCP_BUS].active = (value & (1 << 1)) != 0;
26
#define PCIE_CTRL TO_REG(0x180)
22
+ s->vectors[ARMV7M_EXCP_USAGE].active = (value & (1 << 3)) != 0;
27
#define BMC_MMIO_CTRL TO_REG(0x184)
23
+ s->vectors[ARMV7M_EXCP_SVC].active = (value & (1 << 7)) != 0;
28
@@ -XXX,XX +XXX,XX @@
24
+ s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
29
#define AST2600_HW_STRAP2_PROT TO_REG(0x518)
25
+ s->vectors[ARMV7M_EXCP_PENDSV].active = (value & (1 << 10)) != 0;
30
#define AST2600_RNG_CTRL TO_REG(0x524)
26
+ s->vectors[ARMV7M_EXCP_SYSTICK].active = (value & (1 << 11)) != 0;
31
#define AST2600_RNG_DATA TO_REG(0x540)
27
+ s->vectors[ARMV7M_EXCP_USAGE].pending = (value & (1 << 12)) != 0;
32
+#define AST2600_CHIP_ID0 TO_REG(0x5B0)
28
+ s->vectors[ARMV7M_EXCP_MEM].pending = (value & (1 << 13)) != 0;
33
+#define AST2600_CHIP_ID1 TO_REG(0x5B4)
29
+ s->vectors[ARMV7M_EXCP_BUS].pending = (value & (1 << 14)) != 0;
34
30
+ s->vectors[ARMV7M_EXCP_SVC].pending = (value & (1 << 15)) != 0;
35
#define AST2600_CLK TO_REG(0x40)
31
s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
36
32
s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
37
@@ -XXX,XX +XXX,XX @@ static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
33
s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
38
[CPU2_BASE_SEG1] = 0x80000000U,
39
[CPU2_BASE_SEG4] = 0x1E600000U,
40
[CPU2_BASE_SEG5] = 0xC0000000U,
41
+ [CHIP_ID0] = 0x1234ABCDU,
42
+ [CHIP_ID1] = 0x88884444U,
43
[UART_HPLL_CLK] = 0x00001903U,
44
[PCIE_CTRL] = 0x0000007BU,
45
[BMC_DEV_ID] = 0x00002402U
46
@@ -XXX,XX +XXX,XX @@ static void aspeed_ast2500_scu_write(void *opaque, hwaddr offset,
47
case RNG_DATA:
48
case FREE_CNTR4:
49
case FREE_CNTR4_EXT:
50
+ case CHIP_ID0:
51
+ case CHIP_ID1:
52
qemu_log_mask(LOG_GUEST_ERROR,
53
"%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
54
__func__, offset);
55
@@ -XXX,XX +XXX,XX @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
56
case AST2600_RNG_DATA:
57
case AST2600_SILICON_REV:
58
case AST2600_SILICON_REV2:
59
+ case AST2600_CHIP_ID0:
60
+ case AST2600_CHIP_ID1:
61
/* Add read only registers here */
62
qemu_log_mask(LOG_GUEST_ERROR,
63
"%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
64
@@ -XXX,XX +XXX,XX @@ static const uint32_t ast2600_a0_resets[ASPEED_AST2600_SCU_NR_REGS] = {
65
[AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
66
[AST2600_SDRAM_HANDSHAKE] = 0x00000040, /* SoC completed DRAM init */
67
[AST2600_HPLL_PARAM] = 0x1000405F,
68
+ [AST2600_CHIP_ID0] = 0x1234ABCD,
69
+ [AST2600_CHIP_ID1] = 0x88884444,
70
+
71
};
72
73
static void aspeed_ast2600_scu_reset(DeviceState *dev)
34
--
74
--
35
2.7.4
75
2.20.1
36
76
37
77
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Fix warning reported by Clang static code analyzer:
4
5
CC hw/misc/iotkit-secctl.o
6
hw/misc/iotkit-secctl.c:343:9: warning: Value stored to 'value' is never read
7
value &= 0x00f000f3;
8
^ ~~~~~~~~~~
9
10
Fixes: b3717c23e1c
11
Reported-by: Clang Static Analyzer
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20200217132922.24607-1-f4bug@amsat.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/misc/iotkit-secctl.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/iotkit-secctl.c
23
+++ b/hw/misc/iotkit-secctl.c
24
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
25
qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
26
break;
27
case A_SECPPCINTCLR:
28
- value &= 0x00f000f3;
29
+ s->secppcintstat &= ~(value & 0x00f000f3);
30
foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
31
break;
32
case A_SECPPCINTEN:
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
In the SDHCI protocol, the transfer mode register value
3
Up to now, the mainstone machine only boots if two flash images are
4
is used during multi block transfer to check if block count
4
provided. This is not really necessary; the machine can boot from initrd
5
register is enabled and should be updated. Transfer mode
5
or from SD without it. At the same time, having to provide dummy flash
6
register could be set such that, block count register would
6
images is a nuisance and does not add any real value. Make it optional.
7
not be updated, thus leading to an infinite loop. Add check
8
to avoid it.
9
7
10
Reported-by: Wjjzhang <wjjzhang@tencent.com>
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
11
Reported-by: Jiang Xin <jiangxin1@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
10
Message-id: 20200217210824.18513-1-linux@roeck-us.net
13
Message-id: 20170214185225.7994-3-ppandit@redhat.com
14
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
hw/sd/sdhci.c | 10 +++++-----
13
hw/arm/mainstone.c | 11 +----------
18
1 file changed, 5 insertions(+), 5 deletions(-)
14
1 file changed, 1 insertion(+), 10 deletions(-)
19
15
20
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/sd/sdhci.c
18
--- a/hw/arm/mainstone.c
23
+++ b/hw/sd/sdhci.c
19
+++ b/hw/arm/mainstone.c
24
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
20
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
25
uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
21
/* There are two 32MiB flash devices on the board */
26
uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
22
for (i = 0; i < 2; i ++) {
27
23
dinfo = drive_get(IF_PFLASH, 0, i);
28
+ if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) {
24
- if (!dinfo) {
29
+ qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
25
- if (qtest_enabled()) {
30
+ return;
31
+ }
32
+
33
/* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
34
* possible stop at page boundary if initial address is not page aligned,
35
* allow them to work properly */
36
@@ -XXX,XX +XXX,XX @@ static void sdhci_data_transfer(void *opaque)
37
if (s->trnmod & SDHC_TRNS_DMA) {
38
switch (SDHC_DMA_TYPE(s->hostctl)) {
39
case SDHC_CTRL_SDMA:
40
- if ((s->trnmod & SDHC_TRNS_MULTI) &&
41
- (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
42
- break;
26
- break;
43
- }
27
- }
28
- error_report("Two flash images must be given with the "
29
- "'pflash' parameter");
30
- exit(1);
31
- }
44
-
32
-
45
if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
33
if (!pflash_cfi01_register(mainstone_flash_base[i],
46
sdhci_sdma_transfer_single_block(s);
34
i ? "mainstone.flash1" : "mainstone.flash0",
47
} else {
35
MAINSTONE_FLASH,
36
- blk_by_legacy_dinfo(dinfo),
37
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
38
sector_len, 4, 0, 0, 0, 0, be)) {
39
error_report("Error registering flash memory");
40
exit(1);
48
--
41
--
49
2.7.4
42
2.20.1
50
43
51
44
diff view generated by jsdifflib
New patch
1
From: Guenter Roeck <linux@roeck-us.net>
1
2
3
Up to now, the z2 machine only boots if a flash image is provided.
4
This is not really necessary; the machine can boot from initrd or from
5
SD without it. At the same time, having to provide dummy flash images
6
is a nuisance and does not add any real value. Make it optional.
7
8
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20200217210903.18602-1-linux@roeck-us.net
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/z2.c | 6 ------
14
1 file changed, 6 deletions(-)
15
16
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/z2.c
19
+++ b/hw/arm/z2.c
20
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
21
be = 0;
22
#endif
23
dinfo = drive_get(IF_PFLASH, 0, 0);
24
- if (!dinfo && !qtest_enabled()) {
25
- error_report("Flash image must be given with the "
26
- "'pflash' parameter");
27
- exit(1);
28
- }
29
-
30
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
31
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
32
sector_len, 4, 0, 0, 0, 0, be)) {
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value
3
Writes to AdvSIMD registers flush the bits above 128.
4
0x8000090x). If this cluster ID is not provided, then Linux kernel
5
cannot map DeviceTree nodes to MPIDR values resulting in kernel
6
warning and lack of any secondary CPUs:
7
4
8
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
5
Buglink: https://bugs.launchpad.net/bugs/1863247
9
...
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
smp: Bringing up secondary CPUs ...
7
Message-id: 20200214194643.23317-2-richard.henderson@linaro.org
11
smp: Brought up 1 node, 1 CPU
12
SMP: Total of 1 processors activated (24.00 BogoMIPS).
13
14
Provide a cluster ID so Linux will see proper MPIDR and will try to
15
bring the secondary CPU online.
16
17
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
18
Message-id: 20170226200142.31169-2-krzk@kernel.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
10
---
22
hw/arm/exynos4210.c | 12 ++++++++++++
11
target/arm/translate-a64.c | 1 +
23
1 file changed, 12 insertions(+)
12
1 file changed, 1 insertion(+)
24
13
25
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/exynos4210.c
16
--- a/target/arm/translate-a64.c
28
+++ b/hw/arm/exynos4210.c
17
+++ b/target/arm/translate-a64.c
29
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
30
info->smp_loader_start);
19
tcg_temp_free_i64(tcg_resl);
20
write_vec_element(s, tcg_resh, rd, 1, MO_64);
21
tcg_temp_free_i64(tcg_resh);
22
+ clear_vec_high(s, true, rd);
31
}
23
}
32
24
33
+static uint64_t exynos4210_calc_affinity(int cpu)
25
/* TBL/TBX
34
+{
35
+ uint64_t mp_affinity;
36
+
37
+ /* Exynos4210 has 0x9 as cluster ID */
38
+ mp_affinity = (0x9 << ARM_AFF1_SHIFT) | cpu;
39
+
40
+ return mp_affinity;
41
+}
42
+
43
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
44
unsigned long ram_size)
45
{
46
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
47
}
48
49
s->cpu[n] = ARM_CPU(cpuobj);
50
+ object_property_set_int(cpuobj, exynos4210_calc_affinity(n),
51
+ "mp-affinity", &error_abort);
52
object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR,
53
"reset-cbar", &error_abort);
54
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
55
--
26
--
56
2.7.4
27
2.20.1
57
28
58
29
diff view generated by jsdifflib
1
From: Nick Reilly <nreilly@blackberry.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The aarch64 crypto instructions for AES and SHA are missing the
3
Writes to AdvSIMD registers flush the bits above 128.
4
check for if the FPU is enabled.
5
4
6
Signed-off-by: Nick Reilly <nreilly@blackberry.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200214194643.23317-3-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/translate-a64.c | 12 ++++++++++++
10
target/arm/translate-a64.c | 1 +
11
1 file changed, 12 insertions(+)
11
1 file changed, 1 insertion(+)
12
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
15
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
18
return;
18
tcg_temp_free_i64(tcg_resl);
19
}
19
write_vec_element(s, tcg_resh, rd, 1, MO_64);
20
20
tcg_temp_free_i64(tcg_resh);
21
+ if (!fp_access_check(s)) {
21
+ clear_vec_high(s, true, rd);
22
+ return;
22
}
23
+ }
23
24
+
24
/* ZIP/UZP/TRN
25
/* Note that we convert the Vx register indexes into the
26
* index within the vfp.regs[] array, so we can share the
27
* helper with the AArch32 instructions.
28
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
29
return;
30
}
31
32
+ if (!fp_access_check(s)) {
33
+ return;
34
+ }
35
+
36
tcg_rd_regno = tcg_const_i32(rd << 1);
37
tcg_rn_regno = tcg_const_i32(rn << 1);
38
tcg_rm_regno = tcg_const_i32(rm << 1);
39
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
40
return;
41
}
42
43
+ if (!fp_access_check(s)) {
44
+ return;
45
+ }
46
+
47
tcg_rd_regno = tcg_const_i32(rd << 1);
48
tcg_rn_regno = tcg_const_i32(rn << 1);
49
50
--
25
--
51
2.7.4
26
2.20.1
52
27
53
28
diff view generated by jsdifflib
1
From: Igor Mammedov <imammedo@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
object_new(FOO) returns an object with ref_cnt == 1
3
Writes to AdvSIMD registers flush the bits above 128.
4
and following
5
object_property_set_bool(cpuobj, true, "realized", NULL)
6
set parent of cpuobj to '/machine/unattached' which makes
7
ref_cnt == 2.
8
4
9
Since machvirt_init() doesn't take ownership of cpuobj
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
returned by object_new() it should explicitly drop
6
Message-id: 20200214194643.23317-4-richard.henderson@linaro.org
11
reference to cpuobj when dangling pointer is about to
12
go out of scope like it's done pc_new_cpu() to avoid
13
object leak.
14
15
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
16
Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
9
---
20
hw/arm/virt.c | 1 +
10
target/arm/translate-a64.c | 1 +
21
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+)
22
12
23
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/virt.c
15
--- a/target/arm/translate-a64.c
26
+++ b/hw/arm/virt.c
16
+++ b/target/arm/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
28
}
18
tcg_temp_free_i64(tcg_resl);
29
19
write_vec_element(s, tcg_resh, rd, 1, MO_64);
30
object_property_set_bool(cpuobj, true, "realized", NULL);
20
tcg_temp_free_i64(tcg_resh);
31
+ object_unref(cpuobj);
21
+ clear_vec_high(s, true, rd);
32
}
22
}
33
fdt_add_timer_nodes(vms);
23
34
fdt_add_cpu_nodes(vms);
24
/*
35
--
25
--
36
2.7.4
26
2.20.1
37
27
38
28
diff view generated by jsdifflib
1
From: Kurban Mallachiev <mallachiev@ispras.ru>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The i.MX timer device can be reset by writing to the SWR bit
3
Writes to AdvSIMD registers flush the bits above 128.
4
of the CR register. This has to behave differently from hard
5
(power-on) reset because it does not reset all of the bits
6
in the CR register.
7
4
8
We were incorrectly implementing soft reset and hard reset
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
the same way, and in addition had a logic error which meant
6
Message-id: 20200214194643.23317-5-richard.henderson@linaro.org
10
that we were clearing the bits that soft-reset is supposed
11
to preserve and not touching the bits that soft-reset clears.
12
This was not correct behaviour for either kind of reset.
13
14
Separate out the soft reset and hard reset code paths, and
15
correct the handling of reset of the CR register so that it
16
is correct in both cases.
17
18
Signed-off-by: Kurban Mallachiev <mallachiev@ispras.ru>
19
[PMM: rephrased commit message, spacing on operators;
20
use bool rather than int for is_soft_reset]
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
9
---
24
hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++--------
10
target/arm/translate-a64.c | 6 ++++++
25
1 file changed, 25 insertions(+), 8 deletions(-)
11
1 file changed, 6 insertions(+)
26
12
27
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
28
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/timer/imx_gpt.c
15
--- a/target/arm/translate-a64.c
30
+++ b/hw/timer/imx_gpt.c
16
+++ b/target/arm/translate-a64.c
31
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
17
@@ -XXX,XX +XXX,XX @@ static void handle_simd_inse(DisasContext *s, int rd, int rn,
32
return reg_value;
18
write_vec_element(s, tmp, rd, dst_index, size);
19
20
tcg_temp_free_i64(tmp);
21
+
22
+ /* INS is considered a 128-bit write for SVE. */
23
+ clear_vec_high(s, true, rd);
33
}
24
}
34
25
35
-static void imx_gpt_reset(DeviceState *dev)
26
36
-{
27
@@ -XXX,XX +XXX,XX @@ static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
37
- IMXGPTState *s = IMX_GPT(dev);
28
38
29
idx = extract32(imm5, 1 + size, 4 - size);
39
+static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
30
write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
40
+{
31
+
41
/* stop timer */
32
+ /* INS is considered a 128-bit write for SVE. */
42
ptimer_stop(s->timer);
33
+ clear_vec_high(s, true, rd);
43
44
- /*
45
- * Soft reset doesn't touch some bits; hard reset clears them
46
+ /* Soft reset and hard reset differ only in their handling of the CR
47
+ * register -- soft reset preserves the values of some bits there.
48
*/
49
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
50
- GPT_CR_WAITEN|GPT_CR_DBGEN);
51
+ if (is_soft_reset) {
52
+ /* Clear all CR bits except those that are preserved by soft reset. */
53
+ s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN |
54
+ GPT_CR_WAITEN | GPT_CR_DBGEN |
55
+ (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT);
56
+ } else {
57
+ s->cr = 0;
58
+ }
59
s->sr = 0;
60
s->pr = 0;
61
s->ir = 0;
62
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_reset(DeviceState *dev)
63
}
64
}
34
}
65
35
66
+static void imx_gpt_soft_reset(DeviceState *dev)
36
/*
67
+{
68
+ IMXGPTState *s = IMX_GPT(dev);
69
+ imx_gpt_reset_common(s, true);
70
+}
71
+
72
+static void imx_gpt_reset(DeviceState *dev)
73
+{
74
+ IMXGPTState *s = IMX_GPT(dev);
75
+ imx_gpt_reset_common(s, false);
76
+}
77
+
78
static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
82
s->cr = value & ~0x7c14;
83
if (s->cr & GPT_CR_SWR) { /* force reset */
84
/* handle the reset */
85
- imx_gpt_reset(DEVICE(s));
86
+ imx_gpt_soft_reset(DEVICE(s));
87
} else {
88
/* set our freq, as the source might have changed */
89
imx_gpt_set_freq(s);
90
--
37
--
91
2.7.4
38
2.20.1
92
39
93
40
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In SDHCI protocol, the transfer mode register is defined
3
The psuedocode in aarch64/functions/pac/auth/Auth and
4
to be of 6 bits. Mask its value with '0x0037' so that an
4
aarch64/functions/pac/strip/Strip always uses bit 55 for
5
invalid value could not be assigned.
5
extfield and do not consider if the current regime has 2 ranges.
6
6
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
7
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20170214185225.7994-2-ppandit@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20200216194343.21331-2-richard.henderson@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
hw/sd/sdhci.c | 3 ++-
13
target/arm/pauth_helper.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
14
1 file changed, 2 insertions(+), 1 deletion(-)
14
15
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
18
--- a/target/arm/pauth_helper.c
18
+++ b/hw/sd/sdhci.c
19
+++ b/target/arm/pauth_helper.c
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
20
(SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
21
21
(SDHC_CAPAB_TOCLKFREQ))
22
static uint64_t pauth_original_ptr(uint64_t ptr, ARMVAParameters param)
22
23
{
23
+#define MASK_TRNMOD 0x0037
24
- uint64_t extfield = -param.select;
24
#define MASKED_WRITE(reg, mask, val) (reg = (reg & (mask)) | (val))
25
+ /* Note that bit 55 is used whether or not the regime has 2 ranges. */
25
26
+ uint64_t extfield = sextract64(ptr, 55, 1);
26
static uint8_t sdhci_slotint(SDHCIState *s)
27
int bot_pac_bit = 64 - param.tsz;
27
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
28
int top_pac_bit = 64 - 8 * param.tbi;
28
if (!(s->capareg & SDHC_CAN_DO_DMA)) {
29
29
value &= ~SDHC_TRNS_DMA;
30
}
31
- MASKED_WRITE(s->trnmod, mask, value);
32
+ MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD);
33
MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
34
35
/* Writing to the upper byte of CMDREG triggers SD command generation */
36
--
30
--
37
2.7.4
31
2.20.1
38
32
39
33
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Select should always be 0 for a regime with one range.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200216194343.21331-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper.c | 46 +++++++++++++++++++++++----------------------
11
1 file changed, 24 insertions(+), 22 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
18
bool tbi, tbid, epd, hpd, using16k, using64k;
19
int select, tsz;
20
21
- /*
22
- * Bit 55 is always between the two regions, and is canonical for
23
- * determining if address tagging is enabled.
24
- */
25
- select = extract64(va, 55, 1);
26
-
27
if (!regime_has_2_ranges(mmu_idx)) {
28
+ select = 0;
29
tsz = extract32(tcr, 0, 6);
30
using64k = extract32(tcr, 14, 1);
31
using16k = extract32(tcr, 15, 1);
32
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
33
tbid = extract32(tcr, 29, 1);
34
}
35
epd = false;
36
- } else if (!select) {
37
- tsz = extract32(tcr, 0, 6);
38
- epd = extract32(tcr, 7, 1);
39
- using64k = extract32(tcr, 14, 1);
40
- using16k = extract32(tcr, 15, 1);
41
- tbi = extract64(tcr, 37, 1);
42
- hpd = extract64(tcr, 41, 1);
43
- tbid = extract64(tcr, 51, 1);
44
} else {
45
- int tg = extract32(tcr, 30, 2);
46
- using16k = tg == 1;
47
- using64k = tg == 3;
48
- tsz = extract32(tcr, 16, 6);
49
- epd = extract32(tcr, 23, 1);
50
- tbi = extract64(tcr, 38, 1);
51
- hpd = extract64(tcr, 42, 1);
52
- tbid = extract64(tcr, 52, 1);
53
+ /*
54
+ * Bit 55 is always between the two regions, and is canonical for
55
+ * determining if address tagging is enabled.
56
+ */
57
+ select = extract64(va, 55, 1);
58
+ if (!select) {
59
+ tsz = extract32(tcr, 0, 6);
60
+ epd = extract32(tcr, 7, 1);
61
+ using64k = extract32(tcr, 14, 1);
62
+ using16k = extract32(tcr, 15, 1);
63
+ tbi = extract64(tcr, 37, 1);
64
+ hpd = extract64(tcr, 41, 1);
65
+ tbid = extract64(tcr, 51, 1);
66
+ } else {
67
+ int tg = extract32(tcr, 30, 2);
68
+ using16k = tg == 1;
69
+ using64k = tg == 3;
70
+ tsz = extract32(tcr, 16, 6);
71
+ epd = extract32(tcr, 23, 1);
72
+ tbi = extract64(tcr, 38, 1);
73
+ hpd = extract64(tcr, 42, 1);
74
+ tbid = extract64(tcr, 52, 1);
75
+ }
76
}
77
tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
78
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Now that aa64_va_parameters_both sets select based on the number
4
of ranges in the regime, the ttbr1_valid check is redundant.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200216194343.21331-4-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 6 +-----
12
1 file changed, 1 insertion(+), 5 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
19
TCR *tcr = regime_tcr(env, mmu_idx);
20
int ap, ns, xn, pxn;
21
uint32_t el = regime_el(env, mmu_idx);
22
- bool ttbr1_valid;
23
uint64_t descaddrmask;
24
bool aarch64 = arm_el_is_aa64(env, el);
25
bool guarded = false;
26
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
27
param = aa64_va_parameters(env, address, mmu_idx,
28
access_type != MMU_INST_FETCH);
29
level = 0;
30
- ttbr1_valid = regime_has_2_ranges(mmu_idx);
31
addrsize = 64 - 8 * param.tbi;
32
inputsize = 64 - param.tsz;
33
} else {
34
param = aa32_va_parameters(env, address, mmu_idx);
35
level = 1;
36
- /* There is no TTBR1 for EL2 */
37
- ttbr1_valid = (el != 2);
38
addrsize = (mmu_idx == ARMMMUIdx_Stage2 ? 40 : 32);
39
inputsize = addrsize - param.tsz;
40
}
41
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
42
if (inputsize < addrsize) {
43
target_ulong top_bits = sextract64(address, inputsize,
44
addrsize - inputsize);
45
- if (-top_bits != param.select || (param.select && !ttbr1_valid)) {
46
+ if (-top_bits != param.select) {
47
/* The gap between the two regions is a Translation fault */
48
fault_type = ARMFault_Translation;
49
goto do_fault;
50
--
51
2.20.1
52
53
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Without any clock controller, the Linux kernel was hitting division by
3
For the purpose of rebuild_hflags_a64, we do not need to compute
4
zero during boot or with clk_summary:
4
all of the va parameters, only tbi. Moreover, we can compute them
5
[ 0.000000] [<c031054c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
5
in a form that is more useful to storing in hflags.
6
[ 0.000000] [<c030ba6c>] (show_stack) from [<c05b2660>] (dump_stack+0x88/0x9c)
7
[ 0.000000] [<c05b2660>] (dump_stack) from [<c05b11a4>] (Ldiv0+0x8/0x10)
8
[ 0.000000] [<c05b11a4>] (Ldiv0) from [<c06ad1e0>] (samsung_pll45xx_recalc_rate+0x58/0x74)
9
[ 0.000000] [<c06ad1e0>] (samsung_pll45xx_recalc_rate) from [<c0692ec0>] (clk_register+0x39c/0x63c)
10
[ 0.000000] [<c0692ec0>] (clk_register) from [<c125d360>] (samsung_clk_register_pll+0x2e0/0x3d4)
11
[ 0.000000] [<c125d360>] (samsung_clk_register_pll) from [<c125d7e8>] (exynos4_clk_init+0x1b0/0x5e4)
12
[ 0.000000] [<c125d7e8>] (exynos4_clk_init) from [<c12335f4>] (of_clk_init+0x17c/0x210)
13
[ 0.000000] [<c12335f4>] (of_clk_init) from [<c1204700>] (time_init+0x24/0x2c)
14
[ 0.000000] [<c1204700>] (time_init) from [<c1200b2c>] (start_kernel+0x24c/0x38c)
15
[ 0.000000] [<c1200b2c>] (start_kernel) from [<4020807c>] (0x4020807c)
16
6
17
Provide stub for clock controller returning reset values for PLLs.
7
This eliminates the need for aa64_va_parameter_both, so fold that
8
in to aa64_va_parameter. The remaining calls to aa64_va_parameter
9
are in get_phys_addr_lpae and in pauth_helper.c.
18
10
19
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
11
This reduces the total cpu consumption of aa64_va_parameter in a
20
Message-id: 20170226200142.31169-1-krzk@kernel.org
12
kernel boot plus a kvm guest kernel boot from 3% to 0.5%.
13
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20200216194343.21331-5-richard.henderson@linaro.org
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
18
---
24
hw/misc/Makefile.objs | 2 +-
19
target/arm/internals.h | 3 --
25
hw/arm/exynos4210.c | 6 ++
20
target/arm/helper.c | 68 +++++++++++++++++++++++-------------------
26
hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++
21
2 files changed, 37 insertions(+), 34 deletions(-)
27
3 files changed, 171 insertions(+), 1 deletion(-)
28
create mode 100644 hw/misc/exynos4210_clk.c
29
22
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
23
diff --git a/target/arm/internals.h b/target/arm/internals.h
31
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/misc/Makefile.objs
25
--- a/target/arm/internals.h
33
+++ b/hw/misc/Makefile.objs
26
+++ b/target/arm/internals.h
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o
27
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVAParameters {
35
obj-$(CONFIG_REALVIEW) += arm_sysctl.o
28
unsigned tsz : 8;
36
obj-$(CONFIG_NSERIES) += cbus.o
29
unsigned select : 1;
37
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
30
bool tbi : 1;
38
-obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
31
- bool tbid : 1;
39
+obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o exynos4210_clk.o
32
bool epd : 1;
40
obj-$(CONFIG_IMX) += imx_ccm.o
33
bool hpd : 1;
41
obj-$(CONFIG_IMX) += imx31_ccm.o
34
bool using16k : 1;
42
obj-$(CONFIG_IMX) += imx25_ccm.o
35
bool using64k : 1;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
} ARMVAParameters;
37
38
-ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
39
- ARMMMUIdx mmu_idx);
40
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
41
ARMMMUIdx mmu_idx, bool data);
42
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
45
--- a/target/arm/helper.c
46
+++ b/hw/arm/exynos4210.c
46
+++ b/target/arm/helper.c
47
@@ -XXX,XX +XXX,XX @@
47
@@ -XXX,XX +XXX,XX @@ static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
48
#include "qemu/osdep.h"
48
}
49
#include "qapi/error.h"
49
#endif /* !CONFIG_USER_ONLY */
50
#include "qemu-common.h"
50
51
+#include "qemu/log.h"
51
-ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
52
#include "cpu.h"
52
- ARMMMUIdx mmu_idx)
53
#include "hw/boards.h"
53
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
54
#include "sysemu/sysemu.h"
55
@@ -XXX,XX +XXX,XX @@
56
/* PMU SFR base address */
57
#define EXYNOS4210_PMU_BASE_ADDR 0x10020000
58
59
+/* Clock controller SFR base address */
60
+#define EXYNOS4210_CLK_BASE_ADDR 0x10030000
61
+
62
/* Display controllers (FIMD) */
63
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
64
65
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
66
*/
67
sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
68
69
+ sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL);
70
+
71
/* PWM */
72
sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
73
s->irq_table[exynos4210_get_irq(22, 0)],
74
diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/hw/misc/exynos4210_clk.c
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * Exynos4210 Clock Controller Emulation
82
+ *
83
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ *
95
+ * You should have received a copy of the GNU General Public License along
96
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/log.h"
102
+
103
+#define TYPE_EXYNOS4210_CLK "exynos4210.clk"
104
+#define EXYNOS4210_CLK(obj) \
105
+ OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK)
106
+
107
+#define CLK_PLL_LOCKED BIT(29)
108
+
109
+#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104
110
+
111
+typedef struct Exynos4210Reg {
112
+ const char *name; /* for debug only */
113
+ uint32_t offset;
114
+ uint32_t reset_value;
115
+} Exynos4210Reg;
116
+
117
+/* Clock controller register base: 0x10030000 */
118
+static const Exynos4210Reg exynos4210_clk_regs[] = {
119
+ {"EPLL_LOCK", 0xc010, 0x00000fff},
120
+ {"VPLL_LOCK", 0xc020, 0x00000fff},
121
+ {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED},
122
+ {"EPLL_CON1", 0xc114, 0x00000000},
123
+ {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED},
124
+ {"VPLL_CON1", 0xc124, 0x66010464},
125
+ {"APLL_LOCK", 0x14000, 0x00000fff},
126
+ {"MPLL_LOCK", 0x14004, 0x00000fff},
127
+ {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED},
128
+ {"APLL_CON1", 0x14104, 0x0000001c},
129
+ {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED},
130
+ {"MPLL_CON1", 0x1410c, 0x0000001c},
131
+};
132
+
133
+#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs)
134
+
135
+typedef struct Exynos4210ClkState {
136
+ SysBusDevice parent_obj;
137
+
138
+ MemoryRegion iomem;
139
+ uint32_t reg[EXYNOS4210_REGS_NUM];
140
+} Exynos4210ClkState;
141
+
142
+static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset,
143
+ unsigned size)
144
+{
54
+{
145
+ const Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
55
+ if (regime_has_2_ranges(mmu_idx)) {
146
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
56
+ return extract64(tcr, 37, 2);
147
+ unsigned int i;
57
+ } else if (mmu_idx == ARMMMUIdx_Stage2) {
148
+
58
+ return 0; /* VTCR_EL2 */
149
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
59
+ } else {
150
+ if (regs->offset == offset) {
60
+ return extract32(tcr, 20, 1);
151
+ return s->reg[i];
152
+ }
153
+ regs++;
154
+ }
155
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n",
156
+ __func__, (uint32_t)offset);
157
+ return 0;
158
+}
159
+
160
+static void exynos4210_clk_write(void *opaque, hwaddr offset,
161
+ uint64_t val, unsigned size)
162
+{
163
+ Exynos4210ClkState *s = (Exynos4210ClkState *)opaque;
164
+ const Exynos4210Reg *regs = exynos4210_clk_regs;
165
+ unsigned int i;
166
+
167
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
168
+ if (regs->offset == offset) {
169
+ s->reg[i] = val;
170
+ return;
171
+ }
172
+ regs++;
173
+ }
174
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n",
175
+ __func__, (uint32_t)offset);
176
+}
177
+
178
+static const MemoryRegionOps exynos4210_clk_ops = {
179
+ .read = exynos4210_clk_read,
180
+ .write = exynos4210_clk_write,
181
+ .endianness = DEVICE_NATIVE_ENDIAN,
182
+ .valid = {
183
+ .min_access_size = 4,
184
+ .max_access_size = 4,
185
+ .unaligned = false
186
+ }
187
+};
188
+
189
+static void exynos4210_clk_reset(DeviceState *dev)
190
+{
191
+ Exynos4210ClkState *s = EXYNOS4210_CLK(dev);
192
+ unsigned int i;
193
+
194
+ /* Set default values for registers */
195
+ for (i = 0; i < EXYNOS4210_REGS_NUM; i++) {
196
+ s->reg[i] = exynos4210_clk_regs[i].reset_value;
197
+ }
61
+ }
198
+}
62
+}
199
+
63
+
200
+static void exynos4210_clk_init(Object *obj)
64
+static int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
201
+{
65
+{
202
+ Exynos4210ClkState *s = EXYNOS4210_CLK(obj);
66
+ if (regime_has_2_ranges(mmu_idx)) {
203
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
67
+ return extract64(tcr, 51, 2);
204
+
68
+ } else if (mmu_idx == ARMMMUIdx_Stage2) {
205
+ /* memory mapping */
69
+ return 0; /* VTCR_EL2 */
206
+ memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s,
70
+ } else {
207
+ TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZE);
71
+ return extract32(tcr, 29, 1);
208
+ sysbus_init_mmio(dev, &s->iomem);
72
+ }
209
+}
73
+}
210
+
74
+
211
+static const VMStateDescription exynos4210_clk_vmstate = {
75
+ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
212
+ .name = TYPE_EXYNOS4210_CLK,
76
+ ARMMMUIdx mmu_idx, bool data)
213
+ .version_id = 1,
77
{
214
+ .minimum_version_id = 1,
78
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
215
+ .fields = (VMStateField[]) {
79
- bool tbi, tbid, epd, hpd, using16k, using64k;
216
+ VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM),
80
- int select, tsz;
217
+ VMSTATE_END_OF_LIST()
81
+ bool epd, hpd, using16k, using64k;
82
+ int select, tsz, tbi;
83
84
if (!regime_has_2_ranges(mmu_idx)) {
85
select = 0;
86
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
87
using16k = extract32(tcr, 15, 1);
88
if (mmu_idx == ARMMMUIdx_Stage2) {
89
/* VTCR_EL2 */
90
- tbi = tbid = hpd = false;
91
+ hpd = false;
92
} else {
93
- tbi = extract32(tcr, 20, 1);
94
hpd = extract32(tcr, 24, 1);
95
- tbid = extract32(tcr, 29, 1);
96
}
97
epd = false;
98
} else {
99
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
100
epd = extract32(tcr, 7, 1);
101
using64k = extract32(tcr, 14, 1);
102
using16k = extract32(tcr, 15, 1);
103
- tbi = extract64(tcr, 37, 1);
104
hpd = extract64(tcr, 41, 1);
105
- tbid = extract64(tcr, 51, 1);
106
} else {
107
int tg = extract32(tcr, 30, 2);
108
using16k = tg == 1;
109
using64k = tg == 3;
110
tsz = extract32(tcr, 16, 6);
111
epd = extract32(tcr, 23, 1);
112
- tbi = extract64(tcr, 38, 1);
113
hpd = extract64(tcr, 42, 1);
114
- tbid = extract64(tcr, 52, 1);
115
}
116
}
117
tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
118
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
119
120
+ /* Present TBI as a composite with TBID. */
121
+ tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
122
+ if (!data) {
123
+ tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
218
+ }
124
+ }
219
+};
125
+ tbi = (tbi >> select) & 1;
220
+
126
+
221
+static void exynos4210_clk_class_init(ObjectClass *klass, void *data)
127
return (ARMVAParameters) {
222
+{
128
.tsz = tsz,
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
129
.select = select,
224
+
130
.tbi = tbi,
225
+ dc->reset = exynos4210_clk_reset;
131
- .tbid = tbid,
226
+ dc->vmsd = &exynos4210_clk_vmstate;
132
.epd = epd,
227
+}
133
.hpd = hpd,
228
+
134
.using16k = using16k,
229
+static const TypeInfo exynos4210_clk_info = {
135
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters_both(CPUARMState *env, uint64_t va,
230
+ .name = TYPE_EXYNOS4210_CLK,
136
};
231
+ .parent = TYPE_SYS_BUS_DEVICE,
137
}
232
+ .instance_size = sizeof(Exynos4210ClkState),
138
233
+ .instance_init = exynos4210_clk_init,
139
-ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
234
+ .class_init = exynos4210_clk_class_init,
140
- ARMMMUIdx mmu_idx, bool data)
235
+};
141
-{
236
+
142
- ARMVAParameters ret = aa64_va_parameters_both(env, va, mmu_idx);
237
+static void exynos4210_clk_register(void)
143
-
238
+{
144
- /* Present TBI as a composite with TBID. */
239
+ qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n");
145
- ret.tbi &= (data || !ret.tbid);
240
+ type_register_static(&exynos4210_clk_info);
146
- return ret;
241
+}
147
-}
242
+
148
-
243
+type_init(exynos4210_clk_register)
149
#ifndef CONFIG_USER_ONLY
150
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
151
ARMMMUIdx mmu_idx)
152
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
153
{
154
uint32_t flags = rebuild_hflags_aprofile(env);
155
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
156
- ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
157
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
158
uint64_t sctlr;
159
int tbii, tbid;
160
161
flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
162
163
/* Get control bits for tagged addresses. */
164
- if (regime_has_2_ranges(mmu_idx)) {
165
- ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
166
- tbid = (p1.tbi << 1) | p0.tbi;
167
- tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
168
- } else {
169
- tbid = p0.tbi;
170
- tbii = tbid & !p0.tbid;
171
- }
172
+ tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
173
+ tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
174
175
flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
176
flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
244
--
177
--
245
2.7.4
178
2.20.1
246
179
247
180
diff view generated by jsdifflib
1
M profile doesn't implement ARM, and the architecturally required
1
Enforce a convention that an isar_feature function that tests a
2
behaviour for attempts to execute with the Thumb bit clear is to
2
32-bit ID register always has _aa32_ in its name, and one that
3
generate a UsageFault with the CFSR INVSTATE bit set. We were
3
tests a 64-bit ID register always has _aa64_ in its name.
4
incorrectly implementing this as generating an UNDEFINSTR UsageFault;
4
We already follow this except for three cases: thumb_div,
5
fix this.
5
arm_div and jazelle, which all need _aa32_ adding.
6
6
7
(As noted in the comment, isar_feature_aa32_fp16_arith()
8
is an exception in that it currently tests ID_AA64PFR0_EL1,
9
but will switch to MVFR1 once we've properly implemented
10
FP16 for AArch32.)
11
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Message-id: 20200214175116.9164-2-peter.maydell@linaro.org
9
---
16
---
10
target/arm/cpu.h | 1 +
17
target/arm/cpu.h | 13 ++++++++++---
11
linux-user/main.c | 1 +
18
target/arm/internals.h | 2 +-
12
target/arm/helper.c | 4 ++++
19
linux-user/elfload.c | 4 ++--
13
target/arm/translate.c | 8 ++++++--
20
target/arm/cpu.c | 6 ++++--
14
4 files changed, 12 insertions(+), 2 deletions(-)
21
target/arm/helper.c | 2 +-
22
target/arm/translate.c | 6 +++---
23
6 files changed, 21 insertions(+), 12 deletions(-)
15
24
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
27
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
21
#define EXCP_VFIQ 15
30
/* Shared between translate-sve.c and sve_helper.c. */
22
#define EXCP_SEMIHOST 16 /* semihosting call */
31
extern const uint64_t pred_esz_masks[4];
23
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
32
24
+#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
33
+/*
25
34
+ * Naming convention for isar_feature functions:
26
#define ARMV7M_EXCP_RESET 1
35
+ * Functions which test 32-bit ID registers should have _aa32_ in
27
#define ARMV7M_EXCP_NMI 2
36
+ * their name. Functions which test 64-bit ID registers should have
28
diff --git a/linux-user/main.c b/linux-user/main.c
37
+ * _aa64_ in their name.
38
+ */
39
+
40
/*
41
* 32-bit feature tests via id registers.
42
*/
43
-static inline bool isar_feature_thumb_div(const ARMISARegisters *id)
44
+static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id)
45
{
46
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0;
47
}
48
49
-static inline bool isar_feature_arm_div(const ARMISARegisters *id)
50
+static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
51
{
52
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
53
}
54
55
-static inline bool isar_feature_jazelle(const ARMISARegisters *id)
56
+static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
57
{
58
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
59
}
60
diff --git a/target/arm/internals.h b/target/arm/internals.h
29
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
30
--- a/linux-user/main.c
62
--- a/target/arm/internals.h
31
+++ b/linux-user/main.c
63
+++ b/target/arm/internals.h
32
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
64
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
33
switch(trapnr) {
65
if ((features >> ARM_FEATURE_THUMB2) & 1) {
34
case EXCP_UDEF:
66
valid |= CPSR_IT;
35
case EXCP_NOCP:
67
}
36
+ case EXCP_INVSTATE:
68
- if (isar_feature_jazelle(id)) {
37
{
69
+ if (isar_feature_aa32_jazelle(id)) {
38
TaskState *ts = cs->opaque;
70
valid |= CPSR_J;
39
uint32_t opcode;
71
}
72
if (isar_feature_aa32_pan(id)) {
73
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/linux-user/elfload.c
76
+++ b/linux-user/elfload.c
77
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
78
GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
79
GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
80
GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4);
81
- GET_FEATURE_ID(arm_div, ARM_HWCAP_ARM_IDIVA);
82
- GET_FEATURE_ID(thumb_div, ARM_HWCAP_ARM_IDIVT);
83
+ GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
84
+ GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
85
/* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c.
86
* Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of
87
* ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated
88
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/cpu.c
91
+++ b/target/arm/cpu.c
92
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
93
* Presence of EL2 itself is ARM_FEATURE_EL2, and of the
94
* Security Extensions is ARM_FEATURE_EL3.
95
*/
96
- assert(!tcg_enabled() || no_aa32 || cpu_isar_feature(arm_div, cpu));
97
+ assert(!tcg_enabled() || no_aa32 ||
98
+ cpu_isar_feature(aa32_arm_div, cpu));
99
set_feature(env, ARM_FEATURE_LPAE);
100
set_feature(env, ARM_FEATURE_V7);
101
}
102
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
103
if (arm_feature(env, ARM_FEATURE_V6)) {
104
set_feature(env, ARM_FEATURE_V5);
105
if (!arm_feature(env, ARM_FEATURE_M)) {
106
- assert(!tcg_enabled() || no_aa32 || cpu_isar_feature(jazelle, cpu));
107
+ assert(!tcg_enabled() || no_aa32 ||
108
+ cpu_isar_feature(aa32_jazelle, cpu));
109
set_feature(env, ARM_FEATURE_AUXCR);
110
}
111
}
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
112
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/helper.c
114
--- a/target/arm/helper.c
43
+++ b/target/arm/helper.c
115
+++ b/target/arm/helper.c
44
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
116
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
45
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
117
if (arm_feature(env, ARM_FEATURE_LPAE)) {
46
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
118
define_arm_cp_regs(cpu, lpae_cp_reginfo);
47
break;
119
}
48
+ case EXCP_INVSTATE:
120
- if (cpu_isar_feature(jazelle, cpu)) {
49
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
121
+ if (cpu_isar_feature(aa32_jazelle, cpu)) {
50
+ env->v7m.cfsr |= R_V7M_CFSR_INVSTATE_MASK;
122
define_arm_cp_regs(cpu, jazelle_regs);
51
+ break;
123
}
52
case EXCP_SWI:
124
/* Slightly awkwardly, the OMAP and StrongARM cores need all of
53
/* The PC already points to the next instruction. */
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
55
diff --git a/target/arm/translate.c b/target/arm/translate.c
125
diff --git a/target/arm/translate.c b/target/arm/translate.c
56
index XXXXXXX..XXXXXXX 100644
126
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate.c
127
--- a/target/arm/translate.c
58
+++ b/target/arm/translate.c
128
+++ b/target/arm/translate.c
59
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
129
@@ -XXX,XX +XXX,XX @@
60
TCGv_i32 addr;
130
#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
61
TCGv_i64 tmp64;
131
/* currently all emulated v5 cores are also v5TE, so don't bother */
62
132
#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
63
- /* M variants do not implement ARM mode. */
133
-#define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
64
+ /* M variants do not implement ARM mode; this must raise the INVSTATE
134
+#define ENABLE_ARCH_5J dc_isar_feature(aa32_jazelle, s)
65
+ * UsageFault exception.
135
#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
66
+ */
136
#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
67
if (arm_dc_feature(s, ARM_FEATURE_M)) {
137
#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
68
- goto illegal_op;
138
@@ -XXX,XX +XXX,XX @@ static bool op_div(DisasContext *s, arg_rrr *a, bool u)
69
+ gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
139
TCGv_i32 t1, t2;
70
+ default_exception_el(s));
140
71
+ return;
141
if (s->thumb
142
- ? !dc_isar_feature(thumb_div, s)
143
- : !dc_isar_feature(arm_div, s)) {
144
+ ? !dc_isar_feature(aa32_thumb_div, s)
145
+ : !dc_isar_feature(aa32_arm_div, s)) {
146
return false;
72
}
147
}
73
cond = insn >> 28;
148
74
if (cond == 0xf){
75
--
149
--
76
2.7.4
150
2.20.1
77
151
78
152
diff view generated by jsdifflib
1
Add a state field for the v7M PRIGROUP register and implent
1
In take_aarch32_exception(), we know we are dealing with a CPU that
2
reading and writing it. The current NVIC doesn't honour
2
has AArch32, so the right isar_feature test is aa32_pan, not aa64_pan.
3
the values written, but the new version will.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20200214175116.9164-3-peter.maydell@linaro.org
8
---
7
---
9
hw/intc/armv7m_nvic.c | 14 ++++++++------
8
target/arm/helper.c | 2 +-
10
1 file changed, 8 insertions(+), 6 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
10
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
13
--- a/target/arm/helper.c
15
+++ b/hw/intc/armv7m_nvic.c
14
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
17
typedef struct NVICState {
16
env->elr_el[2] = env->regs[15];
18
GICState gic;
17
} else {
19
ARMCPU *cpu;
18
/* CPSR.PAN is normally preserved preserved unless... */
20
+
19
- if (cpu_isar_feature(aa64_pan, env_archcpu(env))) {
21
+ uint32_t prigroup;
20
+ if (cpu_isar_feature(aa32_pan, env_archcpu(env))) {
22
+
21
switch (new_el) {
23
struct {
22
case 3:
24
uint32_t control;
23
if (!arm_is_secure_below_el3(env)) {
25
uint32_t reload;
26
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
27
case 0xd08: /* Vector Table Offset. */
28
return cpu->env.v7m.vecbase;
29
case 0xd0c: /* Application Interrupt/Reset Control. */
30
- return 0xfa050000;
31
+ return 0xfa050000 | (s->prigroup << 8);
32
case 0xd10: /* System Control. */
33
/* TODO: Implement SLEEPONEXIT. */
34
return 0;
35
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
36
if (value & 1) {
37
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
38
}
39
- if (value & 0x700) {
40
- qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
41
- }
42
+ s->prigroup = extract32(value, 8, 3);
43
}
44
break;
45
case 0xd10: /* System Control. */
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
47
48
static const VMStateDescription vmstate_nvic = {
49
.name = "armv7m_nvic",
50
- .version_id = 1,
51
- .minimum_version_id = 1,
52
+ .version_id = 2,
53
+ .minimum_version_id = 2,
54
.fields = (VMStateField[]) {
55
VMSTATE_UINT32(systick.control, NVICState),
56
VMSTATE_UINT32(systick.reload, NVICState),
57
VMSTATE_INT64(systick.tick, NVICState),
58
VMSTATE_TIMER_PTR(systick.timer, NVICState),
59
+ VMSTATE_UINT32(prigroup, NVICState),
60
VMSTATE_END_OF_LIST()
61
}
62
};
63
--
24
--
64
2.7.4
25
2.20.1
65
26
66
27
diff view generated by jsdifflib
New patch
1
Our current usage of the isar_feature feature tests almost always
2
uses an _aa32_ test when the code path is known to be AArch32
3
specific and an _aa64_ test when the code path is known to be
4
AArch64 specific. There is just one exception: in the vfp_set_fpscr
5
helper we check aa64_fp16 to determine whether the FZ16 bit in
6
the FP(S)CR exists, but this code is also used for AArch32.
7
There are other places in future where we're likely to want
8
a general "does this feature exist for either AArch32 or
9
AArch64" check (typically where architecturally the feature exists
10
for both CPU states if it exists at all, but the CPU might be
11
AArch32-only or AArch64-only, and so only have one set of ID
12
registers).
1
13
14
Introduce a new category of isar_feature_* functions:
15
isar_feature_any_foo() should be tested when what we want to
16
know is "does this feature exist for either AArch32 or AArch64",
17
and always returns the logical OR of isar_feature_aa32_foo()
18
and isar_feature_aa64_foo().
19
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Message-id: 20200214175116.9164-4-peter.maydell@linaro.org
24
---
25
target/arm/cpu.h | 19 ++++++++++++++++++-
26
target/arm/vfp_helper.c | 2 +-
27
2 files changed, 19 insertions(+), 2 deletions(-)
28
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
32
+++ b/target/arm/cpu.h
33
@@ -XXX,XX +XXX,XX @@ extern const uint64_t pred_esz_masks[4];
34
* Naming convention for isar_feature functions:
35
* Functions which test 32-bit ID registers should have _aa32_ in
36
* their name. Functions which test 64-bit ID registers should have
37
- * _aa64_ in their name.
38
+ * _aa64_ in their name. These must only be used in code where we
39
+ * know for certain that the CPU has AArch32 or AArch64 respectively
40
+ * or where the correct answer for a CPU which doesn't implement that
41
+ * CPU state is "false" (eg when generating A32 or A64 code, if adding
42
+ * system registers that are specific to that CPU state, for "should
43
+ * we let this system register bit be set" tests where the 32-bit
44
+ * flavour of the register doesn't have the bit, and so on).
45
+ * Functions which simply ask "does this feature exist at all" have
46
+ * _any_ in their name, and always return the logical OR of the _aa64_
47
+ * and the _aa32_ function.
48
*/
49
50
/*
51
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
52
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
53
}
54
55
+/*
56
+ * Feature tests for "does this exist in either 32-bit or 64-bit?"
57
+ */
58
+static inline bool isar_feature_any_fp16(const ARMISARegisters *id)
59
+{
60
+ return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id);
61
+}
62
+
63
/*
64
* Forward to the above feature tests given an ARMCPU pointer.
65
*/
66
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/vfp_helper.c
69
+++ b/target/arm/vfp_helper.c
70
@@ -XXX,XX +XXX,XX @@ uint32_t vfp_get_fpscr(CPUARMState *env)
71
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
72
{
73
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
74
- if (!cpu_isar_feature(aa64_fp16, env_archcpu(env))) {
75
+ if (!cpu_isar_feature(any_fp16, env_archcpu(env))) {
76
val &= ~FPCR_FZ16;
77
}
78
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
New patch
1
Instead of open-coding "ARM_FEATURE_AARCH64 ? aa64_predinv: aa32_predinv",
2
define and use an any_predinv isar_feature test function.
1
3
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20200214175116.9164-5-peter.maydell@linaro.org
8
---
9
target/arm/cpu.h | 5 +++++
10
target/arm/helper.c | 9 +--------
11
2 files changed, 6 insertions(+), 8 deletions(-)
12
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_fp16(const ARMISARegisters *id)
18
return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id);
19
}
20
21
+static inline bool isar_feature_any_predinv(const ARMISARegisters *id)
22
+{
23
+ return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id);
24
+}
25
+
26
/*
27
* Forward to the above feature tests given an ARMCPU pointer.
28
*/
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper.c
32
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
34
#endif /*CONFIG_USER_ONLY*/
35
#endif
36
37
- /*
38
- * While all v8.0 cpus support aarch64, QEMU does have configurations
39
- * that do not set ID_AA64ISAR1, e.g. user-only qemu-arm -cpu max,
40
- * which will set ID_ISAR6.
41
- */
42
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
43
- ? cpu_isar_feature(aa64_predinv, cpu)
44
- : cpu_isar_feature(aa32_predinv, cpu)) {
45
+ if (cpu_isar_feature(any_predinv, cpu)) {
46
define_arm_cp_regs(cpu, predinv_reginfo);
47
}
48
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
New patch
1
1
Pull the code that defines the various PMU registers out
2
into its own function, matching the pattern we have
3
already for the debug registers.
4
5
Apart from one style fix to a multi-line comment, this
6
is purely movement of code with no changes to it.
7
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20200214175116.9164-6-peter.maydell@linaro.org
12
---
13
target/arm/helper.c | 158 +++++++++++++++++++++++---------------------
14
1 file changed, 82 insertions(+), 76 deletions(-)
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
21
}
22
}
23
24
+static void define_pmu_regs(ARMCPU *cpu)
25
+{
26
+ /*
27
+ * v7 performance monitor control register: same implementor
28
+ * field as main ID register, and we implement four counters in
29
+ * addition to the cycle count register.
30
+ */
31
+ unsigned int i, pmcrn = 4;
32
+ ARMCPRegInfo pmcr = {
33
+ .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
34
+ .access = PL0_RW,
35
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
36
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
37
+ .accessfn = pmreg_access, .writefn = pmcr_write,
38
+ .raw_writefn = raw_write,
39
+ };
40
+ ARMCPRegInfo pmcr64 = {
41
+ .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
43
+ .access = PL0_RW, .accessfn = pmreg_access,
44
+ .type = ARM_CP_IO,
45
+ .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
46
+ .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT),
47
+ .writefn = pmcr_write, .raw_writefn = raw_write,
48
+ };
49
+ define_one_arm_cp_reg(cpu, &pmcr);
50
+ define_one_arm_cp_reg(cpu, &pmcr64);
51
+ for (i = 0; i < pmcrn; i++) {
52
+ char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i);
53
+ char *pmevcntr_el0_name = g_strdup_printf("PMEVCNTR%d_EL0", i);
54
+ char *pmevtyper_name = g_strdup_printf("PMEVTYPER%d", i);
55
+ char *pmevtyper_el0_name = g_strdup_printf("PMEVTYPER%d_EL0", i);
56
+ ARMCPRegInfo pmev_regs[] = {
57
+ { .name = pmevcntr_name, .cp = 15, .crn = 14,
58
+ .crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
59
+ .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
60
+ .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
61
+ .accessfn = pmreg_access },
62
+ { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
63
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
64
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
65
+ .type = ARM_CP_IO,
66
+ .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
67
+ .raw_readfn = pmevcntr_rawread,
68
+ .raw_writefn = pmevcntr_rawwrite },
69
+ { .name = pmevtyper_name, .cp = 15, .crn = 14,
70
+ .crm = 12 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
71
+ .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
72
+ .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
73
+ .accessfn = pmreg_access },
74
+ { .name = pmevtyper_el0_name, .state = ARM_CP_STATE_AA64,
75
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 12 | (3 & (i >> 3)),
76
+ .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
77
+ .type = ARM_CP_IO,
78
+ .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
79
+ .raw_writefn = pmevtyper_rawwrite },
80
+ REGINFO_SENTINEL
81
+ };
82
+ define_arm_cp_regs(cpu, pmev_regs);
83
+ g_free(pmevcntr_name);
84
+ g_free(pmevcntr_el0_name);
85
+ g_free(pmevtyper_name);
86
+ g_free(pmevtyper_el0_name);
87
+ }
88
+ if (FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
89
+ FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) != 0xf) {
90
+ ARMCPRegInfo v81_pmu_regs[] = {
91
+ { .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
92
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
93
+ .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
94
+ .resetvalue = extract64(cpu->pmceid0, 32, 32) },
95
+ { .name = "PMCEID3", .state = ARM_CP_STATE_AA32,
96
+ .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
97
+ .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
98
+ .resetvalue = extract64(cpu->pmceid1, 32, 32) },
99
+ REGINFO_SENTINEL
100
+ };
101
+ define_arm_cp_regs(cpu, v81_pmu_regs);
102
+ }
103
+}
104
+
105
/* We don't know until after realize whether there's a GICv3
106
* attached, and that is what registers the gicv3 sysregs.
107
* So we have to fill in the GIC fields in ID_PFR/ID_PFR1_EL1/ID_AA64PFR0_EL1
108
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
109
define_arm_cp_regs(cpu, pmovsset_cp_reginfo);
110
}
111
if (arm_feature(env, ARM_FEATURE_V7)) {
112
- /* v7 performance monitor control register: same implementor
113
- * field as main ID register, and we implement four counters in
114
- * addition to the cycle count register.
115
- */
116
- unsigned int i, pmcrn = 4;
117
- ARMCPRegInfo pmcr = {
118
- .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
119
- .access = PL0_RW,
120
- .type = ARM_CP_IO | ARM_CP_ALIAS,
121
- .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
122
- .accessfn = pmreg_access, .writefn = pmcr_write,
123
- .raw_writefn = raw_write,
124
- };
125
- ARMCPRegInfo pmcr64 = {
126
- .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
127
- .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
128
- .access = PL0_RW, .accessfn = pmreg_access,
129
- .type = ARM_CP_IO,
130
- .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
131
- .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT),
132
- .writefn = pmcr_write, .raw_writefn = raw_write,
133
- };
134
- define_one_arm_cp_reg(cpu, &pmcr);
135
- define_one_arm_cp_reg(cpu, &pmcr64);
136
- for (i = 0; i < pmcrn; i++) {
137
- char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i);
138
- char *pmevcntr_el0_name = g_strdup_printf("PMEVCNTR%d_EL0", i);
139
- char *pmevtyper_name = g_strdup_printf("PMEVTYPER%d", i);
140
- char *pmevtyper_el0_name = g_strdup_printf("PMEVTYPER%d_EL0", i);
141
- ARMCPRegInfo pmev_regs[] = {
142
- { .name = pmevcntr_name, .cp = 15, .crn = 14,
143
- .crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
144
- .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
145
- .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
146
- .accessfn = pmreg_access },
147
- { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
148
- .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
149
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
150
- .type = ARM_CP_IO,
151
- .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
152
- .raw_readfn = pmevcntr_rawread,
153
- .raw_writefn = pmevcntr_rawwrite },
154
- { .name = pmevtyper_name, .cp = 15, .crn = 14,
155
- .crm = 12 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
156
- .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
157
- .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
158
- .accessfn = pmreg_access },
159
- { .name = pmevtyper_el0_name, .state = ARM_CP_STATE_AA64,
160
- .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 12 | (3 & (i >> 3)),
161
- .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
162
- .type = ARM_CP_IO,
163
- .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
164
- .raw_writefn = pmevtyper_rawwrite },
165
- REGINFO_SENTINEL
166
- };
167
- define_arm_cp_regs(cpu, pmev_regs);
168
- g_free(pmevcntr_name);
169
- g_free(pmevcntr_el0_name);
170
- g_free(pmevtyper_name);
171
- g_free(pmevtyper_el0_name);
172
- }
173
ARMCPRegInfo clidr = {
174
.name = "CLIDR", .state = ARM_CP_STATE_BOTH,
175
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
176
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
177
define_one_arm_cp_reg(cpu, &clidr);
178
define_arm_cp_regs(cpu, v7_cp_reginfo);
179
define_debug_regs(cpu);
180
+ define_pmu_regs(cpu);
181
} else {
182
define_arm_cp_regs(cpu, not_v7_cp_reginfo);
183
}
184
- if (FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
185
- FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) != 0xf) {
186
- ARMCPRegInfo v81_pmu_regs[] = {
187
- { .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
188
- .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
189
- .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
190
- .resetvalue = extract64(cpu->pmceid0, 32, 32) },
191
- { .name = "PMCEID3", .state = ARM_CP_STATE_AA32,
192
- .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
193
- .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
194
- .resetvalue = extract64(cpu->pmceid1, 32, 32) },
195
- REGINFO_SENTINEL
196
- };
197
- define_arm_cp_regs(cpu, v81_pmu_regs);
198
- }
199
if (arm_feature(env, ARM_FEATURE_V8)) {
200
/* AArch64 ID registers, which all have impdef reset values.
201
* Note that within the ID register ranges the unused slots
202
--
203
2.20.1
204
205
diff view generated by jsdifflib
New patch
1
Add FIELD() definitions for the ID_AA64DFR0_EL1 and use them
2
where we currently have hard-coded bit values.
1
3
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20200214175116.9164-7-peter.maydell@linaro.org
8
---
9
target/arm/cpu.h | 10 ++++++++++
10
target/arm/cpu.c | 2 +-
11
target/arm/helper.c | 6 +++---
12
3 files changed, 14 insertions(+), 4 deletions(-)
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR2, BBM, 52, 4)
19
FIELD(ID_AA64MMFR2, EVT, 56, 4)
20
FIELD(ID_AA64MMFR2, E0PD, 60, 4)
21
22
+FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
23
+FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
24
+FIELD(ID_AA64DFR0, PMUVER, 8, 4)
25
+FIELD(ID_AA64DFR0, BRPS, 12, 4)
26
+FIELD(ID_AA64DFR0, WRPS, 20, 4)
27
+FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
28
+FIELD(ID_AA64DFR0, PMSVER, 32, 4)
29
+FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
30
+FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
31
+
32
FIELD(ID_DFR0, COPDBG, 0, 4)
33
FIELD(ID_DFR0, COPSDBG, 4, 4)
34
FIELD(ID_DFR0, MMAPDBG, 8, 4)
35
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.c
38
+++ b/target/arm/cpu.c
39
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
40
cpu);
41
#endif
42
} else {
43
- cpu->id_aa64dfr0 &= ~0xf00;
44
+ cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
45
cpu->id_dfr0 &= ~(0xf << 24);
46
cpu->pmceid0 = 0;
47
cpu->pmceid1 = 0;
48
diff --git a/target/arm/helper.c b/target/arm/helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/helper.c
51
+++ b/target/arm/helper.c
52
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
53
* check that if they both exist then they agree.
54
*/
55
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
56
- assert(extract32(cpu->id_aa64dfr0, 12, 4) == brps);
57
- assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps);
58
- assert(extract32(cpu->id_aa64dfr0, 28, 4) == ctx_cmps);
59
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
60
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
61
+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps);
62
}
63
64
define_one_arm_cp_reg(cpu, &dbgdidr);
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
New patch
1
We already define FIELD macros for ID_DFR0, so use them in the
2
one place where we're doing direct bit value manipulation.
1
3
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20200214175116.9164-8-peter.maydell@linaro.org
8
---
9
target/arm/cpu.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
17
#endif
18
} else {
19
cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
20
- cpu->id_dfr0 &= ~(0xf << 24);
21
+ cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0);
22
cpu->pmceid0 = 0;
23
cpu->pmceid1 = 0;
24
}
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
Instead of open-coding a check on the ID_DFR0 PerfMon ID register
2
2
field, create a standardly-named isar_feature for "does AArch32 have
3
The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both
3
a v8.1 PMUv3" and use it.
4
documented as UNPREDICTABLE if you write a 1 to them when
4
5
the processor is not halted in Debug state (ie stopped
5
This entails moving the id_dfr0 field into the ARMISARegisters struct.
6
and under the control of an external JTAG debugger).
6
7
Since we don't implement Debug state or emulated JTAG
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
these bits are always UNPREDICTABLE for us. Instead of
9
logging them as unimplemented we can simply log writes
10
as guest errors and ignore them.
11
12
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
13
[PMM: change extracted from another patch; commit message
14
constructed from scratch]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20200214175116.9164-9-peter.maydell@linaro.org
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
10
---
19
hw/intc/armv7m_nvic.c | 8 ++++++--
11
target/arm/cpu.h | 9 ++++++++-
20
1 file changed, 6 insertions(+), 2 deletions(-)
12
hw/intc/armv7m_nvic.c | 2 +-
21
13
target/arm/cpu.c | 28 ++++++++++++++--------------
14
target/arm/cpu64.c | 6 +++---
15
target/arm/helper.c | 5 ++---
16
5 files changed, 28 insertions(+), 22 deletions(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
23
uint32_t mvfr0;
24
uint32_t mvfr1;
25
uint32_t mvfr2;
26
+ uint32_t id_dfr0;
27
uint64_t id_aa64isar0;
28
uint64_t id_aa64isar1;
29
uint64_t id_aa64pfr0;
30
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
31
uint32_t reset_sctlr;
32
uint32_t id_pfr0;
33
uint32_t id_pfr1;
34
- uint32_t id_dfr0;
35
uint64_t pmceid0;
36
uint64_t pmceid1;
37
uint32_t id_afr0;
38
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
39
return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
40
}
41
42
+static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id)
43
+{
44
+ /* 0xf means "non-standard IMPDEF PMU" */
45
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
46
+ FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
47
+}
48
+
49
/*
50
* 64-bit feature tests via id registers.
51
*/
22
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
52
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
23
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/armv7m_nvic.c
54
--- a/hw/intc/armv7m_nvic.c
25
+++ b/hw/intc/armv7m_nvic.c
55
+++ b/hw/intc/armv7m_nvic.c
26
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
56
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
27
qemu_irq_pulse(s->sysresetreq);
57
case 0xd44: /* PFR1. */
28
}
58
return cpu->id_pfr1;
29
if (value & 2) {
59
case 0xd48: /* DFR0. */
30
- qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
60
- return cpu->id_dfr0;
31
+ qemu_log_mask(LOG_GUEST_ERROR,
61
+ return cpu->isar.id_dfr0;
32
+ "Setting VECTCLRACTIVE when not in DEBUG mode "
62
case 0xd4c: /* AFR0. */
33
+ "is UNPREDICTABLE\n");
63
return cpu->id_afr0;
34
}
64
case 0xd50: /* MMFR0. */
35
if (value & 1) {
65
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
36
- qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
66
index XXXXXXX..XXXXXXX 100644
37
+ qemu_log_mask(LOG_GUEST_ERROR,
67
--- a/target/arm/cpu.c
38
+ "Setting VECTRESET when not in DEBUG mode "
68
+++ b/target/arm/cpu.c
39
+ "is UNPREDICTABLE\n");
69
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
40
}
70
#endif
41
s->prigroup = extract32(value, 8, 3);
71
} else {
42
nvic_irq_update(s);
72
cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
73
- cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0);
74
+ cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
75
cpu->pmceid0 = 0;
76
cpu->pmceid1 = 0;
77
}
78
@@ -XXX,XX +XXX,XX @@ static void arm1136_r2_initfn(Object *obj)
79
cpu->reset_sctlr = 0x00050078;
80
cpu->id_pfr0 = 0x111;
81
cpu->id_pfr1 = 0x1;
82
- cpu->id_dfr0 = 0x2;
83
+ cpu->isar.id_dfr0 = 0x2;
84
cpu->id_afr0 = 0x3;
85
cpu->id_mmfr0 = 0x01130003;
86
cpu->id_mmfr1 = 0x10030302;
87
@@ -XXX,XX +XXX,XX @@ static void arm1136_initfn(Object *obj)
88
cpu->reset_sctlr = 0x00050078;
89
cpu->id_pfr0 = 0x111;
90
cpu->id_pfr1 = 0x1;
91
- cpu->id_dfr0 = 0x2;
92
+ cpu->isar.id_dfr0 = 0x2;
93
cpu->id_afr0 = 0x3;
94
cpu->id_mmfr0 = 0x01130003;
95
cpu->id_mmfr1 = 0x10030302;
96
@@ -XXX,XX +XXX,XX @@ static void arm1176_initfn(Object *obj)
97
cpu->reset_sctlr = 0x00050078;
98
cpu->id_pfr0 = 0x111;
99
cpu->id_pfr1 = 0x11;
100
- cpu->id_dfr0 = 0x33;
101
+ cpu->isar.id_dfr0 = 0x33;
102
cpu->id_afr0 = 0;
103
cpu->id_mmfr0 = 0x01130003;
104
cpu->id_mmfr1 = 0x10030302;
105
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
106
cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */
107
cpu->id_pfr0 = 0x111;
108
cpu->id_pfr1 = 0x1;
109
- cpu->id_dfr0 = 0;
110
+ cpu->isar.id_dfr0 = 0;
111
cpu->id_afr0 = 0x2;
112
cpu->id_mmfr0 = 0x01100103;
113
cpu->id_mmfr1 = 0x10020302;
114
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
115
cpu->pmsav7_dregion = 8;
116
cpu->id_pfr0 = 0x00000030;
117
cpu->id_pfr1 = 0x00000200;
118
- cpu->id_dfr0 = 0x00100000;
119
+ cpu->isar.id_dfr0 = 0x00100000;
120
cpu->id_afr0 = 0x00000000;
121
cpu->id_mmfr0 = 0x00000030;
122
cpu->id_mmfr1 = 0x00000000;
123
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
124
cpu->isar.mvfr2 = 0x00000000;
125
cpu->id_pfr0 = 0x00000030;
126
cpu->id_pfr1 = 0x00000200;
127
- cpu->id_dfr0 = 0x00100000;
128
+ cpu->isar.id_dfr0 = 0x00100000;
129
cpu->id_afr0 = 0x00000000;
130
cpu->id_mmfr0 = 0x00000030;
131
cpu->id_mmfr1 = 0x00000000;
132
@@ -XXX,XX +XXX,XX @@ static void cortex_m7_initfn(Object *obj)
133
cpu->isar.mvfr2 = 0x00000040;
134
cpu->id_pfr0 = 0x00000030;
135
cpu->id_pfr1 = 0x00000200;
136
- cpu->id_dfr0 = 0x00100000;
137
+ cpu->isar.id_dfr0 = 0x00100000;
138
cpu->id_afr0 = 0x00000000;
139
cpu->id_mmfr0 = 0x00100030;
140
cpu->id_mmfr1 = 0x00000000;
141
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
142
cpu->isar.mvfr2 = 0x00000040;
143
cpu->id_pfr0 = 0x00000030;
144
cpu->id_pfr1 = 0x00000210;
145
- cpu->id_dfr0 = 0x00200000;
146
+ cpu->isar.id_dfr0 = 0x00200000;
147
cpu->id_afr0 = 0x00000000;
148
cpu->id_mmfr0 = 0x00101F40;
149
cpu->id_mmfr1 = 0x00000000;
150
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
151
cpu->midr = 0x411fc153; /* r1p3 */
152
cpu->id_pfr0 = 0x0131;
153
cpu->id_pfr1 = 0x001;
154
- cpu->id_dfr0 = 0x010400;
155
+ cpu->isar.id_dfr0 = 0x010400;
156
cpu->id_afr0 = 0x0;
157
cpu->id_mmfr0 = 0x0210030;
158
cpu->id_mmfr1 = 0x00000000;
159
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
160
cpu->reset_sctlr = 0x00c50078;
161
cpu->id_pfr0 = 0x1031;
162
cpu->id_pfr1 = 0x11;
163
- cpu->id_dfr0 = 0x400;
164
+ cpu->isar.id_dfr0 = 0x400;
165
cpu->id_afr0 = 0;
166
cpu->id_mmfr0 = 0x31100003;
167
cpu->id_mmfr1 = 0x20000000;
168
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
169
cpu->reset_sctlr = 0x00c50078;
170
cpu->id_pfr0 = 0x1031;
171
cpu->id_pfr1 = 0x11;
172
- cpu->id_dfr0 = 0x000;
173
+ cpu->isar.id_dfr0 = 0x000;
174
cpu->id_afr0 = 0;
175
cpu->id_mmfr0 = 0x00100103;
176
cpu->id_mmfr1 = 0x20000000;
177
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
178
cpu->reset_sctlr = 0x00c50078;
179
cpu->id_pfr0 = 0x00001131;
180
cpu->id_pfr1 = 0x00011011;
181
- cpu->id_dfr0 = 0x02010555;
182
+ cpu->isar.id_dfr0 = 0x02010555;
183
cpu->id_afr0 = 0x00000000;
184
cpu->id_mmfr0 = 0x10101105;
185
cpu->id_mmfr1 = 0x40000000;
186
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
187
cpu->reset_sctlr = 0x00c50078;
188
cpu->id_pfr0 = 0x00001131;
189
cpu->id_pfr1 = 0x00011011;
190
- cpu->id_dfr0 = 0x02010555;
191
+ cpu->isar.id_dfr0 = 0x02010555;
192
cpu->id_afr0 = 0x00000000;
193
cpu->id_mmfr0 = 0x10201105;
194
cpu->id_mmfr1 = 0x20000000;
195
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/target/arm/cpu64.c
198
+++ b/target/arm/cpu64.c
199
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
200
cpu->reset_sctlr = 0x00c50838;
201
cpu->id_pfr0 = 0x00000131;
202
cpu->id_pfr1 = 0x00011011;
203
- cpu->id_dfr0 = 0x03010066;
204
+ cpu->isar.id_dfr0 = 0x03010066;
205
cpu->id_afr0 = 0x00000000;
206
cpu->id_mmfr0 = 0x10101105;
207
cpu->id_mmfr1 = 0x40000000;
208
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
209
cpu->reset_sctlr = 0x00c50838;
210
cpu->id_pfr0 = 0x00000131;
211
cpu->id_pfr1 = 0x00011011;
212
- cpu->id_dfr0 = 0x03010066;
213
+ cpu->isar.id_dfr0 = 0x03010066;
214
cpu->id_afr0 = 0x00000000;
215
cpu->id_mmfr0 = 0x10101105;
216
cpu->id_mmfr1 = 0x40000000;
217
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
218
cpu->reset_sctlr = 0x00c50838;
219
cpu->id_pfr0 = 0x00000131;
220
cpu->id_pfr1 = 0x00011011;
221
- cpu->id_dfr0 = 0x03010066;
222
+ cpu->isar.id_dfr0 = 0x03010066;
223
cpu->id_afr0 = 0x00000000;
224
cpu->id_mmfr0 = 0x10201105;
225
cpu->id_mmfr1 = 0x40000000;
226
diff --git a/target/arm/helper.c b/target/arm/helper.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/target/arm/helper.c
229
+++ b/target/arm/helper.c
230
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
231
g_free(pmevtyper_name);
232
g_free(pmevtyper_el0_name);
233
}
234
- if (FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
235
- FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) != 0xf) {
236
+ if (cpu_isar_feature(aa32_pmu_8_1, cpu)) {
237
ARMCPRegInfo v81_pmu_regs[] = {
238
{ .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
239
.cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
240
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
241
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2,
242
.access = PL1_R, .type = ARM_CP_CONST,
243
.accessfn = access_aa32_tid3,
244
- .resetvalue = cpu->id_dfr0 },
245
+ .resetvalue = cpu->isar.id_dfr0 },
246
{ .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH,
247
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3,
248
.access = PL1_R, .type = ARM_CP_CONST,
43
--
249
--
44
2.7.4
250
2.20.1
45
251
46
252
diff view generated by jsdifflib
New patch
1
Add the 64-bit version of the "is this a v8.1 PMUv3?"
2
ID register check function, and the _any_ version that
3
checks for either AArch32 or AArch64 support. We'll use
4
this in a later commit.
1
5
6
We don't (yet) do any isar_feature checks on ID_AA64DFR1_EL1,
7
but we move id_aa64dfr1 into the ARMISARegisters struct with
8
id_aa64dfr0, for consistency.
9
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20200214175116.9164-10-peter.maydell@linaro.org
14
---
15
target/arm/cpu.h | 15 +++++++++++++--
16
target/arm/cpu.c | 3 ++-
17
target/arm/cpu64.c | 6 +++---
18
target/arm/helper.c | 12 +++++++-----
19
4 files changed, 25 insertions(+), 11 deletions(-)
20
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
26
uint64_t id_aa64mmfr0;
27
uint64_t id_aa64mmfr1;
28
uint64_t id_aa64mmfr2;
29
+ uint64_t id_aa64dfr0;
30
+ uint64_t id_aa64dfr1;
31
} isar;
32
uint32_t midr;
33
uint32_t revidr;
34
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
35
uint32_t id_mmfr2;
36
uint32_t id_mmfr3;
37
uint32_t id_mmfr4;
38
- uint64_t id_aa64dfr0;
39
- uint64_t id_aa64dfr1;
40
uint64_t id_aa64afr0;
41
uint64_t id_aa64afr1;
42
uint32_t dbgdidr;
43
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
44
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
45
}
46
47
+static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
48
+{
49
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 &&
50
+ FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
51
+}
52
+
53
/*
54
* Feature tests for "does this exist in either 32-bit or 64-bit?"
55
*/
56
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_predinv(const ARMISARegisters *id)
57
return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id);
58
}
59
60
+static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id)
61
+{
62
+ return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id);
63
+}
64
+
65
/*
66
* Forward to the above feature tests given an ARMCPU pointer.
67
*/
68
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/cpu.c
71
+++ b/target/arm/cpu.c
72
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
73
cpu);
74
#endif
75
} else {
76
- cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
77
+ cpu->isar.id_aa64dfr0 =
78
+ FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0);
79
cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0);
80
cpu->pmceid0 = 0;
81
cpu->pmceid1 = 0;
82
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/cpu64.c
85
+++ b/target/arm/cpu64.c
86
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
87
cpu->isar.id_isar5 = 0x00011121;
88
cpu->isar.id_isar6 = 0;
89
cpu->isar.id_aa64pfr0 = 0x00002222;
90
- cpu->id_aa64dfr0 = 0x10305106;
91
+ cpu->isar.id_aa64dfr0 = 0x10305106;
92
cpu->isar.id_aa64isar0 = 0x00011120;
93
cpu->isar.id_aa64mmfr0 = 0x00001124;
94
cpu->dbgdidr = 0x3516d000;
95
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
96
cpu->isar.id_isar5 = 0x00011121;
97
cpu->isar.id_isar6 = 0;
98
cpu->isar.id_aa64pfr0 = 0x00002222;
99
- cpu->id_aa64dfr0 = 0x10305106;
100
+ cpu->isar.id_aa64dfr0 = 0x10305106;
101
cpu->isar.id_aa64isar0 = 0x00011120;
102
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
103
cpu->dbgdidr = 0x3516d000;
104
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
105
cpu->isar.id_isar4 = 0x00011142;
106
cpu->isar.id_isar5 = 0x00011121;
107
cpu->isar.id_aa64pfr0 = 0x00002222;
108
- cpu->id_aa64dfr0 = 0x10305106;
109
+ cpu->isar.id_aa64dfr0 = 0x10305106;
110
cpu->isar.id_aa64isar0 = 0x00011120;
111
cpu->isar.id_aa64mmfr0 = 0x00001124;
112
cpu->dbgdidr = 0x3516d000;
113
diff --git a/target/arm/helper.c b/target/arm/helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/helper.c
116
+++ b/target/arm/helper.c
117
@@ -XXX,XX +XXX,XX @@
118
#include "hw/semihosting/semihost.h"
119
#include "sysemu/cpus.h"
120
#include "sysemu/kvm.h"
121
+#include "sysemu/tcg.h"
122
#include "qemu/range.h"
123
#include "qapi/qapi-commands-machine-target.h"
124
#include "qapi/error.h"
125
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
126
* check that if they both exist then they agree.
127
*/
128
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
129
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
130
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
131
- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps);
132
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
133
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
134
+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS)
135
+ == ctx_cmps);
136
}
137
138
define_one_arm_cp_reg(cpu, &dbgdidr);
139
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
140
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
141
.access = PL1_R, .type = ARM_CP_CONST,
142
.accessfn = access_aa64_tid3,
143
- .resetvalue = cpu->id_aa64dfr0 },
144
+ .resetvalue = cpu->isar.id_aa64dfr0 },
145
{ .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
146
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
147
.access = PL1_R, .type = ARM_CP_CONST,
148
.accessfn = access_aa64_tid3,
149
- .resetvalue = cpu->id_aa64dfr1 },
150
+ .resetvalue = cpu->isar.id_aa64dfr1 },
151
{ .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
152
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2,
153
.access = PL1_R, .type = ARM_CP_CONST,
154
--
155
2.20.1
156
157
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
The AArch32 DBGDIDR defines properties like the number of
2
breakpoints, watchpoints and context-matching comparators. On an
3
AArch64 CPU, the register may not even exist if AArch32 is not
4
supported at EL1.
2
5
3
Now that the NVIC is its own separate implementation, we can
6
Currently we hard-code use of DBGDIDR to identify the number of
4
clean up the GIC code by removing REV_NVIC and conditionals
7
breakpoints etc; this works for all our TCG CPUs, but will break if
5
which use it.
8
we ever add an AArch64-only CPU. We also have an assert() that the
9
AArch32 and AArch64 registers match, which currently works only by
10
luck for KVM because we don't populate either of these ID registers
11
from the KVM vCPU and so they are both zero.
6
12
7
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
13
Clean this up so we have functions for finding the number
14
of breakpoints, watchpoints and context comparators which look
15
in the appropriate ID register.
16
17
This allows us to drop the "check that AArch64 and AArch32 agree
18
on the number of breakpoints etc" asserts:
19
* we no longer look at the AArch32 versions unless that's the
20
right place to be looking
21
* it's valid to have a CPU (eg AArch64-only) where they don't match
22
* we shouldn't have been asserting the validity of ID registers
23
in a codepath used with KVM anyway
24
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20200214175116.9164-11-peter.maydell@linaro.org
10
---
28
---
11
hw/intc/gic_internal.h | 7 ++-----
29
target/arm/cpu.h | 7 +++++++
12
hw/intc/arm_gic.c | 31 +++++--------------------------
30
target/arm/internals.h | 42 +++++++++++++++++++++++++++++++++++++++
13
hw/intc/arm_gic_common.c | 23 ++++++++---------------
31
target/arm/debug_helper.c | 6 +++---
14
3 files changed, 15 insertions(+), 46 deletions(-)
32
target/arm/helper.c | 21 +++++---------------
33
4 files changed, 57 insertions(+), 19 deletions(-)
15
34
16
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gic_internal.h
37
--- a/target/arm/cpu.h
19
+++ b/hw/intc/gic_internal.h
38
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
21
40
FIELD(ID_DFR0, PERFMON, 24, 4)
22
#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
41
FIELD(ID_DFR0, TRACEFILT, 28, 4)
23
42
24
-/* The NVIC has 16 internal vectors. However these are not exposed
43
+FIELD(DBGDIDR, SE_IMP, 12, 1)
25
- through the normal GIC interface. */
44
+FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
26
-#define GIC_BASE_IRQ ((s->revision == REV_NVIC) ? 32 : 0)
45
+FIELD(DBGDIDR, VERSION, 16, 4)
27
+#define GIC_BASE_IRQ 0
46
+FIELD(DBGDIDR, CTX_CMPS, 20, 4)
28
47
+FIELD(DBGDIDR, BRPS, 24, 4)
29
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
48
+FIELD(DBGDIDR, WRPS, 28, 4)
30
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
49
+
31
@@ -XXX,XX +XXX,XX @@
50
FIELD(MVFR0, SIMDREG, 0, 4)
32
51
FIELD(MVFR0, FPSP, 4, 4)
33
/* The special cases for the revision property: */
52
FIELD(MVFR0, FPDP, 8, 4)
34
#define REV_11MPCORE 0
53
diff --git a/target/arm/internals.h b/target/arm/internals.h
35
-#define REV_NVIC 0xffffffff
36
37
void gic_set_pending_private(GICState *s, int cpu, int irq);
38
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
39
@@ -XXX,XX +XXX,XX @@ void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val,
40
41
static inline bool gic_test_pending(GICState *s, int irq, int cm)
42
{
43
- if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
44
+ if (s->revision == REV_11MPCORE) {
45
return s->irq_state[irq].pending & cm;
46
} else {
47
/* Edge-triggered interrupts are marked pending on a rising edge, but
48
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
49
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/intc/arm_gic.c
55
--- a/target/arm/internals.h
51
+++ b/hw/intc/arm_gic.c
56
+++ b/target/arm/internals.h
52
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
57
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
53
}
58
}
54
}
59
}
55
60
56
-static void gic_set_irq_nvic(GICState *s, int irq, int level,
61
+/**
57
- int cm, int target)
62
+ * arm_num_brps: Return number of implemented breakpoints.
58
-{
63
+ * Note that the ID register BRPS field is "number of bps - 1",
59
- if (level) {
64
+ * and we return the actual number of breakpoints.
60
- GIC_SET_LEVEL(irq, cm);
65
+ */
61
- GIC_SET_PENDING(irq, target);
66
+static inline int arm_num_brps(ARMCPU *cpu)
62
- } else {
67
+{
63
- GIC_CLEAR_LEVEL(irq, cm);
68
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
69
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
70
+ } else {
71
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1;
72
+ }
73
+}
74
+
75
+/**
76
+ * arm_num_wrps: Return number of implemented watchpoints.
77
+ * Note that the ID register WRPS field is "number of wps - 1",
78
+ * and we return the actual number of watchpoints.
79
+ */
80
+static inline int arm_num_wrps(ARMCPU *cpu)
81
+{
82
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
83
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
84
+ } else {
85
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1;
86
+ }
87
+}
88
+
89
+/**
90
+ * arm_num_ctx_cmps: Return number of implemented context comparators.
91
+ * Note that the ID register CTX_CMPS field is "number of cmps - 1",
92
+ * and we return the actual number of comparators.
93
+ */
94
+static inline int arm_num_ctx_cmps(ARMCPU *cpu)
95
+{
96
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
97
+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
98
+ } else {
99
+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1;
100
+ }
101
+}
102
+
103
/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3.
104
* Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits.
105
*/
106
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/debug_helper.c
109
+++ b/target/arm/debug_helper.c
110
@@ -XXX,XX +XXX,XX @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
111
{
112
CPUARMState *env = &cpu->env;
113
uint64_t bcr = env->cp15.dbgbcr[lbn];
114
- int brps = extract32(cpu->dbgdidr, 24, 4);
115
- int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
116
+ int brps = arm_num_brps(cpu);
117
+ int ctx_cmps = arm_num_ctx_cmps(cpu);
118
int bt;
119
uint32_t contextidr;
120
uint64_t hcr_el2;
121
@@ -XXX,XX +XXX,XX @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
122
* case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
123
* We choose the former.
124
*/
125
- if (lbn > brps || lbn < (brps - ctx_cmps)) {
126
+ if (lbn >= brps || lbn < (brps - ctx_cmps)) {
127
return false;
128
}
129
130
diff --git a/target/arm/helper.c b/target/arm/helper.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/target/arm/helper.c
133
+++ b/target/arm/helper.c
134
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
135
};
136
137
/* Note that all these register fields hold "number of Xs minus 1". */
138
- brps = extract32(cpu->dbgdidr, 24, 4);
139
- wrps = extract32(cpu->dbgdidr, 28, 4);
140
- ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
141
+ brps = arm_num_brps(cpu);
142
+ wrps = arm_num_wrps(cpu);
143
+ ctx_cmps = arm_num_ctx_cmps(cpu);
144
145
assert(ctx_cmps <= brps);
146
147
- /* The DBGDIDR and ID_AA64DFR0_EL1 define various properties
148
- * of the debug registers such as number of breakpoints;
149
- * check that if they both exist then they agree.
150
- */
151
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
152
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps);
153
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps);
154
- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS)
155
- == ctx_cmps);
64
- }
156
- }
65
-}
66
-
157
-
67
static void gic_set_irq_generic(GICState *s, int irq, int level,
158
define_one_arm_cp_reg(cpu, &dbgdidr);
68
int cm, int target)
159
define_arm_cp_regs(cpu, debug_cp_reginfo);
69
{
160
70
@@ -XXX,XX +XXX,XX @@ static void gic_set_irq(void *opaque, int irq, int level)
161
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
71
162
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
72
if (s->revision == REV_11MPCORE) {
73
gic_set_irq_11mpcore(s, irq, level, cm, target);
74
- } else if (s->revision == REV_NVIC) {
75
- gic_set_irq_nvic(s, irq, level, cm, target);
76
} else {
77
gic_set_irq_generic(s, irq, level, cm, target);
78
}
163
}
79
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
164
80
return 1023;
165
- for (i = 0; i < brps + 1; i++) {
166
+ for (i = 0; i < brps; i++) {
167
ARMCPRegInfo dbgregs[] = {
168
{ .name = "DBGBVR", .state = ARM_CP_STATE_BOTH,
169
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
170
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
171
define_arm_cp_regs(cpu, dbgregs);
81
}
172
}
82
173
83
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
174
- for (i = 0; i < wrps + 1; i++) {
84
+ if (s->revision == REV_11MPCORE) {
175
+ for (i = 0; i < wrps; i++) {
85
/* Clear pending flags for both level and edge triggered interrupts.
176
ARMCPRegInfo dbgregs[] = {
86
* Level triggered IRQs will be reasserted once they become inactive.
177
{ .name = "DBGWVR", .state = ARM_CP_STATE_BOTH,
87
*/
178
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
88
@@ -XXX,XX +XXX,XX @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
89
DPRINTF("Set %d pending mask %x\n", irq, cm);
90
GIC_SET_PENDING(irq, cm);
91
}
92
- } else if (s->revision == REV_NVIC) {
93
- if (GIC_TEST_LEVEL(irq, cm)) {
94
- DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
95
- GIC_SET_PENDING(irq, cm);
96
- }
97
}
98
99
group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
100
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
101
} else if (offset < 0xf10) {
102
goto bad_reg;
103
} else if (offset < 0xf30) {
104
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
105
+ if (s->revision == REV_11MPCORE) {
106
goto bad_reg;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
110
case 2:
111
res = gic_id_gicv2[(offset - 0xfd0) >> 2];
112
break;
113
- case REV_NVIC:
114
- /* Shouldn't be able to get here */
115
- abort();
116
default:
117
res = 0;
118
}
119
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
120
continue; /* Ignore Non-secure access of Group0 IRQ */
121
}
122
123
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
124
+ if (s->revision == REV_11MPCORE) {
125
if (value & (1 << (i * 2))) {
126
GIC_SET_MODEL(irq + i);
127
} else {
128
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
129
goto bad_reg;
130
} else if (offset < 0xf20) {
131
/* GICD_CPENDSGIRn */
132
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
133
+ if (s->revision == REV_11MPCORE) {
134
goto bad_reg;
135
}
136
irq = (offset - 0xf10);
137
@@ -XXX,XX +XXX,XX @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
138
}
139
} else if (offset < 0xf30) {
140
/* GICD_SPENDSGIRn */
141
- if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
142
+ if (s->revision == REV_11MPCORE) {
143
goto bad_reg;
144
}
145
irq = (offset - 0xf20);
146
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/arm_gic_common.c
149
+++ b/hw/intc/arm_gic_common.c
150
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
151
* [N+32..N+63] PPIs for CPU 1
152
* ...
153
*/
154
- if (s->revision != REV_NVIC) {
155
- i += (GIC_INTERNAL * s->num_cpu);
156
- }
157
+ i += (GIC_INTERNAL * s->num_cpu);
158
qdev_init_gpio_in(DEVICE(s), handler, i);
159
160
for (i = 0; i < s->num_cpu; i++) {
161
@@ -XXX,XX +XXX,XX @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
162
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
163
sysbus_init_mmio(sbd, &s->iomem);
164
165
- if (s->revision != REV_NVIC) {
166
- /* This is the main CPU interface "for this core". It is always
167
- * present because it is required by both software emulation and KVM.
168
- * NVIC is not handled here because its CPU interface is different,
169
- * neither it can use KVM.
170
- */
171
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
172
- s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
173
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
174
- }
175
+ /* This is the main CPU interface "for this core". It is always
176
+ * present because it is required by both software emulation and KVM.
177
+ */
178
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
179
+ s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100);
180
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
181
}
182
183
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
184
@@ -XXX,XX +XXX,XX @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
185
}
186
187
if (s->security_extn &&
188
- (s->revision == REV_11MPCORE || s->revision == REV_NVIC)) {
189
+ (s->revision == REV_11MPCORE)) {
190
error_setg(errp, "this GIC revision does not implement "
191
"the security extensions");
192
return;
193
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
194
DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
195
/* Revision can be 1 or 2 for GIC architecture specification
196
* versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC.
197
- * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".)
198
*/
199
DEFINE_PROP_UINT32("revision", GICState, revision, 1),
200
/* True if the GIC should implement the security extensions */
201
--
179
--
202
2.7.4
180
2.20.1
203
181
204
182
diff view generated by jsdifflib
1
Implement the exception return consistency checks
1
We're going to want to read the DBGDIDR register from KVM in
2
described in the v7M pseudocode ExceptionReturn().
2
a subsequent commit, which means it needs to be in the
3
3
ARMISARegisters sub-struct. Move it.
4
Inspired by a patch from Michael Davidsaver's series, but
5
this is a reimplementation from scratch based on the
6
ARM ARM pseudocode.
7
4
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200214175116.9164-12-peter.maydell@linaro.org
10
---
8
---
11
target/arm/cpu.h | 12 +++++-
9
target/arm/cpu.h | 2 +-
12
hw/intc/armv7m_nvic.c | 12 +++++-
10
target/arm/internals.h | 6 +++---
13
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-----
11
target/arm/cpu.c | 8 ++++----
14
3 files changed, 123 insertions(+), 13 deletions(-)
12
target/arm/cpu64.c | 6 +++---
13
target/arm/helper.c | 2 +-
14
5 files changed, 12 insertions(+), 12 deletions(-)
15
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
#endif
21
uint32_t mvfr1;
22
void armv7m_nvic_set_pending(void *opaque, int irq);
22
uint32_t mvfr2;
23
void armv7m_nvic_acknowledge_irq(void *opaque);
23
uint32_t id_dfr0;
24
-void armv7m_nvic_complete_irq(void *opaque, int irq);
24
+ uint32_t dbgdidr;
25
+/**
25
uint64_t id_aa64isar0;
26
+ * armv7m_nvic_complete_irq: complete specified interrupt or exception
26
uint64_t id_aa64isar1;
27
+ * @opaque: the NVIC
27
uint64_t id_aa64pfr0;
28
+ * @irq: the exception number to complete
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
29
+ *
29
uint32_t id_mmfr4;
30
+ * Returns: -1 if the irq was not active
30
uint64_t id_aa64afr0;
31
+ * 1 if completing this irq brought us back to base (no active irqs)
31
uint64_t id_aa64afr1;
32
+ * 0 if there is still an irq active after this one was completed
32
- uint32_t dbgdidr;
33
+ * (Ignoring -1, this is the same as the RETTOBASE value before completion.)
33
uint32_t clidr;
34
+ */
34
uint64_t mp_affinity; /* MP ID without feature bits */
35
+int armv7m_nvic_complete_irq(void *opaque, int irq);
35
/* The elements of this array are the CCSIDR values for each cache,
36
36
diff --git a/target/arm/internals.h b/target/arm/internals.h
37
/* Interface for defining coprocessor registers.
38
* Registers are defined in tables of arm_cp_reginfo structs
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
38
--- a/target/arm/internals.h
42
+++ b/hw/intc/armv7m_nvic.c
39
+++ b/target/arm/internals.h
43
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque)
40
@@ -XXX,XX +XXX,XX @@ static inline int arm_num_brps(ARMCPU *cpu)
44
nvic_irq_update(s);
41
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
42
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1;
43
} else {
44
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1;
45
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1;
46
}
45
}
47
}
46
48
47
-void armv7m_nvic_complete_irq(void *opaque, int irq)
49
@@ -XXX,XX +XXX,XX @@ static inline int arm_num_wrps(ARMCPU *cpu)
48
+int armv7m_nvic_complete_irq(void *opaque, int irq)
50
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
49
{
51
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1;
50
NVICState *s = (NVICState *)opaque;
52
} else {
51
VecInfo *vec;
53
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1;
52
+ int ret;
54
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1;
53
54
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
55
56
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
57
58
trace_nvic_complete_irq(irq);
59
60
+ if (!vec->active) {
61
+ /* Tell the caller this was an illegal exception return */
62
+ return -1;
63
+ }
64
+
65
+ ret = nvic_rettobase(s);
66
+
67
vec->active = 0;
68
if (vec->level) {
69
/* Re-pend the exception if it's still held high; only
70
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
71
}
55
}
72
73
nvic_irq_update(s);
74
+
75
+ return ret;
76
}
56
}
77
57
78
/* callback when external interrupt line is changed */
58
@@ -XXX,XX +XXX,XX @@ static inline int arm_num_ctx_cmps(ARMCPU *cpu)
59
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
60
return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1;
61
} else {
62
- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1;
63
+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1;
64
}
65
}
66
67
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/cpu.c
70
+++ b/target/arm/cpu.c
71
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
72
cpu->isar.id_isar2 = 0x21232031;
73
cpu->isar.id_isar3 = 0x11112131;
74
cpu->isar.id_isar4 = 0x00111142;
75
- cpu->dbgdidr = 0x15141000;
76
+ cpu->isar.dbgdidr = 0x15141000;
77
cpu->clidr = (1 << 27) | (2 << 24) | 3;
78
cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
79
cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
80
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
81
cpu->isar.id_isar2 = 0x21232041;
82
cpu->isar.id_isar3 = 0x11112131;
83
cpu->isar.id_isar4 = 0x00111142;
84
- cpu->dbgdidr = 0x35141000;
85
+ cpu->isar.dbgdidr = 0x35141000;
86
cpu->clidr = (1 << 27) | (1 << 24) | 3;
87
cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
88
cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
89
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
90
cpu->isar.id_isar2 = 0x21232041;
91
cpu->isar.id_isar3 = 0x11112131;
92
cpu->isar.id_isar4 = 0x10011142;
93
- cpu->dbgdidr = 0x3515f005;
94
+ cpu->isar.dbgdidr = 0x3515f005;
95
cpu->clidr = 0x0a200023;
96
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
97
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
98
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
99
cpu->isar.id_isar2 = 0x21232041;
100
cpu->isar.id_isar3 = 0x11112131;
101
cpu->isar.id_isar4 = 0x10011142;
102
- cpu->dbgdidr = 0x3515f021;
103
+ cpu->isar.dbgdidr = 0x3515f021;
104
cpu->clidr = 0x0a200023;
105
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
106
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
107
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/cpu64.c
110
+++ b/target/arm/cpu64.c
111
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
112
cpu->isar.id_aa64dfr0 = 0x10305106;
113
cpu->isar.id_aa64isar0 = 0x00011120;
114
cpu->isar.id_aa64mmfr0 = 0x00001124;
115
- cpu->dbgdidr = 0x3516d000;
116
+ cpu->isar.dbgdidr = 0x3516d000;
117
cpu->clidr = 0x0a200023;
118
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
119
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
120
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
121
cpu->isar.id_aa64dfr0 = 0x10305106;
122
cpu->isar.id_aa64isar0 = 0x00011120;
123
cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */
124
- cpu->dbgdidr = 0x3516d000;
125
+ cpu->isar.dbgdidr = 0x3516d000;
126
cpu->clidr = 0x0a200023;
127
cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */
128
cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */
129
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
130
cpu->isar.id_aa64dfr0 = 0x10305106;
131
cpu->isar.id_aa64isar0 = 0x00011120;
132
cpu->isar.id_aa64mmfr0 = 0x00001124;
133
- cpu->dbgdidr = 0x3516d000;
134
+ cpu->isar.dbgdidr = 0x3516d000;
135
cpu->clidr = 0x0a200023;
136
cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */
137
cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
138
diff --git a/target/arm/helper.c b/target/arm/helper.c
80
index XXXXXXX..XXXXXXX 100644
139
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/helper.c
140
--- a/target/arm/helper.c
82
+++ b/target/arm/helper.c
141
+++ b/target/arm/helper.c
83
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
142
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
84
v7m_push(env, env->regs[0]);
143
ARMCPRegInfo dbgdidr = {
85
}
144
.name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
86
145
.access = PL0_R, .accessfn = access_tda,
87
-static void do_v7m_exception_exit(CPUARMState *env)
146
- .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr,
88
+static void do_v7m_exception_exit(ARMCPU *cpu)
147
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
89
{
148
};
90
+ CPUARMState *env = &cpu->env;
149
91
uint32_t type;
150
/* Note that all these register fields hold "number of Xs minus 1". */
92
uint32_t xpsr;
93
-
94
+ bool ufault = false;
95
+ bool return_to_sp_process = false;
96
+ bool return_to_handler = false;
97
+ bool rettobase = false;
98
+
99
+ /* We can only get here from an EXCP_EXCEPTION_EXIT, and
100
+ * arm_v7m_do_unassigned_access() enforces the architectural rule
101
+ * that jumps to magic addresses don't have magic behaviour unless
102
+ * we're in Handler mode (compare pseudocode BXWritePC()).
103
+ */
104
+ assert(env->v7m.exception != 0);
105
+
106
+ /* In the spec pseudocode ExceptionReturn() is called directly
107
+ * from BXWritePC() and gets the full target PC value including
108
+ * bit zero. In QEMU's implementation we treat it as a normal
109
+ * jump-to-register (which is then caught later on), and so split
110
+ * the target value up between env->regs[15] and env->thumb in
111
+ * gen_bx(). Reconstitute it.
112
+ */
113
type = env->regs[15];
114
+ if (env->thumb) {
115
+ type |= 1;
116
+ }
117
+
118
+ qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32
119
+ " previous exception %d\n",
120
+ type, env->v7m.exception);
121
+
122
+ if (extract32(type, 5, 23) != extract32(-1, 5, 23)) {
123
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in exception "
124
+ "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", type);
125
+ }
126
+
127
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
128
/* Auto-clear FAULTMASK on return from other than NMI */
129
env->daif &= ~PSTATE_F;
130
}
131
- if (env->v7m.exception != 0) {
132
- armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
133
+
134
+ switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
135
+ case -1:
136
+ /* attempt to exit an exception that isn't active */
137
+ ufault = true;
138
+ break;
139
+ case 0:
140
+ /* still an irq active now */
141
+ break;
142
+ case 1:
143
+ /* we returned to base exception level, no nesting.
144
+ * (In the pseudocode this is written using "NestedActivation != 1"
145
+ * where we have 'rettobase == false'.)
146
+ */
147
+ rettobase = true;
148
+ break;
149
+ default:
150
+ g_assert_not_reached();
151
+ }
152
+
153
+ switch (type & 0xf) {
154
+ case 1: /* Return to Handler */
155
+ return_to_handler = true;
156
+ break;
157
+ case 13: /* Return to Thread using Process stack */
158
+ return_to_sp_process = true;
159
+ /* fall through */
160
+ case 9: /* Return to Thread using Main stack */
161
+ if (!rettobase &&
162
+ !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) {
163
+ ufault = true;
164
+ }
165
+ break;
166
+ default:
167
+ ufault = true;
168
+ }
169
+
170
+ if (ufault) {
171
+ /* Bad exception return: instead of popping the exception
172
+ * stack, directly take a usage fault on the current stack.
173
+ */
174
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
175
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
176
+ v7m_exception_taken(cpu, type | 0xf0000000);
177
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
178
+ "stackframe: failed exception return integrity check\n");
179
+ return;
180
}
181
182
/* Switch to the target stack. */
183
- switch_v7m_sp(env, (type & 4) != 0);
184
+ switch_v7m_sp(env, return_to_sp_process);
185
/* Pop registers. */
186
env->regs[0] = v7m_pop(env);
187
env->regs[1] = v7m_pop(env);
188
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(CPUARMState *env)
189
/* Undo stack alignment. */
190
if (xpsr & 0x200)
191
env->regs[13] |= 4;
192
- /* ??? The exception return type specifies Thread/Handler mode. However
193
- this is also implied by the xPSR value. Not sure what to do
194
- if there is a mismatch. */
195
- /* ??? Likewise for mismatches between the CONTROL register and the stack
196
- pointer. */
197
+
198
+ /* The restored xPSR exception field will be zero if we're
199
+ * resuming in Thread mode. If that doesn't match what the
200
+ * exception return type specified then this is a UsageFault.
201
+ */
202
+ if (return_to_handler == (env->v7m.exception == 0)) {
203
+ /* Take an INVPC UsageFault by pushing the stack again. */
204
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
205
+ env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
206
+ v7m_push_stack(cpu);
207
+ v7m_exception_taken(cpu, type | 0xf0000000);
208
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
209
+ "failed exception return integrity check\n");
210
+ return;
211
+ }
212
+
213
+ /* Otherwise, we have a successful exception exit. */
214
+ qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
215
}
216
217
static void arm_log_exception(int idx)
218
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
219
case EXCP_IRQ:
220
break;
221
case EXCP_EXCEPTION_EXIT:
222
- do_v7m_exception_exit(env);
223
+ do_v7m_exception_exit(cpu);
224
return;
225
default:
226
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
227
--
151
--
228
2.7.4
152
2.20.1
229
153
230
154
diff view generated by jsdifflib
1
In get_page_addr_code(), if the guest PC doesn't correspond to RAM
1
Now we have isar_feature test functions that look at fields in the
2
then we currently run the CPU's do_unassigned_access() hook if it has
2
ID_AA64DFR0_EL1 and ID_DFR0 ID registers, add the code that reads
3
one, and otherwise we give up and exit QEMU with a more-or-less
3
these register values from KVM so that the checks behave correctly
4
useful message. This code assumes that the do_unassigned_access hook
4
when we're using KVM.
5
will never return, because if it does then we'll plough on attempting
6
to use a non-RAM TLB entry to get a RAM address and will abort() in
7
qemu_ram_addr_from_host_nofail(). Unfortunately some CPU
8
implementations of this hook do return: Microblaze, SPARC and the ARM
9
v7M.
10
5
11
Change the code to call report_bad_exec() if the hook returns, as
6
No isar_feature function tests ID_AA64DFR1_EL1 or DBGDIDR yet, but we
12
well as if it didn't have one. This means we can tidy it up to use
7
add it to maintain the invariant that every field in the
13
the cpu_unassigned_access() function which wraps the "get the CPU
8
ARMISARegisters struct is populated for a KVM CPU and can be relied
14
class and call the hook if it has one" work, since we aren't trying
9
on. This requirement isn't actually written down yet, so add a note
15
to distinguish "no hook" from "hook existed and returned" any more.
10
to the relevant comment.
16
17
This brings the handling of this hook into line with the handling
18
used for data accesses, where "hook returned" is treated the
19
same as "no hook existed" and gets you the default behaviour.
20
11
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <rth@twiddle.net>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200214175116.9164-13-peter.maydell@linaro.org
23
---
15
---
24
cputlb.c | 15 +++++++--------
16
target/arm/cpu.h | 5 +++++
25
1 file changed, 7 insertions(+), 8 deletions(-)
17
target/arm/kvm32.c | 8 ++++++++
18
target/arm/kvm64.c | 36 ++++++++++++++++++++++++++++++++++++
19
3 files changed, 49 insertions(+)
26
20
27
diff --git a/cputlb.c b/cputlb.c
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
29
--- a/cputlb.c
23
--- a/target/arm/cpu.h
30
+++ b/cputlb.c
24
+++ b/target/arm/cpu.h
31
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
25
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
32
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
26
* prefix means a constant register.
33
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
27
* Some of these registers are split out into a substructure that
34
if (memory_region_is_unassigned(mr)) {
28
* is shared with the translators to control the ISA.
35
- CPUClass *cc = CPU_GET_CLASS(cpu);
29
+ *
36
-
30
+ * Note that if you add an ID register to the ARMISARegisters struct
37
- if (cc->do_unassigned_access) {
31
+ * you need to also update the 32-bit and 64-bit versions of the
38
- cc->do_unassigned_access(cpu, addr, false, true, 0, 4);
32
+ * kvm_arm_get_host_cpu_features() function to correctly populate the
39
- } else {
33
+ * field by reading the value from the KVM vCPU.
40
- report_bad_exec(cpu, addr);
34
*/
41
- exit(1);
35
struct ARMISARegisters {
42
- }
36
uint32_t id_isar0;
43
+ cpu_unassigned_access(cpu, addr, false, true, 0, 4);
37
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
44
+ /* The CPU's unassigned access hook might have longjumped out
38
index XXXXXXX..XXXXXXX 100644
45
+ * with an exception. If it didn't (or there was no hook) then
39
--- a/target/arm/kvm32.c
46
+ * we can't proceed further.
40
+++ b/target/arm/kvm32.c
41
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
42
ahcf->isar.id_isar6 = 0;
43
}
44
45
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
46
+ ARM_CP15_REG32(0, 0, 1, 2));
47
+
48
err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
49
KVM_REG_ARM | KVM_REG_SIZE_U32 |
50
KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
51
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
52
* Fortunately there is not yet anything in there that affects migration.
53
*/
54
55
+ /*
56
+ * There is no way to read DBGDIDR, because currently 32-bit KVM
57
+ * doesn't implement debug at all. Leave it at zero.
58
+ */
59
+
60
kvm_arm_destroy_scratch_host_vcpu(fdarray);
61
62
if (err < 0) {
63
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/kvm64.c
66
+++ b/target/arm/kvm64.c
67
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
68
} else {
69
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1,
70
ARM64_SYS_REG(3, 0, 0, 4, 1));
71
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0,
72
+ ARM64_SYS_REG(3, 0, 0, 5, 0));
73
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1,
74
+ ARM64_SYS_REG(3, 0, 0, 5, 1));
75
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0,
76
ARM64_SYS_REG(3, 0, 0, 6, 0));
77
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1,
78
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
79
* than skipping the reads and leaving 0, as we must avoid
80
* considering the values in every case.
81
*/
82
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
83
+ ARM64_SYS_REG(3, 0, 0, 1, 2));
84
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
85
ARM64_SYS_REG(3, 0, 0, 2, 0));
86
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
87
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
88
ARM64_SYS_REG(3, 0, 0, 3, 1));
89
err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2,
90
ARM64_SYS_REG(3, 0, 0, 3, 2));
91
+
92
+ /*
93
+ * DBGDIDR is a bit complicated because the kernel doesn't
94
+ * provide an accessor for it in 64-bit mode, which is what this
95
+ * scratch VM is in, and there's no architected "64-bit sysreg
96
+ * which reads the same as the 32-bit register" the way there is
97
+ * for other ID registers. Instead we synthesize a value from the
98
+ * AArch64 ID_AA64DFR0, the same way the kernel code in
99
+ * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does.
100
+ * We only do this if the CPU supports AArch32 at EL1.
47
+ */
101
+ */
48
+ report_bad_exec(cpu, addr);
102
+ if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) {
49
+ exit(1);
103
+ int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS);
104
+ int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS);
105
+ int ctx_cmps =
106
+ FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS);
107
+ int version = 6; /* ARMv8 debug architecture */
108
+ bool has_el3 =
109
+ !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3);
110
+ uint32_t dbgdidr = 0;
111
+
112
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps);
113
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, BRPS, brps);
114
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, CTX_CMPS, ctx_cmps);
115
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, VERSION, version);
116
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3);
117
+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3);
118
+ dbgdidr |= (1 << 15); /* RES1 bit */
119
+ ahcf->isar.dbgdidr = dbgdidr;
120
+ }
50
}
121
}
51
p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
122
52
return qemu_ram_addr_from_host_nofail(p);
123
sve_supported = ioctl(fdarray[0], KVM_CHECK_EXTENSION, KVM_CAP_ARM_SVE) > 0;
53
--
124
--
54
2.7.4
125
2.20.1
55
126
56
127
diff view generated by jsdifflib
1
Extract the code from the tail end of arm_v7m_do_interrupt() which
1
The ARMv8.1-PMU extension requires:
2
enters the exception handler into a pair of utility functions
2
* the evtCount field in PMETYPER<n>_EL0 is 16 bits, not 10
3
v7m_exception_taken() and v7m_push_stack(), which correspond roughly
3
* MDCR_EL2.HPMD allows event counting to be disabled at EL2
4
to the pseudocode PushStack() and ExceptionTaken().
4
* two new required events, STALL_FRONTEND and STALL_BACKEND
5
* ID register bits in ID_AA64DFR0_EL1 and ID_DFR0
5
6
6
This also requires us to move the arm_v7m_load_vector() utility
7
We already implement the 16-bit evtCount field and the
7
routine up so we can call it.
8
HPMD bit, so all that is missing is the two new events:
9
STALL_FRONTEND
10
"counts every cycle counted by the CPU_CYCLES event on which no
11
operation was issued because there are no operations available
12
to issue to this PE from the frontend"
13
STALL_BACKEND
14
"counts every cycle counted by the CPU_CYCLES event on which no
15
operation was issued because the backend is unable to accept
16
any available operations from the frontend"
8
17
9
Handling illegal exception returns has some cases where we want to
18
QEMU never stalls in this sense, so our implementation is trivial:
10
take a UsageFault either on an existing stack frame or with a new
19
always return a zero count.
11
stack frame but with a specific LR value, so we want to be able to
12
call these without having to go via arm_v7m_cpu_do_interrupt().
13
20
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
23
Message-id: 20200214175116.9164-14-peter.maydell@linaro.org
16
---
24
---
17
target/arm/helper.c | 118 ++++++++++++++++++++++++++++++----------------------
25
target/arm/helper.c | 32 ++++++++++++++++++++++++++++++--
18
1 file changed, 68 insertions(+), 50 deletions(-)
26
1 file changed, 30 insertions(+), 2 deletions(-)
19
27
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
30
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
31
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void switch_v7m_sp(CPUARMState *env, bool new_spsel)
32
@@ -XXX,XX +XXX,XX @@ static int64_t instructions_ns_per(uint64_t icount)
25
}
26
}
33
}
27
34
#endif
28
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
35
36
+static bool pmu_8_1_events_supported(CPUARMState *env)
29
+{
37
+{
30
+ CPUState *cs = CPU(cpu);
38
+ /* For events which are supported in any v8.1 PMU */
31
+ CPUARMState *env = &cpu->env;
39
+ return cpu_isar_feature(any_pmu_8_1, env_archcpu(env));
32
+ MemTxResult result;
33
+ hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
34
+ uint32_t addr;
35
+
36
+ addr = address_space_ldl(cs->as, vec,
37
+ MEMTXATTRS_UNSPECIFIED, &result);
38
+ if (result != MEMTX_OK) {
39
+ /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
40
+ * which would then be immediately followed by our failing to load
41
+ * the entry vector for that HardFault, which is a Lockup case.
42
+ * Since we don't model Lockup, we just report this guest error
43
+ * via cpu_abort().
44
+ */
45
+ cpu_abort(cs, "Failed to read from exception vector table "
46
+ "entry %08x\n", (unsigned)vec);
47
+ }
48
+ return addr;
49
+}
40
+}
50
+
41
+
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr)
42
+static uint64_t zero_event_get_count(CPUARMState *env)
52
+{
43
+{
53
+ /* Do the "take the exception" parts of exception entry,
44
+ /* For events which on QEMU never fire, so their count is always zero */
54
+ * but not the pushing of state to the stack. This is
45
+ return 0;
55
+ * similar to the pseudocode ExceptionTaken() function.
56
+ */
57
+ CPUARMState *env = &cpu->env;
58
+ uint32_t addr;
59
+
60
+ armv7m_nvic_acknowledge_irq(env->nvic);
61
+ switch_v7m_sp(env, 0);
62
+ /* Clear IT bits */
63
+ env->condexec_bits = 0;
64
+ env->regs[14] = lr;
65
+ addr = arm_v7m_load_vector(cpu);
66
+ env->regs[15] = addr & 0xfffffffe;
67
+ env->thumb = addr & 1;
68
+}
46
+}
69
+
47
+
70
+static void v7m_push_stack(ARMCPU *cpu)
48
+static int64_t zero_event_ns_per(uint64_t cycles)
71
+{
49
+{
72
+ /* Do the "set up stack frame" part of exception entry,
50
+ /* An event which never fires can never overflow */
73
+ * similar to pseudocode PushStack().
51
+ return -1;
74
+ */
75
+ CPUARMState *env = &cpu->env;
76
+ uint32_t xpsr = xpsr_read(env);
77
+
78
+ /* Align stack pointer if the guest wants that */
79
+ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
80
+ env->regs[13] -= 4;
81
+ xpsr |= 0x200;
82
+ }
83
+ /* Switch to the handler mode. */
84
+ v7m_push(env, xpsr);
85
+ v7m_push(env, env->regs[15]);
86
+ v7m_push(env, env->regs[14]);
87
+ v7m_push(env, env->regs[12]);
88
+ v7m_push(env, env->regs[3]);
89
+ v7m_push(env, env->regs[2]);
90
+ v7m_push(env, env->regs[1]);
91
+ v7m_push(env, env->regs[0]);
92
+}
52
+}
93
+
53
+
94
static void do_v7m_exception_exit(CPUARMState *env)
54
static const pm_event pm_events[] = {
95
{
55
{ .number = 0x000, /* SW_INCR */
96
uint32_t type;
56
.supported = event_always_supported,
97
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
57
@@ -XXX,XX +XXX,XX @@ static const pm_event pm_events[] = {
98
}
58
.supported = event_always_supported,
99
}
59
.get_count = cycles_get_count,
100
60
.ns_per_count = cycles_ns_per,
101
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu)
102
-
103
-{
104
- CPUState *cs = CPU(cpu);
105
- CPUARMState *env = &cpu->env;
106
- MemTxResult result;
107
- hwaddr vec = env->v7m.vecbase + env->v7m.exception * 4;
108
- uint32_t addr;
109
-
110
- addr = address_space_ldl(cs->as, vec,
111
- MEMTXATTRS_UNSPECIFIED, &result);
112
- if (result != MEMTX_OK) {
113
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
114
- * which would then be immediately followed by our failing to load
115
- * the entry vector for that HardFault, which is a Lockup case.
116
- * Since we don't model Lockup, we just report this guest error
117
- * via cpu_abort().
118
- */
119
- cpu_abort(cs, "Failed to read from exception vector table "
120
- "entry %08x\n", (unsigned)vec);
121
- }
61
- }
122
- return addr;
62
+ },
123
-}
63
#endif
124
-
64
+ { .number = 0x023, /* STALL_FRONTEND */
125
void arm_v7m_cpu_do_interrupt(CPUState *cs)
65
+ .supported = pmu_8_1_events_supported,
126
{
66
+ .get_count = zero_event_get_count,
127
ARMCPU *cpu = ARM_CPU(cs);
67
+ .ns_per_count = zero_event_ns_per,
128
CPUARMState *env = &cpu->env;
68
+ },
129
- uint32_t xpsr = xpsr_read(env);
69
+ { .number = 0x024, /* STALL_BACKEND */
130
uint32_t lr;
70
+ .supported = pmu_8_1_events_supported,
131
- uint32_t addr;
71
+ .get_count = zero_event_get_count,
132
72
+ .ns_per_count = zero_event_ns_per,
133
arm_log_exception(cs->exception_index);
73
+ },
134
74
};
135
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
75
136
return; /* Never happens. Keep compiler happy. */
76
/*
137
}
77
@@ -XXX,XX +XXX,XX @@ static const pm_event pm_events[] = {
138
78
* should first be updated to something sparse instead of the current
139
- armv7m_nvic_acknowledge_irq(env->nvic);
79
* supported_event_map[] array.
140
-
80
*/
141
+ v7m_push_stack(cpu);
81
-#define MAX_EVENT_ID 0x11
142
+ v7m_exception_taken(cpu, lr);
82
+#define MAX_EVENT_ID 0x24
143
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
83
#define UNSUPPORTED_EVENT UINT16_MAX
144
-
84
static uint16_t supported_event_map[MAX_EVENT_ID + 1];
145
- /* Align stack pointer if the guest wants that */
85
146
- if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
147
- env->regs[13] -= 4;
148
- xpsr |= 0x200;
149
- }
150
- /* Switch to the handler mode. */
151
- v7m_push(env, xpsr);
152
- v7m_push(env, env->regs[15]);
153
- v7m_push(env, env->regs[14]);
154
- v7m_push(env, env->regs[12]);
155
- v7m_push(env, env->regs[3]);
156
- v7m_push(env, env->regs[2]);
157
- v7m_push(env, env->regs[1]);
158
- v7m_push(env, env->regs[0]);
159
- switch_v7m_sp(env, 0);
160
- /* Clear IT bits */
161
- env->condexec_bits = 0;
162
- env->regs[14] = lr;
163
- addr = arm_v7m_load_vector(cpu);
164
- env->regs[15] = addr & 0xfffffffe;
165
- env->thumb = addr & 1;
166
}
167
168
/* Function used to synchronize QEMU's AArch64 register set with AArch32
169
--
86
--
170
2.7.4
87
2.20.1
171
88
172
89
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
The ARMv8.4-PMU extension adds:
2
* one new required event, STALL
3
* one new system register PMMIR_EL1
2
4
3
Despite some superficial similarities of register layout, the
5
(There are also some more L1-cache related events, but since
4
M-profile NVIC is really very different from the A-profile GIC.
6
we don't implement any cache we don't provide these, in the
5
Our current attempt to reuse the GIC code means that we have
7
same way we don't provide the base-PMUv3 cache events.)
6
significant bugs in our NVIC.
7
8
8
Implement the NVIC as an entirely separate device, to give
9
The STALL event "counts every attributable cycle on which no
9
us somewhere we can get the behaviour correct.
10
attributable instruction or operation was sent for execution on this
11
PE". QEMU doesn't stall in this sense, so this is another
12
always-reads-zero event.
10
13
11
This initial commit does not attempt to implement exception
14
The PMMIR_EL1 register is a read-only register providing
12
priority escalation, since the GIC-based code didn't either.
15
implementation-specific information about the PMU; currently it has
13
It does fix a few bugs in passing:
16
only one field, SLOTS, which defines behaviour of the STALL_SLOT PMU
14
* ICSR.RETTOBASE polarity was wrong and didn't account for
17
event. Since QEMU doesn't implement the STALL_SLOT event, we can
15
internal exceptions
18
validly make the register read zero.
16
* ICSR.VECTPENDING was 16 too high if the pending exception
17
was for an external interrupt
18
* UsageFault, BusFault and MemFault were not disabled on reset
19
as they are supposed to be
20
19
21
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
[PMM: reworked, various bugs and stylistic cleanups]
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
22
Message-id: 20200214175116.9164-15-peter.maydell@linaro.org
25
---
23
---
26
hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++----------
24
target/arm/cpu.h | 18 ++++++++++++++++++
27
hw/intc/trace-events | 15 +
25
target/arm/helper.c | 22 +++++++++++++++++++++-
28
2 files changed, 609 insertions(+), 144 deletions(-)
26
2 files changed, 39 insertions(+), 1 deletion(-)
29
27
30
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/armv7m_nvic.c
30
--- a/target/arm/cpu.h
33
+++ b/hw/intc/armv7m_nvic.c
31
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id)
35
#include "hw/sysbus.h"
33
FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
36
#include "qemu/timer.h"
37
#include "hw/arm/arm.h"
38
+#include "target/arm/cpu.h"
39
#include "exec/address-spaces.h"
40
-#include "gic_internal.h"
41
#include "qemu/log.h"
42
+#include "trace.h"
43
+
44
+/* IRQ number counting:
45
+ *
46
+ * the num-irq property counts the number of external IRQ lines
47
+ *
48
+ * NVICState::num_irq counts the total number of exceptions
49
+ * (external IRQs, the 15 internal exceptions including reset,
50
+ * and one for the unused exception number 0).
51
+ *
52
+ * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines.
53
+ *
54
+ * NVIC_MAX_VECTORS is the highest permitted number of exceptions.
55
+ *
56
+ * Iterating through all exceptions should typically be done with
57
+ * for (i = 1; i < s->num_irq; i++) to avoid the unused slot 0.
58
+ *
59
+ * The external qemu_irq lines are the NVIC's external IRQ lines,
60
+ * so line 0 is exception 16.
61
+ *
62
+ * In the terminology of the architecture manual, "interrupts" are
63
+ * a subcategory of exception referring to the external interrupts
64
+ * (which are exception numbers NVIC_FIRST_IRQ and upward).
65
+ * For historical reasons QEMU tends to use "interrupt" and
66
+ * "exception" more or less interchangeably.
67
+ */
68
+#define NVIC_FIRST_IRQ 16
69
+#define NVIC_MAX_VECTORS 512
70
+#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
71
+
72
+/* Effective running priority of the CPU when no exception is active
73
+ * (higher than the highest possible priority value)
74
+ */
75
+#define NVIC_NOEXC_PRIO 0x100
76
+
77
+typedef struct VecInfo {
78
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
79
+ * priority values for RESET, NMI and HardFault can be negative.
80
+ */
81
+ int16_t prio;
82
+ uint8_t enabled;
83
+ uint8_t pending;
84
+ uint8_t active;
85
+ uint8_t level; /* exceptions <=15 never set level */
86
+} VecInfo;
87
88
typedef struct NVICState {
89
- GICState gic;
90
+ /*< private >*/
91
+ SysBusDevice parent_obj;
92
+ /*< public >*/
93
+
94
ARMCPU *cpu;
95
96
+ VecInfo vectors[NVIC_MAX_VECTORS];
97
uint32_t prigroup;
98
99
+ /* vectpending and exception_prio are both cached state that can
100
+ * be recalculated from the vectors[] array and the prigroup field.
101
+ */
102
+ unsigned int vectpending; /* highest prio pending enabled exception */
103
+ int exception_prio; /* group prio of the highest prio active exception */
104
+
105
struct {
106
uint32_t control;
107
uint32_t reload;
108
int64_t tick;
109
QEMUTimer *timer;
110
} systick;
111
+
112
MemoryRegion sysregmem;
113
- MemoryRegion gic_iomem_alias;
114
MemoryRegion container;
115
+
116
uint32_t num_irq;
117
+ qemu_irq excpout;
118
qemu_irq sysresetreq;
119
} NVICState;
120
121
#define TYPE_NVIC "armv7m_nvic"
122
-/**
123
- * NVICClass:
124
- * @parent_reset: the parent class' reset handler.
125
- *
126
- * A model of the v7M NVIC and System Controller
127
- */
128
-typedef struct NVICClass {
129
- /*< private >*/
130
- ARMGICClass parent_class;
131
- /*< public >*/
132
- DeviceRealize parent_realize;
133
- void (*parent_reset)(DeviceState *dev);
134
-} NVICClass;
135
-
136
-#define NVIC_CLASS(klass) \
137
- OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
138
-#define NVIC_GET_CLASS(obj) \
139
- OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
140
+
141
#define NVIC(obj) \
142
OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
143
144
@@ -XXX,XX +XXX,XX @@ static void systick_reset(NVICState *s)
145
timer_del(s->systick.timer);
146
}
34
}
147
35
148
-/* The external routines use the hardware vector numbering, ie. the first
36
+static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id)
149
- IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
150
+static int nvic_pending_prio(NVICState *s)
151
+{
37
+{
152
+ /* return the priority of the current pending interrupt,
38
+ /* 0xf means "non-standard IMPDEF PMU" */
153
+ * or NVIC_NOEXC_PRIO if no interrupt is pending
39
+ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 &&
154
+ */
40
+ FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
155
+ return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_PRIO;
156
+}
41
+}
157
+
42
+
158
+/* Return the value of the ISCR RETTOBASE bit:
43
/*
159
+ * 1 if there is exactly one active exception
44
* 64-bit feature tests via id registers.
160
+ * 0 if there is more than one active exception
45
*/
161
+ * UNKNOWN if there are no active exceptions (we choose 1,
46
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
162
+ * which matches the choice Cortex-M3 is documented as making).
47
FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
163
+ *
48
}
164
+ * NB: some versions of the documentation talk about this
49
165
+ * counting "active exceptions other than the one shown by IPSR";
50
+static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id)
166
+ * this is only different in the obscure corner case where guest
167
+ * code has manually deactivated an exception and is about
168
+ * to fail an exception-return integrity check. The definition
169
+ * above is the one from the v8M ARM ARM and is also in line
170
+ * with the behaviour documented for the Cortex-M3.
171
+ */
172
+static bool nvic_rettobase(NVICState *s)
173
+{
51
+{
174
+ int irq, nhand = 0;
52
+ return FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
175
+
53
+ FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
176
+ for (irq = ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) {
177
+ if (s->vectors[irq].active) {
178
+ nhand++;
179
+ if (nhand == 2) {
180
+ return 0;
181
+ }
182
+ }
183
+ }
184
+
185
+ return 1;
186
+}
54
+}
187
+
55
+
188
+/* Return the value of the ISCR ISRPENDING bit:
56
/*
189
+ * 1 if an external interrupt is pending
57
* Feature tests for "does this exist in either 32-bit or 64-bit?"
190
+ * 0 if no external interrupt is pending
58
*/
191
+ */
59
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id)
192
+static bool nvic_isrpending(NVICState *s)
60
return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id);
61
}
62
63
+static inline bool isar_feature_any_pmu_8_4(const ARMISARegisters *id)
193
+{
64
+{
194
+ int irq;
65
+ return isar_feature_aa64_pmu_8_4(id) || isar_feature_aa32_pmu_8_4(id);
195
+
196
+ /* We can shortcut if the highest priority pending interrupt
197
+ * happens to be external or if there is nothing pending.
198
+ */
199
+ if (s->vectpending > NVIC_FIRST_IRQ) {
200
+ return true;
201
+ }
202
+ if (s->vectpending == 0) {
203
+ return false;
204
+ }
205
+
206
+ for (irq = NVIC_FIRST_IRQ; irq < s->num_irq; irq++) {
207
+ if (s->vectors[irq].pending) {
208
+ return true;
209
+ }
210
+ }
211
+ return false;
212
+}
66
+}
213
+
67
+
214
+/* Return a mask word which clears the subpriority bits from
68
/*
215
+ * a priority value for an M-profile exception, leaving only
69
* Forward to the above feature tests given an ARMCPU pointer.
216
+ * the group priority.
70
*/
217
+ */
71
diff --git a/target/arm/helper.c b/target/arm/helper.c
218
+static inline uint32_t nvic_gprio_mask(NVICState *s)
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/helper.c
74
+++ b/target/arm/helper.c
75
@@ -XXX,XX +XXX,XX @@ static bool pmu_8_1_events_supported(CPUARMState *env)
76
return cpu_isar_feature(any_pmu_8_1, env_archcpu(env));
77
}
78
79
+static bool pmu_8_4_events_supported(CPUARMState *env)
219
+{
80
+{
220
+ return ~0U << (s->prigroup + 1);
81
+ /* For events which are supported in any v8.1 PMU */
82
+ return cpu_isar_feature(any_pmu_8_4, env_archcpu(env));
221
+}
83
+}
222
+
84
+
223
+/* Recompute vectpending and exception_prio */
85
static uint64_t zero_event_get_count(CPUARMState *env)
224
+static void nvic_recompute_state(NVICState *s)
225
+{
226
+ int i;
227
+ int pend_prio = NVIC_NOEXC_PRIO;
228
+ int active_prio = NVIC_NOEXC_PRIO;
229
+ int pend_irq = 0;
230
+
231
+ for (i = 1; i < s->num_irq; i++) {
232
+ VecInfo *vec = &s->vectors[i];
233
+
234
+ if (vec->enabled && vec->pending && vec->prio < pend_prio) {
235
+ pend_prio = vec->prio;
236
+ pend_irq = i;
237
+ }
238
+ if (vec->active && vec->prio < active_prio) {
239
+ active_prio = vec->prio;
240
+ }
241
+ }
242
+
243
+ s->vectpending = pend_irq;
244
+ s->exception_prio = active_prio & nvic_gprio_mask(s);
245
+
246
+ trace_nvic_recompute_state(s->vectpending, s->exception_prio);
247
+}
248
+
249
+/* Return the current execution priority of the CPU
250
+ * (equivalent to the pseudocode ExecutionPriority function).
251
+ * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO.
252
+ */
253
+static inline int nvic_exec_prio(NVICState *s)
254
+{
255
+ CPUARMState *env = &s->cpu->env;
256
+ int running;
257
+
258
+ if (env->daif & PSTATE_F) { /* FAULTMASK */
259
+ running = -1;
260
+ } else if (env->daif & PSTATE_I) { /* PRIMASK */
261
+ running = 0;
262
+ } else if (env->v7m.basepri > 0) {
263
+ running = env->v7m.basepri & nvic_gprio_mask(s);
264
+ } else {
265
+ running = NVIC_NOEXC_PRIO; /* lower than any possible priority */
266
+ }
267
+ /* consider priority of active handler */
268
+ return MIN(running, s->exception_prio);
269
+}
270
+
271
+/* caller must call nvic_irq_update() after this */
272
+static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
273
+{
274
+ assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */
275
+ assert(irq < s->num_irq);
276
+
277
+ s->vectors[irq].prio = prio;
278
+
279
+ trace_nvic_set_prio(irq, prio);
280
+}
281
+
282
+/* Recompute state and assert irq line accordingly.
283
+ * Must be called after changes to:
284
+ * vec->active, vec->enabled, vec->pending or vec->prio for any vector
285
+ * prigroup
286
+ */
287
+static void nvic_irq_update(NVICState *s)
288
+{
289
+ int lvl;
290
+ int pend_prio;
291
+
292
+ nvic_recompute_state(s);
293
+ pend_prio = nvic_pending_prio(s);
294
+
295
+ /* Raise NVIC output if this IRQ would be taken, except that we
296
+ * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which
297
+ * will be checked for in arm_v7m_cpu_exec_interrupt()); changes
298
+ * to those CPU registers don't cause us to recalculate the NVIC
299
+ * pending info.
300
+ */
301
+ lvl = (pend_prio < s->exception_prio);
302
+ trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lvl);
303
+ qemu_set_irq(s->excpout, lvl);
304
+}
305
+
306
+static void armv7m_nvic_clear_pending(void *opaque, int irq)
307
+{
308
+ NVICState *s = (NVICState *)opaque;
309
+ VecInfo *vec;
310
+
311
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
312
+
313
+ vec = &s->vectors[irq];
314
+ trace_nvic_clear_pending(irq, vec->enabled, vec->prio);
315
+ if (vec->pending) {
316
+ vec->pending = 0;
317
+ nvic_irq_update(s);
318
+ }
319
+}
320
+
321
void armv7m_nvic_set_pending(void *opaque, int irq)
322
{
86
{
323
NVICState *s = (NVICState *)opaque;
87
/* For events which on QEMU never fire, so their count is always zero */
324
- if (irq >= 16)
88
@@ -XXX,XX +XXX,XX @@ static const pm_event pm_events[] = {
325
- irq += 16;
89
.get_count = zero_event_get_count,
326
- gic_set_pending_private(&s->gic, 0, irq);
90
.ns_per_count = zero_event_ns_per,
327
+ VecInfo *vec;
91
},
328
+
92
+ { .number = 0x03c, /* STALL */
329
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
93
+ .supported = pmu_8_4_events_supported,
330
+
94
+ .get_count = zero_event_get_count,
331
+ vec = &s->vectors[irq];
95
+ .ns_per_count = zero_event_ns_per,
332
+ trace_nvic_set_pending(irq, vec->enabled, vec->prio);
96
+ },
333
+ if (!vec->pending) {
97
};
334
+ vec->pending = 1;
98
335
+ nvic_irq_update(s);
99
/*
100
@@ -XXX,XX +XXX,XX @@ static const pm_event pm_events[] = {
101
* should first be updated to something sparse instead of the current
102
* supported_event_map[] array.
103
*/
104
-#define MAX_EVENT_ID 0x24
105
+#define MAX_EVENT_ID 0x3c
106
#define UNSUPPORTED_EVENT UINT16_MAX
107
static uint16_t supported_event_map[MAX_EVENT_ID + 1];
108
109
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
110
};
111
define_arm_cp_regs(cpu, v81_pmu_regs);
112
}
113
+ if (cpu_isar_feature(any_pmu_8_4, cpu)) {
114
+ static const ARMCPRegInfo v84_pmmir = {
115
+ .name = "PMMIR_EL1", .state = ARM_CP_STATE_BOTH,
116
+ .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 6,
117
+ .access = PL1_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
118
+ .resetvalue = 0
119
+ };
120
+ define_one_arm_cp_reg(cpu, &v84_pmmir);
336
+ }
121
+ }
337
}
122
}
338
123
339
/* Make pending IRQ active. */
124
/* We don't know until after realize whether there's a GICv3
340
int armv7m_nvic_acknowledge_irq(void *opaque)
341
{
342
NVICState *s = (NVICState *)opaque;
343
- uint32_t irq;
344
-
345
- irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
346
- if (irq == 1023)
347
- hw_error("Interrupt but no vector\n");
348
- if (irq >= 32)
349
- irq -= 16;
350
- return irq;
351
+ CPUARMState *env = &s->cpu->env;
352
+ const int pending = s->vectpending;
353
+ const int running = nvic_exec_prio(s);
354
+ int pendgroupprio;
355
+ VecInfo *vec;
356
+
357
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
358
+
359
+ vec = &s->vectors[pending];
360
+
361
+ assert(vec->enabled);
362
+ assert(vec->pending);
363
+
364
+ pendgroupprio = vec->prio & nvic_gprio_mask(s);
365
+ assert(pendgroupprio < running);
366
+
367
+ trace_nvic_acknowledge_irq(pending, vec->prio);
368
+
369
+ vec->active = 1;
370
+ vec->pending = 0;
371
+
372
+ env->v7m.exception = s->vectpending;
373
+
374
+ nvic_irq_update(s);
375
+
376
+ return env->v7m.exception;
377
}
378
379
void armv7m_nvic_complete_irq(void *opaque, int irq)
380
{
381
NVICState *s = (NVICState *)opaque;
382
- if (irq >= 16)
383
- irq += 16;
384
- gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
385
+ VecInfo *vec;
386
+
387
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
388
+
389
+ vec = &s->vectors[irq];
390
+
391
+ trace_nvic_complete_irq(irq);
392
+
393
+ vec->active = 0;
394
+ if (vec->level) {
395
+ /* Re-pend the exception if it's still held high; only
396
+ * happens for extenal IRQs
397
+ */
398
+ assert(irq >= NVIC_FIRST_IRQ);
399
+ vec->pending = 1;
400
+ }
401
+
402
+ nvic_irq_update(s);
403
+}
404
+
405
+/* callback when external interrupt line is changed */
406
+static void set_irq_level(void *opaque, int n, int level)
407
+{
408
+ NVICState *s = opaque;
409
+ VecInfo *vec;
410
+
411
+ n += NVIC_FIRST_IRQ;
412
+
413
+ assert(n >= NVIC_FIRST_IRQ && n < s->num_irq);
414
+
415
+ trace_nvic_set_irq_level(n, level);
416
+
417
+ /* The pending status of an external interrupt is
418
+ * latched on rising edge and exception handler return.
419
+ *
420
+ * Pulsing the IRQ will always run the handler
421
+ * once, and the handler will re-run until the
422
+ * level is low when the handler completes.
423
+ */
424
+ vec = &s->vectors[n];
425
+ if (level != vec->level) {
426
+ vec->level = level;
427
+ if (level) {
428
+ armv7m_nvic_set_pending(s, n);
429
+ }
430
+ }
431
}
432
433
static uint32_t nvic_readl(NVICState *s, uint32_t offset)
434
{
435
ARMCPU *cpu = s->cpu;
436
uint32_t val;
437
- int irq;
438
439
switch (offset) {
440
case 4: /* Interrupt Control Type. */
441
- return (s->num_irq / 32) - 1;
442
+ return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
443
case 0x10: /* SysTick Control and Status. */
444
val = s->systick.control;
445
s->systick.control &= ~SYSTICK_COUNTFLAG;
446
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
447
case 0xd04: /* Interrupt Control State. */
448
/* VECTACTIVE */
449
val = cpu->env.v7m.exception;
450
- if (val == 1023) {
451
- val = 0;
452
- } else if (val >= 32) {
453
- val -= 16;
454
- }
455
/* VECTPENDING */
456
- if (s->gic.current_pending[0] != 1023)
457
- val |= (s->gic.current_pending[0] << 12);
458
- /* ISRPENDING and RETTOBASE */
459
- for (irq = 32; irq < s->num_irq; irq++) {
460
- if (s->gic.irq_state[irq].pending) {
461
- val |= (1 << 22);
462
- break;
463
- }
464
- if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
465
- val |= (1 << 11);
466
- }
467
+ val |= (s->vectpending & 0xff) << 12;
468
+ /* ISRPENDING - set if any external IRQ is pending */
469
+ if (nvic_isrpending(s)) {
470
+ val |= (1 << 22);
471
+ }
472
+ /* RETTOBASE - set if only one handler is active */
473
+ if (nvic_rettobase(s)) {
474
+ val |= (1 << 11);
475
}
476
/* PENDSTSET */
477
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
478
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) {
479
val |= (1 << 26);
480
+ }
481
/* PENDSVSET */
482
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
483
+ if (s->vectors[ARMV7M_EXCP_PENDSV].pending) {
484
val |= (1 << 28);
485
+ }
486
/* NMIPENDSET */
487
- if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
488
+ if (s->vectors[ARMV7M_EXCP_NMI].pending) {
489
val |= (1 << 31);
490
+ }
491
+ /* ISRPREEMPT not implemented */
492
return val;
493
case 0xd08: /* Vector Table Offset. */
494
return cpu->env.v7m.vecbase;
495
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
496
return cpu->env.v7m.ccr;
497
case 0xd24: /* System Handler Status. */
498
val = 0;
499
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
500
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
501
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
502
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
503
- if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
504
- if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
505
- if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
506
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
507
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
508
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
509
- if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
510
- if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
511
- if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
512
- if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
513
+ if (s->vectors[ARMV7M_EXCP_MEM].active) {
514
+ val |= (1 << 0);
515
+ }
516
+ if (s->vectors[ARMV7M_EXCP_BUS].active) {
517
+ val |= (1 << 1);
518
+ }
519
+ if (s->vectors[ARMV7M_EXCP_USAGE].active) {
520
+ val |= (1 << 3);
521
+ }
522
+ if (s->vectors[ARMV7M_EXCP_SVC].active) {
523
+ val |= (1 << 7);
524
+ }
525
+ if (s->vectors[ARMV7M_EXCP_DEBUG].active) {
526
+ val |= (1 << 8);
527
+ }
528
+ if (s->vectors[ARMV7M_EXCP_PENDSV].active) {
529
+ val |= (1 << 10);
530
+ }
531
+ if (s->vectors[ARMV7M_EXCP_SYSTICK].active) {
532
+ val |= (1 << 11);
533
+ }
534
+ if (s->vectors[ARMV7M_EXCP_USAGE].pending) {
535
+ val |= (1 << 12);
536
+ }
537
+ if (s->vectors[ARMV7M_EXCP_MEM].pending) {
538
+ val |= (1 << 13);
539
+ }
540
+ if (s->vectors[ARMV7M_EXCP_BUS].pending) {
541
+ val |= (1 << 14);
542
+ }
543
+ if (s->vectors[ARMV7M_EXCP_SVC].pending) {
544
+ val |= (1 << 15);
545
+ }
546
+ if (s->vectors[ARMV7M_EXCP_MEM].enabled) {
547
+ val |= (1 << 16);
548
+ }
549
+ if (s->vectors[ARMV7M_EXCP_BUS].enabled) {
550
+ val |= (1 << 17);
551
+ }
552
+ if (s->vectors[ARMV7M_EXCP_USAGE].enabled) {
553
+ val |= (1 << 18);
554
+ }
555
return val;
556
case 0xd28: /* Configurable Fault Status. */
557
return cpu->env.v7m.cfsr;
558
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
559
if (value & (1 << 28)) {
560
armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
561
} else if (value & (1 << 27)) {
562
- s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
563
- gic_update(&s->gic);
564
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV);
565
}
566
if (value & (1 << 26)) {
567
armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
568
} else if (value & (1 << 25)) {
569
- s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
570
- gic_update(&s->gic);
571
+ armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK);
572
}
573
break;
574
case 0xd08: /* Vector Table Offset. */
575
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
576
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
577
}
578
s->prigroup = extract32(value, 8, 3);
579
+ nvic_irq_update(s);
580
}
581
break;
582
case 0xd10: /* System Control. */
583
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
584
case 0xd24: /* System Handler Control. */
585
/* TODO: Real hardware allows you to set/clear the active bits
586
under some circumstances. We don't implement this. */
587
- s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
588
- s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
589
- s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
590
+ s->vectors[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
591
+ s->vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
592
+ s->vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
593
+ nvic_irq_update(s);
594
break;
595
case 0xd28: /* Configurable Fault Status. */
596
cpu->env.v7m.cfsr &= ~value; /* W1C */
597
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
598
"NVIC: Aux fault status registers unimplemented\n");
599
break;
600
case 0xf00: /* Software Triggered Interrupt Register */
601
+ {
602
/* user mode can only write to STIR if CCR.USERSETMPEND permits it */
603
- if ((value & 0x1ff) < s->num_irq &&
604
+ int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
605
+ if (excnum < s->num_irq &&
606
(arm_current_el(&cpu->env) ||
607
(cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
608
- gic_set_pending_private(&s->gic, 0, value & 0x1ff);
609
+ armv7m_nvic_set_pending(s, excnum);
610
}
611
break;
612
+ }
613
default:
614
qemu_log_mask(LOG_GUEST_ERROR,
615
"NVIC: Bad write offset 0x%x\n", offset);
616
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
617
{
618
NVICState *s = (NVICState *)opaque;
619
uint32_t offset = addr;
620
- int i;
621
+ unsigned i, startvec, end;
622
uint32_t val;
623
624
switch (offset) {
625
+ /* reads of set and clear both return the status */
626
+ case 0x100 ... 0x13f: /* NVIC Set enable */
627
+ offset += 0x80;
628
+ /* fall through */
629
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
630
+ val = 0;
631
+ startvec = offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */
632
+
633
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
634
+ if (s->vectors[startvec + i].enabled) {
635
+ val |= (1 << i);
636
+ }
637
+ }
638
+ break;
639
+ case 0x200 ... 0x23f: /* NVIC Set pend */
640
+ offset += 0x80;
641
+ /* fall through */
642
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
643
+ val = 0;
644
+ startvec = offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */
645
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
646
+ if (s->vectors[startvec + i].pending) {
647
+ val |= (1 << i);
648
+ }
649
+ }
650
+ break;
651
+ case 0x300 ... 0x33f: /* NVIC Active */
652
+ val = 0;
653
+ startvec = offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */
654
+
655
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
656
+ if (s->vectors[startvec + i].active) {
657
+ val |= (1 << i);
658
+ }
659
+ }
660
+ break;
661
+ case 0x400 ... 0x5ef: /* NVIC Priority */
662
+ val = 0;
663
+ startvec = offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */
664
+
665
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
666
+ val |= s->vectors[startvec + i].prio << (8 * i);
667
+ }
668
+ break;
669
case 0xd18 ... 0xd23: /* System Handler Priority. */
670
val = 0;
671
for (i = 0; i < size; i++) {
672
- val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
673
+ val |= s->vectors[(offset - 0xd14) + i].prio << (i * 8);
674
}
675
- return val;
676
+ break;
677
case 0xfe0 ... 0xfff: /* ID. */
678
if (offset & 3) {
679
- return 0;
680
+ val = 0;
681
+ } else {
682
+ val = nvic_id[(offset - 0xfe0) >> 2];
683
+ }
684
+ break;
685
+ default:
686
+ if (size == 4) {
687
+ val = nvic_readl(s, offset);
688
+ } else {
689
+ qemu_log_mask(LOG_GUEST_ERROR,
690
+ "NVIC: Bad read of size %d at offset 0x%x\n",
691
+ size, offset);
692
+ val = 0;
693
}
694
- return nvic_id[(offset - 0xfe0) >> 2];
695
- }
696
- if (size == 4) {
697
- return nvic_readl(s, offset);
698
}
699
- qemu_log_mask(LOG_GUEST_ERROR,
700
- "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
701
- return 0;
702
+
703
+ trace_nvic_sysreg_read(addr, val, size);
704
+ return val;
705
}
706
707
static void nvic_sysreg_write(void *opaque, hwaddr addr,
708
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
709
{
710
NVICState *s = (NVICState *)opaque;
711
uint32_t offset = addr;
712
- int i;
713
+ unsigned i, startvec, end;
714
+ unsigned setval = 0;
715
+
716
+ trace_nvic_sysreg_write(addr, value, size);
717
718
switch (offset) {
719
+ case 0x100 ... 0x13f: /* NVIC Set enable */
720
+ offset += 0x80;
721
+ setval = 1;
722
+ /* fall through */
723
+ case 0x180 ... 0x1bf: /* NVIC Clear enable */
724
+ startvec = 8 * (offset - 0x180) + NVIC_FIRST_IRQ;
725
+
726
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
727
+ if (value & (1 << i)) {
728
+ s->vectors[startvec + i].enabled = setval;
729
+ }
730
+ }
731
+ nvic_irq_update(s);
732
+ return;
733
+ case 0x200 ... 0x23f: /* NVIC Set pend */
734
+ /* the special logic in armv7m_nvic_set_pending()
735
+ * is not needed since IRQs are never escalated
736
+ */
737
+ offset += 0x80;
738
+ setval = 1;
739
+ /* fall through */
740
+ case 0x280 ... 0x2bf: /* NVIC Clear pend */
741
+ startvec = 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */
742
+
743
+ for (i = 0, end = size * 8; i < end && startvec + i < s->num_irq; i++) {
744
+ if (value & (1 << i)) {
745
+ s->vectors[startvec + i].pending = setval;
746
+ }
747
+ }
748
+ nvic_irq_update(s);
749
+ return;
750
+ case 0x300 ... 0x33f: /* NVIC Active */
751
+ return; /* R/O */
752
+ case 0x400 ... 0x5ef: /* NVIC Priority */
753
+ startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
754
+
755
+ for (i = 0; i < size && startvec + i < s->num_irq; i++) {
756
+ set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
757
+ }
758
+ nvic_irq_update(s);
759
+ return;
760
case 0xd18 ... 0xd23: /* System Handler Priority. */
761
for (i = 0; i < size; i++) {
762
- s->gic.priority1[(offset - 0xd14) + i][0] =
763
- (value >> (i * 8)) & 0xff;
764
+ unsigned hdlidx = (offset - 0xd14) + i;
765
+ set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
766
}
767
- gic_update(&s->gic);
768
+ nvic_irq_update(s);
769
return;
770
}
771
if (size == 4) {
772
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
773
.endianness = DEVICE_NATIVE_ENDIAN,
774
};
775
776
+static int nvic_post_load(void *opaque, int version_id)
777
+{
778
+ NVICState *s = opaque;
779
+ unsigned i;
780
+
781
+ /* Check for out of range priority settings */
782
+ if (s->vectors[ARMV7M_EXCP_RESET].prio != -3 ||
783
+ s->vectors[ARMV7M_EXCP_NMI].prio != -2 ||
784
+ s->vectors[ARMV7M_EXCP_HARD].prio != -1) {
785
+ return 1;
786
+ }
787
+ for (i = ARMV7M_EXCP_MEM; i < s->num_irq; i++) {
788
+ if (s->vectors[i].prio & ~0xff) {
789
+ return 1;
790
+ }
791
+ }
792
+
793
+ nvic_recompute_state(s);
794
+
795
+ return 0;
796
+}
797
+
798
+static const VMStateDescription vmstate_VecInfo = {
799
+ .name = "armv7m_nvic_info",
800
+ .version_id = 1,
801
+ .minimum_version_id = 1,
802
+ .fields = (VMStateField[]) {
803
+ VMSTATE_INT16(prio, VecInfo),
804
+ VMSTATE_UINT8(enabled, VecInfo),
805
+ VMSTATE_UINT8(pending, VecInfo),
806
+ VMSTATE_UINT8(active, VecInfo),
807
+ VMSTATE_UINT8(level, VecInfo),
808
+ VMSTATE_END_OF_LIST()
809
+ }
810
+};
811
+
812
static const VMStateDescription vmstate_nvic = {
813
.name = "armv7m_nvic",
814
- .version_id = 2,
815
- .minimum_version_id = 2,
816
+ .version_id = 3,
817
+ .minimum_version_id = 3,
818
+ .post_load = &nvic_post_load,
819
.fields = (VMStateField[]) {
820
+ VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
821
+ vmstate_VecInfo, VecInfo),
822
VMSTATE_UINT32(systick.control, NVICState),
823
VMSTATE_UINT32(systick.reload, NVICState),
824
VMSTATE_INT64(systick.tick, NVICState),
825
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
826
}
827
};
828
829
+static Property props_nvic[] = {
830
+ /* Number of external IRQ lines (so excluding the 16 internal exceptions) */
831
+ DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64),
832
+ DEFINE_PROP_END_OF_LIST()
833
+};
834
+
835
static void armv7m_nvic_reset(DeviceState *dev)
836
{
837
NVICState *s = NVIC(dev);
838
- NVICClass *nc = NVIC_GET_CLASS(s);
839
- nc->parent_reset(dev);
840
- /* Common GIC reset resets to disabled; the NVIC doesn't have
841
- * per-CPU interfaces so mark our non-existent CPU interface
842
- * as enabled by default, and with a priority mask which allows
843
- * all interrupts through.
844
+
845
+ s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
846
+ s->vectors[ARMV7M_EXCP_HARD].enabled = 1;
847
+ /* MEM, BUS, and USAGE are enabled through
848
+ * the System Handler Control register
849
*/
850
- s->gic.cpu_ctlr[0] = GICC_CTLR_EN_GRP0;
851
- s->gic.priority_mask[0] = 0x100;
852
- /* The NVIC as a whole is always enabled. */
853
- s->gic.ctlr = 1;
854
+ s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
855
+ s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
856
+ s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
857
+ s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
858
+
859
+ s->vectors[ARMV7M_EXCP_RESET].prio = -3;
860
+ s->vectors[ARMV7M_EXCP_NMI].prio = -2;
861
+ s->vectors[ARMV7M_EXCP_HARD].prio = -1;
862
+
863
+ /* Strictly speaking the reset handler should be enabled.
864
+ * However, we don't simulate soft resets through the NVIC,
865
+ * and the reset vector should never be pended.
866
+ * So we leave it disabled to catch logic errors.
867
+ */
868
+
869
+ s->exception_prio = NVIC_NOEXC_PRIO;
870
+ s->vectpending = 0;
871
+
872
systick_reset(s);
873
}
874
875
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
876
{
877
NVICState *s = NVIC(dev);
878
- NVICClass *nc = NVIC_GET_CLASS(s);
879
- Error *local_err = NULL;
880
881
s->cpu = ARM_CPU(qemu_get_cpu(0));
882
assert(s->cpu);
883
- /* The NVIC always has only one CPU */
884
- s->gic.num_cpu = 1;
885
- /* Tell the common code we're an NVIC */
886
- s->gic.revision = 0xffffffff;
887
- s->num_irq = s->gic.num_irq;
888
- nc->parent_realize(dev, &local_err);
889
- if (local_err) {
890
- error_propagate(errp, local_err);
891
+
892
+ if (s->num_irq > NVIC_MAX_IRQ) {
893
+ error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
894
return;
895
}
896
- gic_init_irqs_and_distributor(&s->gic);
897
- /* The NVIC and system controller register area looks like this:
898
- * 0..0xff : system control registers, including systick
899
- * 0x100..0xcff : GIC-like registers
900
- * 0xd00..0xfff : system control registers
901
- * We use overlaying to put the GIC like registers
902
- * over the top of the system control register region.
903
+
904
+ qdev_init_gpio_in(dev, set_irq_level, s->num_irq);
905
+
906
+ /* include space for internal exception vectors */
907
+ s->num_irq += NVIC_FIRST_IRQ;
908
+
909
+ /* The NVIC and System Control Space (SCS) starts at 0xe000e000
910
+ * and looks like this:
911
+ * 0x004 - ICTR
912
+ * 0x010 - 0x1c - systick
913
+ * 0x100..0x7ec - NVIC
914
+ * 0x7f0..0xcff - Reserved
915
+ * 0xd00..0xd3c - SCS registers
916
+ * 0xd40..0xeff - Reserved or Not implemented
917
+ * 0xf00 - STIR
918
+ *
919
+ * At the moment there is only one thing in the container region,
920
+ * but we leave it in place to allow us to pull systick out into
921
+ * its own device object later.
922
*/
923
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
924
/* The system register region goes at the bottom of the priority
925
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
926
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
927
"nvic_sysregs", 0x1000);
928
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
929
- /* Alias the GIC region so we can get only the section of it
930
- * we need, and layer it on top of the system register region.
931
- */
932
- memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
933
- "nvic-gic", &s->gic.iomem,
934
- 0x100, 0xc00);
935
- memory_region_add_subregion_overlap(&s->container, 0x100,
936
- &s->gic_iomem_alias, 1);
937
+
938
/* Map the whole thing into system memory at the location required
939
* by the v7M architecture.
940
*/
941
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
942
* any user-specified property setting, so just modify the
943
* value in the GICState struct.
944
*/
945
- GICState *s = ARM_GIC_COMMON(obj);
946
DeviceState *dev = DEVICE(obj);
947
NVICState *nvic = NVIC(obj);
948
- /* The ARM v7m may have anything from 0 to 496 external interrupt
949
- * IRQ lines. We default to 64. Other boards may differ and should
950
- * set the num-irq property appropriately.
951
- */
952
- s->num_irq = 64;
953
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
954
+
955
+ sysbus_init_irq(sbd, &nvic->excpout);
956
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
957
}
958
959
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
960
{
961
- NVICClass *nc = NVIC_CLASS(klass);
962
DeviceClass *dc = DEVICE_CLASS(klass);
963
964
- nc->parent_reset = dc->reset;
965
- nc->parent_realize = dc->realize;
966
dc->vmsd = &vmstate_nvic;
967
+ dc->props = props_nvic;
968
dc->reset = armv7m_nvic_reset;
969
dc->realize = armv7m_nvic_realize;
970
}
971
972
static const TypeInfo armv7m_nvic_info = {
973
.name = TYPE_NVIC,
974
- .parent = TYPE_ARM_GIC_COMMON,
975
+ .parent = TYPE_SYS_BUS_DEVICE,
976
.instance_init = armv7m_nvic_instance_init,
977
.instance_size = sizeof(NVICState),
978
.class_init = armv7m_nvic_class_init,
979
- .class_size = sizeof(NVICClass),
980
+ .class_size = sizeof(SysBusDeviceClass),
981
};
982
983
static void armv7m_nvic_register_types(void)
984
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
985
index XXXXXXX..XXXXXXX 100644
986
--- a/hw/intc/trace-events
987
+++ b/hw/intc/trace-events
988
@@ -XXX,XX +XXX,XX @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size,
989
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
990
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
991
gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pending SGI %d"
992
+
993
+# hw/intc/armv7m_nvic.c
994
+nvic_recompute_state(int vectpending, int exception_prio) "NVIC state recomputed: vectpending %d exception_prio %d"
995
+nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d"
996
+nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
997
+nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
998
+nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
999
+nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enabled: %d priority %d)"
1000
+nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (enabled: %d priority %d)"
1001
+nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
1002
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
1003
+nvic_complete_irq(int irq) "NVIC complete IRQ %d"
1004
+nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
1005
+nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1006
+nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1007
--
125
--
1008
2.7.4
126
2.20.1
1009
127
1010
128
diff view generated by jsdifflib
New patch
1
Set the ID register bits to provide ARMv8.4-PMU (and implicitly
2
also ARMv8.1-PMU) in the 'max' CPU.
1
3
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20200214175116.9164-16-peter.maydell@linaro.org
7
---
8
target/arm/cpu64.c | 8 ++++++++
9
1 file changed, 8 insertions(+)
10
11
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu64.c
14
+++ b/target/arm/cpu64.c
15
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
16
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
17
cpu->id_mmfr3 = u;
18
19
+ u = cpu->isar.id_aa64dfr0;
20
+ u = FIELD_DP64(u, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
21
+ cpu->isar.id_aa64dfr0 = u;
22
+
23
+ u = cpu->isar.id_dfr0;
24
+ u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
25
+ cpu->isar.id_dfr0 = u;
26
+
27
/*
28
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
29
* so do not set MVFR1.FPHP. Strictly speaking this is not legal,
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
New patch
1
The PMCR_EL0.DP bit is bit 5, which is 0x20, not 0x10. 0x10 is 'X'.
2
Correct our #define of PMCRDP and add the missing PMCRX.
1
3
4
We do have the correct behaviour for handling the DP bit being
5
set, so this fixes a guest-visible bug.
6
7
Fixes: 033614c47de
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20200214175116.9164-17-peter.maydell@linaro.org
12
---
13
target/arm/helper.c | 3 ++-
14
1 file changed, 2 insertions(+), 1 deletion(-)
15
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
21
#define PMCRN_MASK 0xf800
22
#define PMCRN_SHIFT 11
23
#define PMCRLC 0x40
24
-#define PMCRDP 0x10
25
+#define PMCRDP 0x20
26
+#define PMCRX 0x10
27
#define PMCRD 0x8
28
#define PMCRC 0x4
29
#define PMCRP 0x2
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
The LC bit in the PMCR_EL0 register is supposed to be:
2
* read/write
3
* RES1 on an AArch64-only implementation
4
* an architecturally UNKNOWN value on reset
5
(and use of LC==0 by software is deprecated).
2
6
3
All the places in armv7m_cpu_do_interrupt() which pend an
7
We were implementing it incorrectly as read-only always zero,
4
exception in the NVIC are doing so for synchronous
8
though we do have all the code needed to test it and behave
5
exceptions. We know that we will always take some
9
accordingly.
6
exception in this case, so we can just acknowledge it
7
immediately, rather than returning and then immediately
8
being called again because the NVIC has raised its outbound
9
IRQ line.
10
10
11
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
11
Instead make it a read-write bit which resets to 1 always, which
12
[PMM: tweaked commit message; added DEBUG to the set of
12
satisfies all the architectural requirements above.
13
exceptions we handle immediately, since it is synchronous
13
14
when it results from the BKPT instruction]
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20200214175116.9164-18-peter.maydell@linaro.org
17
---
18
---
18
target/arm/helper.c | 15 +++++++++------
19
target/arm/helper.c | 13 +++++++++----
19
1 file changed, 9 insertions(+), 6 deletions(-)
20
1 file changed, 9 insertions(+), 4 deletions(-)
20
21
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
26
case EXCP_UDEF:
27
#define PMCRC 0x4
27
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
28
#define PMCRP 0x2
28
env->v7m.cfsr |= R_V7M_CFSR_UNDEFINSTR_MASK;
29
#define PMCRE 0x1
29
- return;
30
+/*
30
+ break;
31
+ * Mask of PMCR bits writeable by guest (not including WO bits like C, P,
31
case EXCP_NOCP:
32
+ * which can be written as 1 to trigger behaviour but which stay RAZ).
32
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
33
+ */
33
env->v7m.cfsr |= R_V7M_CFSR_NOCP_MASK;
34
+#define PMCR_WRITEABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE)
34
- return;
35
35
+ break;
36
#define PMXEVTYPER_P 0x80000000
36
case EXCP_SWI:
37
#define PMXEVTYPER_U 0x40000000
37
/* The PC already points to the next instruction. */
38
@@ -XXX,XX +XXX,XX @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
38
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
39
- return;
40
+ break;
41
case EXCP_PREFETCH_ABORT:
42
case EXCP_DATA_ABORT:
43
/* TODO: if we implemented the MPU registers, this is where we
44
* should set the MMFAR, etc from exception.fsr and exception.vaddress.
45
*/
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
47
- return;
48
+ break;
49
case EXCP_BKPT:
50
if (semihosting_enabled()) {
51
int nr;
52
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
53
}
54
}
39
}
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
56
- return;
57
+ break;
58
case EXCP_IRQ:
59
- armv7m_nvic_acknowledge_irq(env->nvic);
60
break;
61
case EXCP_EXCEPTION_EXIT:
62
do_v7m_exception_exit(env);
63
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
64
return; /* Never happens. Keep compiler happy. */
65
}
40
}
66
41
67
+ armv7m_nvic_acknowledge_irq(env->nvic);
42
- /* only the DP, X, D and E bits are writable */
68
+
43
- env->cp15.c9_pmcr &= ~0x39;
69
+ qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
44
- env->cp15.c9_pmcr |= (value & 0x39);
70
+
45
+ env->cp15.c9_pmcr &= ~PMCR_WRITEABLE_MASK;
71
/* Align stack pointer if the guest wants that */
46
+ env->cp15.c9_pmcr |= (value & PMCR_WRITEABLE_MASK);
72
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
47
73
env->regs[13] -= 4;
48
pmu_op_finish(env);
49
}
50
@@ -XXX,XX +XXX,XX @@ static void define_pmu_regs(ARMCPU *cpu)
51
.access = PL0_RW, .accessfn = pmreg_access,
52
.type = ARM_CP_IO,
53
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
54
- .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT),
55
+ .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT) |
56
+ PMCRLC,
57
.writefn = pmcr_write, .raw_writefn = raw_write,
58
};
59
define_one_arm_cp_reg(cpu, &pmcr);
74
--
60
--
75
2.7.4
61
2.20.1
76
62
77
63
diff view generated by jsdifflib
1
Having armv7m_nvic_acknowledge_irq() return the new value of
1
The isar_feature_aa32_pan and isar_feature_aa32_ats1e1 functions
2
env->v7m.exception and its one caller assign the return value
2
are supposed to be testing fields in ID_MMFR3; but a cut-and-paste
3
back to env->v7m.exception is pointless. Just make the return
3
error meant we were looking at MVFR0 instead.
4
type void instead.
5
4
5
Fix the functions to look at the right register; this requires
6
us to move at least id_mmfr3 to the ARMISARegisters struct; we
7
choose to move all the ID_MMFRn registers for consistency.
8
9
Fixes: 3d6ad6bb466f
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200214175116.9164-19-peter.maydell@linaro.org
8
---
13
---
9
target/arm/cpu.h | 2 +-
14
target/arm/cpu.h | 14 +++---
10
hw/intc/armv7m_nvic.c | 4 +---
15
hw/intc/armv7m_nvic.c | 8 ++--
11
target/arm/helper.c | 2 +-
16
target/arm/cpu.c | 104 +++++++++++++++++++++---------------------
12
3 files changed, 3 insertions(+), 5 deletions(-)
17
target/arm/cpu64.c | 28 ++++++------
18
target/arm/helper.c | 12 ++---
19
target/arm/kvm32.c | 17 +++++++
20
target/arm/kvm64.c | 10 ++++
21
7 files changed, 110 insertions(+), 83 deletions(-)
13
22
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
25
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
27
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
28
uint32_t id_isar4;
29
uint32_t id_isar5;
30
uint32_t id_isar6;
31
+ uint32_t id_mmfr0;
32
+ uint32_t id_mmfr1;
33
+ uint32_t id_mmfr2;
34
+ uint32_t id_mmfr3;
35
+ uint32_t id_mmfr4;
36
uint32_t mvfr0;
37
uint32_t mvfr1;
38
uint32_t mvfr2;
39
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
40
uint64_t pmceid0;
41
uint64_t pmceid1;
42
uint32_t id_afr0;
43
- uint32_t id_mmfr0;
44
- uint32_t id_mmfr1;
45
- uint32_t id_mmfr2;
46
- uint32_t id_mmfr3;
47
- uint32_t id_mmfr4;
48
uint64_t id_aa64afr0;
49
uint64_t id_aa64afr1;
50
uint32_t clidr;
51
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
52
53
static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
54
{
55
- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
56
+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0;
19
}
57
}
20
#endif
58
21
void armv7m_nvic_set_pending(void *opaque, int irq);
59
static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
22
-int armv7m_nvic_acknowledge_irq(void *opaque);
60
{
23
+void armv7m_nvic_acknowledge_irq(void *opaque);
61
- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
24
void armv7m_nvic_complete_irq(void *opaque, int irq);
62
+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2;
25
63
}
26
/* Interface for defining coprocessor registers.
64
65
static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
66
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
68
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
69
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
70
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
32
}
71
case 0xd4c: /* AFR0. */
33
72
return cpu->id_afr0;
34
/* Make pending IRQ active. */
73
case 0xd50: /* MMFR0. */
35
-int armv7m_nvic_acknowledge_irq(void *opaque)
74
- return cpu->id_mmfr0;
36
+void armv7m_nvic_acknowledge_irq(void *opaque)
75
+ return cpu->isar.id_mmfr0;
37
{
76
case 0xd54: /* MMFR1. */
38
NVICState *s = (NVICState *)opaque;
77
- return cpu->id_mmfr1;
39
CPUARMState *env = &s->cpu->env;
78
+ return cpu->isar.id_mmfr1;
40
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
79
case 0xd58: /* MMFR2. */
41
env->v7m.exception = s->vectpending;
80
- return cpu->id_mmfr2;
42
81
+ return cpu->isar.id_mmfr2;
43
nvic_irq_update(s);
82
case 0xd5c: /* MMFR3. */
44
-
83
- return cpu->id_mmfr3;
45
- return env->v7m.exception;
84
+ return cpu->isar.id_mmfr3;
46
}
85
case 0xd60: /* ISAR0. */
47
86
return cpu->isar.id_isar0;
48
void armv7m_nvic_complete_irq(void *opaque, int irq)
87
case 0xd64: /* ISAR1. */
88
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/cpu.c
91
+++ b/target/arm/cpu.c
92
@@ -XXX,XX +XXX,XX @@ static void arm1136_r2_initfn(Object *obj)
93
cpu->id_pfr1 = 0x1;
94
cpu->isar.id_dfr0 = 0x2;
95
cpu->id_afr0 = 0x3;
96
- cpu->id_mmfr0 = 0x01130003;
97
- cpu->id_mmfr1 = 0x10030302;
98
- cpu->id_mmfr2 = 0x01222110;
99
+ cpu->isar.id_mmfr0 = 0x01130003;
100
+ cpu->isar.id_mmfr1 = 0x10030302;
101
+ cpu->isar.id_mmfr2 = 0x01222110;
102
cpu->isar.id_isar0 = 0x00140011;
103
cpu->isar.id_isar1 = 0x12002111;
104
cpu->isar.id_isar2 = 0x11231111;
105
@@ -XXX,XX +XXX,XX @@ static void arm1136_initfn(Object *obj)
106
cpu->id_pfr1 = 0x1;
107
cpu->isar.id_dfr0 = 0x2;
108
cpu->id_afr0 = 0x3;
109
- cpu->id_mmfr0 = 0x01130003;
110
- cpu->id_mmfr1 = 0x10030302;
111
- cpu->id_mmfr2 = 0x01222110;
112
+ cpu->isar.id_mmfr0 = 0x01130003;
113
+ cpu->isar.id_mmfr1 = 0x10030302;
114
+ cpu->isar.id_mmfr2 = 0x01222110;
115
cpu->isar.id_isar0 = 0x00140011;
116
cpu->isar.id_isar1 = 0x12002111;
117
cpu->isar.id_isar2 = 0x11231111;
118
@@ -XXX,XX +XXX,XX @@ static void arm1176_initfn(Object *obj)
119
cpu->id_pfr1 = 0x11;
120
cpu->isar.id_dfr0 = 0x33;
121
cpu->id_afr0 = 0;
122
- cpu->id_mmfr0 = 0x01130003;
123
- cpu->id_mmfr1 = 0x10030302;
124
- cpu->id_mmfr2 = 0x01222100;
125
+ cpu->isar.id_mmfr0 = 0x01130003;
126
+ cpu->isar.id_mmfr1 = 0x10030302;
127
+ cpu->isar.id_mmfr2 = 0x01222100;
128
cpu->isar.id_isar0 = 0x0140011;
129
cpu->isar.id_isar1 = 0x12002111;
130
cpu->isar.id_isar2 = 0x11231121;
131
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
132
cpu->id_pfr1 = 0x1;
133
cpu->isar.id_dfr0 = 0;
134
cpu->id_afr0 = 0x2;
135
- cpu->id_mmfr0 = 0x01100103;
136
- cpu->id_mmfr1 = 0x10020302;
137
- cpu->id_mmfr2 = 0x01222000;
138
+ cpu->isar.id_mmfr0 = 0x01100103;
139
+ cpu->isar.id_mmfr1 = 0x10020302;
140
+ cpu->isar.id_mmfr2 = 0x01222000;
141
cpu->isar.id_isar0 = 0x00100011;
142
cpu->isar.id_isar1 = 0x12002111;
143
cpu->isar.id_isar2 = 0x11221011;
144
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
145
cpu->id_pfr1 = 0x00000200;
146
cpu->isar.id_dfr0 = 0x00100000;
147
cpu->id_afr0 = 0x00000000;
148
- cpu->id_mmfr0 = 0x00000030;
149
- cpu->id_mmfr1 = 0x00000000;
150
- cpu->id_mmfr2 = 0x00000000;
151
- cpu->id_mmfr3 = 0x00000000;
152
+ cpu->isar.id_mmfr0 = 0x00000030;
153
+ cpu->isar.id_mmfr1 = 0x00000000;
154
+ cpu->isar.id_mmfr2 = 0x00000000;
155
+ cpu->isar.id_mmfr3 = 0x00000000;
156
cpu->isar.id_isar0 = 0x01141110;
157
cpu->isar.id_isar1 = 0x02111000;
158
cpu->isar.id_isar2 = 0x21112231;
159
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
160
cpu->id_pfr1 = 0x00000200;
161
cpu->isar.id_dfr0 = 0x00100000;
162
cpu->id_afr0 = 0x00000000;
163
- cpu->id_mmfr0 = 0x00000030;
164
- cpu->id_mmfr1 = 0x00000000;
165
- cpu->id_mmfr2 = 0x00000000;
166
- cpu->id_mmfr3 = 0x00000000;
167
+ cpu->isar.id_mmfr0 = 0x00000030;
168
+ cpu->isar.id_mmfr1 = 0x00000000;
169
+ cpu->isar.id_mmfr2 = 0x00000000;
170
+ cpu->isar.id_mmfr3 = 0x00000000;
171
cpu->isar.id_isar0 = 0x01141110;
172
cpu->isar.id_isar1 = 0x02111000;
173
cpu->isar.id_isar2 = 0x21112231;
174
@@ -XXX,XX +XXX,XX @@ static void cortex_m7_initfn(Object *obj)
175
cpu->id_pfr1 = 0x00000200;
176
cpu->isar.id_dfr0 = 0x00100000;
177
cpu->id_afr0 = 0x00000000;
178
- cpu->id_mmfr0 = 0x00100030;
179
- cpu->id_mmfr1 = 0x00000000;
180
- cpu->id_mmfr2 = 0x01000000;
181
- cpu->id_mmfr3 = 0x00000000;
182
+ cpu->isar.id_mmfr0 = 0x00100030;
183
+ cpu->isar.id_mmfr1 = 0x00000000;
184
+ cpu->isar.id_mmfr2 = 0x01000000;
185
+ cpu->isar.id_mmfr3 = 0x00000000;
186
cpu->isar.id_isar0 = 0x01101110;
187
cpu->isar.id_isar1 = 0x02112000;
188
cpu->isar.id_isar2 = 0x20232231;
189
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
190
cpu->id_pfr1 = 0x00000210;
191
cpu->isar.id_dfr0 = 0x00200000;
192
cpu->id_afr0 = 0x00000000;
193
- cpu->id_mmfr0 = 0x00101F40;
194
- cpu->id_mmfr1 = 0x00000000;
195
- cpu->id_mmfr2 = 0x01000000;
196
- cpu->id_mmfr3 = 0x00000000;
197
+ cpu->isar.id_mmfr0 = 0x00101F40;
198
+ cpu->isar.id_mmfr1 = 0x00000000;
199
+ cpu->isar.id_mmfr2 = 0x01000000;
200
+ cpu->isar.id_mmfr3 = 0x00000000;
201
cpu->isar.id_isar0 = 0x01101110;
202
cpu->isar.id_isar1 = 0x02212000;
203
cpu->isar.id_isar2 = 0x20232232;
204
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
205
cpu->id_pfr1 = 0x001;
206
cpu->isar.id_dfr0 = 0x010400;
207
cpu->id_afr0 = 0x0;
208
- cpu->id_mmfr0 = 0x0210030;
209
- cpu->id_mmfr1 = 0x00000000;
210
- cpu->id_mmfr2 = 0x01200000;
211
- cpu->id_mmfr3 = 0x0211;
212
+ cpu->isar.id_mmfr0 = 0x0210030;
213
+ cpu->isar.id_mmfr1 = 0x00000000;
214
+ cpu->isar.id_mmfr2 = 0x01200000;
215
+ cpu->isar.id_mmfr3 = 0x0211;
216
cpu->isar.id_isar0 = 0x02101111;
217
cpu->isar.id_isar1 = 0x13112111;
218
cpu->isar.id_isar2 = 0x21232141;
219
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
220
cpu->id_pfr1 = 0x11;
221
cpu->isar.id_dfr0 = 0x400;
222
cpu->id_afr0 = 0;
223
- cpu->id_mmfr0 = 0x31100003;
224
- cpu->id_mmfr1 = 0x20000000;
225
- cpu->id_mmfr2 = 0x01202000;
226
- cpu->id_mmfr3 = 0x11;
227
+ cpu->isar.id_mmfr0 = 0x31100003;
228
+ cpu->isar.id_mmfr1 = 0x20000000;
229
+ cpu->isar.id_mmfr2 = 0x01202000;
230
+ cpu->isar.id_mmfr3 = 0x11;
231
cpu->isar.id_isar0 = 0x00101111;
232
cpu->isar.id_isar1 = 0x12112111;
233
cpu->isar.id_isar2 = 0x21232031;
234
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
235
cpu->id_pfr1 = 0x11;
236
cpu->isar.id_dfr0 = 0x000;
237
cpu->id_afr0 = 0;
238
- cpu->id_mmfr0 = 0x00100103;
239
- cpu->id_mmfr1 = 0x20000000;
240
- cpu->id_mmfr2 = 0x01230000;
241
- cpu->id_mmfr3 = 0x00002111;
242
+ cpu->isar.id_mmfr0 = 0x00100103;
243
+ cpu->isar.id_mmfr1 = 0x20000000;
244
+ cpu->isar.id_mmfr2 = 0x01230000;
245
+ cpu->isar.id_mmfr3 = 0x00002111;
246
cpu->isar.id_isar0 = 0x00101111;
247
cpu->isar.id_isar1 = 0x13112111;
248
cpu->isar.id_isar2 = 0x21232041;
249
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
250
cpu->id_pfr1 = 0x00011011;
251
cpu->isar.id_dfr0 = 0x02010555;
252
cpu->id_afr0 = 0x00000000;
253
- cpu->id_mmfr0 = 0x10101105;
254
- cpu->id_mmfr1 = 0x40000000;
255
- cpu->id_mmfr2 = 0x01240000;
256
- cpu->id_mmfr3 = 0x02102211;
257
+ cpu->isar.id_mmfr0 = 0x10101105;
258
+ cpu->isar.id_mmfr1 = 0x40000000;
259
+ cpu->isar.id_mmfr2 = 0x01240000;
260
+ cpu->isar.id_mmfr3 = 0x02102211;
261
/* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
262
* table 4-41 gives 0x02101110, which includes the arm div insns.
263
*/
264
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
265
cpu->id_pfr1 = 0x00011011;
266
cpu->isar.id_dfr0 = 0x02010555;
267
cpu->id_afr0 = 0x00000000;
268
- cpu->id_mmfr0 = 0x10201105;
269
- cpu->id_mmfr1 = 0x20000000;
270
- cpu->id_mmfr2 = 0x01240000;
271
- cpu->id_mmfr3 = 0x02102211;
272
+ cpu->isar.id_mmfr0 = 0x10201105;
273
+ cpu->isar.id_mmfr1 = 0x20000000;
274
+ cpu->isar.id_mmfr2 = 0x01240000;
275
+ cpu->isar.id_mmfr3 = 0x02102211;
276
cpu->isar.id_isar0 = 0x02101110;
277
cpu->isar.id_isar1 = 0x13112111;
278
cpu->isar.id_isar2 = 0x21232041;
279
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
280
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
281
cpu->isar.mvfr2 = t;
282
283
- t = cpu->id_mmfr3;
284
+ t = cpu->isar.id_mmfr3;
285
t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
286
- cpu->id_mmfr3 = t;
287
+ cpu->isar.id_mmfr3 = t;
288
289
- t = cpu->id_mmfr4;
290
+ t = cpu->isar.id_mmfr4;
291
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
292
- cpu->id_mmfr4 = t;
293
+ cpu->isar.id_mmfr4 = t;
294
}
295
#endif
296
}
297
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
298
index XXXXXXX..XXXXXXX 100644
299
--- a/target/arm/cpu64.c
300
+++ b/target/arm/cpu64.c
301
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
302
cpu->id_pfr1 = 0x00011011;
303
cpu->isar.id_dfr0 = 0x03010066;
304
cpu->id_afr0 = 0x00000000;
305
- cpu->id_mmfr0 = 0x10101105;
306
- cpu->id_mmfr1 = 0x40000000;
307
- cpu->id_mmfr2 = 0x01260000;
308
- cpu->id_mmfr3 = 0x02102211;
309
+ cpu->isar.id_mmfr0 = 0x10101105;
310
+ cpu->isar.id_mmfr1 = 0x40000000;
311
+ cpu->isar.id_mmfr2 = 0x01260000;
312
+ cpu->isar.id_mmfr3 = 0x02102211;
313
cpu->isar.id_isar0 = 0x02101110;
314
cpu->isar.id_isar1 = 0x13112111;
315
cpu->isar.id_isar2 = 0x21232042;
316
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
317
cpu->id_pfr1 = 0x00011011;
318
cpu->isar.id_dfr0 = 0x03010066;
319
cpu->id_afr0 = 0x00000000;
320
- cpu->id_mmfr0 = 0x10101105;
321
- cpu->id_mmfr1 = 0x40000000;
322
- cpu->id_mmfr2 = 0x01260000;
323
- cpu->id_mmfr3 = 0x02102211;
324
+ cpu->isar.id_mmfr0 = 0x10101105;
325
+ cpu->isar.id_mmfr1 = 0x40000000;
326
+ cpu->isar.id_mmfr2 = 0x01260000;
327
+ cpu->isar.id_mmfr3 = 0x02102211;
328
cpu->isar.id_isar0 = 0x02101110;
329
cpu->isar.id_isar1 = 0x13112111;
330
cpu->isar.id_isar2 = 0x21232042;
331
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
332
cpu->id_pfr1 = 0x00011011;
333
cpu->isar.id_dfr0 = 0x03010066;
334
cpu->id_afr0 = 0x00000000;
335
- cpu->id_mmfr0 = 0x10201105;
336
- cpu->id_mmfr1 = 0x40000000;
337
- cpu->id_mmfr2 = 0x01260000;
338
- cpu->id_mmfr3 = 0x02102211;
339
+ cpu->isar.id_mmfr0 = 0x10201105;
340
+ cpu->isar.id_mmfr1 = 0x40000000;
341
+ cpu->isar.id_mmfr2 = 0x01260000;
342
+ cpu->isar.id_mmfr3 = 0x02102211;
343
cpu->isar.id_isar0 = 0x02101110;
344
cpu->isar.id_isar1 = 0x13112111;
345
cpu->isar.id_isar2 = 0x21232042;
346
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
347
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
348
cpu->isar.id_isar6 = u;
349
350
- u = cpu->id_mmfr3;
351
+ u = cpu->isar.id_mmfr3;
352
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
353
- cpu->id_mmfr3 = u;
354
+ cpu->isar.id_mmfr3 = u;
355
356
u = cpu->isar.id_aa64dfr0;
357
u = FIELD_DP64(u, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
358
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
index XXXXXXX..XXXXXXX 100644
359
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/helper.c
360
--- a/target/arm/helper.c
52
+++ b/target/arm/helper.c
361
+++ b/target/arm/helper.c
53
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
362
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
54
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
363
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4,
55
return;
364
.access = PL1_R, .type = ARM_CP_CONST,
56
case EXCP_IRQ:
365
.accessfn = access_aa32_tid3,
57
- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
366
- .resetvalue = cpu->id_mmfr0 },
58
+ armv7m_nvic_acknowledge_irq(env->nvic);
367
+ .resetvalue = cpu->isar.id_mmfr0 },
59
break;
368
{ .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH,
60
case EXCP_EXCEPTION_EXIT:
369
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5,
61
do_v7m_exception_exit(env);
370
.access = PL1_R, .type = ARM_CP_CONST,
371
.accessfn = access_aa32_tid3,
372
- .resetvalue = cpu->id_mmfr1 },
373
+ .resetvalue = cpu->isar.id_mmfr1 },
374
{ .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH,
375
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6,
376
.access = PL1_R, .type = ARM_CP_CONST,
377
.accessfn = access_aa32_tid3,
378
- .resetvalue = cpu->id_mmfr2 },
379
+ .resetvalue = cpu->isar.id_mmfr2 },
380
{ .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH,
381
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7,
382
.access = PL1_R, .type = ARM_CP_CONST,
383
.accessfn = access_aa32_tid3,
384
- .resetvalue = cpu->id_mmfr3 },
385
+ .resetvalue = cpu->isar.id_mmfr3 },
386
{ .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH,
387
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
388
.access = PL1_R, .type = ARM_CP_CONST,
389
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
390
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
391
.access = PL1_R, .type = ARM_CP_CONST,
392
.accessfn = access_aa32_tid3,
393
- .resetvalue = cpu->id_mmfr4 },
394
+ .resetvalue = cpu->isar.id_mmfr4 },
395
{ .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH,
396
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
397
.access = PL1_R, .type = ARM_CP_CONST,
398
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
399
define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
400
define_arm_cp_regs(cpu, vmsa_cp_reginfo);
401
/* TTCBR2 is introduced with ARMv8.2-A32HPD. */
402
- if (FIELD_EX32(cpu->id_mmfr4, ID_MMFR4, HPDS) != 0) {
403
+ if (FIELD_EX32(cpu->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) {
404
define_one_arm_cp_reg(cpu, &ttbcr2_reginfo);
405
}
406
}
407
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
408
index XXXXXXX..XXXXXXX 100644
409
--- a/target/arm/kvm32.c
410
+++ b/target/arm/kvm32.c
411
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
412
* Fortunately there is not yet anything in there that affects migration.
413
*/
414
415
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
416
+ ARM_CP15_REG32(0, 0, 1, 4));
417
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
418
+ ARM_CP15_REG32(0, 0, 1, 5));
419
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
420
+ ARM_CP15_REG32(0, 0, 1, 6));
421
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
422
+ ARM_CP15_REG32(0, 0, 1, 7));
423
+ if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
424
+ ARM_CP15_REG32(0, 0, 2, 6))) {
425
+ /*
426
+ * Older kernels don't support reading ID_MMFR4 (a new in v8
427
+ * register); assume it's zero.
428
+ */
429
+ ahcf->isar.id_mmfr4 = 0;
430
+ }
431
+
432
/*
433
* There is no way to read DBGDIDR, because currently 32-bit KVM
434
* doesn't implement debug at all. Leave it at zero.
435
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/target/arm/kvm64.c
438
+++ b/target/arm/kvm64.c
439
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
440
*/
441
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
442
ARM64_SYS_REG(3, 0, 0, 1, 2));
443
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
444
+ ARM64_SYS_REG(3, 0, 0, 1, 4));
445
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
446
+ ARM64_SYS_REG(3, 0, 0, 1, 5));
447
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
448
+ ARM64_SYS_REG(3, 0, 0, 1, 6));
449
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
450
+ ARM64_SYS_REG(3, 0, 0, 1, 7));
451
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
452
ARM64_SYS_REG(3, 0, 0, 2, 0));
453
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
454
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
455
ARM64_SYS_REG(3, 0, 0, 2, 4));
456
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
457
ARM64_SYS_REG(3, 0, 0, 2, 5));
458
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
459
+ ARM64_SYS_REG(3, 0, 0, 2, 6));
460
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
461
ARM64_SYS_REG(3, 0, 0, 2, 7));
462
62
--
463
--
63
2.7.4
464
2.20.1
64
465
65
466
diff view generated by jsdifflib
1
Switch to using qcrypto_random_bytes() rather than rand() as
1
Now we have moved ID_MMFR4 into the ARMISARegisters struct, we
2
our source of randomness for the BCM2835 RNG.
2
can define and use an isar_feature for the presence of the
3
ARMv8.2-AA32HPD feature, rather than open-coding the test.
3
4
4
If qcrypto_random_bytes() fails, we don't want to return the guest a
5
While we're here, correct a comment typo which missed an 'A'
5
non-random value in case they're really using it for cryptographic
6
from the feature name.
6
purposes, so the best we can do is a fatal error. This shouldn't
7
happen unless something's broken, though.
8
9
In theory we could implement this device's full FIFO and interrupt
10
semantics and then just stop filling the FIFO. That's a lot of work,
11
though, and doesn't really give a very nice diagnostic to the user
12
since the guest will just seem to hang.
13
7
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200214175116.9164-20-peter.maydell@linaro.org
16
---
11
---
17
hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++-
12
target/arm/cpu.h | 5 +++++
18
1 file changed, 26 insertions(+), 1 deletion(-)
13
target/arm/helper.c | 4 ++--
14
2 files changed, 7 insertions(+), 2 deletions(-)
19
15
20
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/bcm2835_rng.c
18
--- a/target/arm/cpu.h
23
+++ b/hw/misc/bcm2835_rng.c
19
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id)
25
21
FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
26
#include "qemu/osdep.h"
22
}
27
#include "qemu/log.h"
23
28
+#include "qapi/error.h"
24
+static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
29
+#include "crypto/random.h"
30
#include "hw/misc/bcm2835_rng.h"
31
32
+static uint32_t get_random_bytes(void)
33
+{
25
+{
34
+ uint32_t res;
26
+ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0;
35
+ Error *err = NULL;
36
+
37
+ if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) {
38
+ /* On failure we don't want to return the guest a non-random
39
+ * value in case they're really using it for cryptographic
40
+ * purposes, so the best we can do is die here.
41
+ * This shouldn't happen unless something's broken.
42
+ * In theory we could implement this device's full FIFO
43
+ * and interrupt semantics and then just stop filling the
44
+ * FIFO. That's a lot of work, though, so we assume any
45
+ * errors are systematic problems and trust that if we didn't
46
+ * fail as the guest inited then we won't fail later on
47
+ * mid-run.
48
+ */
49
+ error_report_err(err);
50
+ exit(1);
51
+ }
52
+ return res;
53
+}
27
+}
54
+
28
+
55
static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
29
/*
56
unsigned size)
30
* 64-bit feature tests via id registers.
57
{
31
*/
58
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
59
res = s->rng_status | (1 << 24);
33
index XXXXXXX..XXXXXXX 100644
60
break;
34
--- a/target/arm/helper.c
61
case 0x8: /* rng_data */
35
+++ b/target/arm/helper.c
62
- res = rand();
36
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
63
+ res = get_random_bytes();
37
} else {
64
break;
38
define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo);
65
39
define_arm_cp_regs(cpu, vmsa_cp_reginfo);
66
default:
40
- /* TTCBR2 is introduced with ARMv8.2-A32HPD. */
41
- if (FIELD_EX32(cpu->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) {
42
+ /* TTCBR2 is introduced with ARMv8.2-AA32HPD. */
43
+ if (cpu_isar_feature(aa32_hpd, cpu)) {
44
define_one_arm_cp_reg(cpu, &ttbcr2_reginfo);
45
}
46
}
67
--
47
--
68
2.7.4
48
2.20.1
69
49
70
50
diff view generated by jsdifflib
1
Rename the nvic_state struct to NVICState, to match
1
Cut-and-paste errors mean we're using FIELD_EX64() to extract fields from
2
our naming conventions.
2
some 32-bit ID register fields. Use FIELD_EX32() instead. (This makes
3
no difference in behaviour, it's just more consistent.)
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 20200214175116.9164-21-peter.maydell@linaro.org
7
---
8
---
8
hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++----------------------
9
target/arm/cpu.h | 18 +++++++++---------
9
1 file changed, 22 insertions(+), 22 deletions(-)
10
1 file changed, 9 insertions(+), 9 deletions(-)
10
11
11
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/armv7m_nvic.c
14
--- a/target/arm/cpu.h
14
+++ b/hw/intc/armv7m_nvic.c
15
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
16
#include "gic_internal.h"
17
static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id)
17
#include "qemu/log.h"
18
19
-typedef struct {
20
+typedef struct NVICState {
21
GICState gic;
22
ARMCPU *cpu;
23
struct {
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
MemoryRegion container;
26
uint32_t num_irq;
27
qemu_irq sysresetreq;
28
-} nvic_state;
29
+} NVICState;
30
31
#define TYPE_NVIC "armv7m_nvic"
32
/**
33
@@ -XXX,XX +XXX,XX @@ typedef struct NVICClass {
34
#define NVIC_GET_CLASS(obj) \
35
OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
36
#define NVIC(obj) \
37
- OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
39
40
static const uint8_t nvic_id[] = {
41
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
42
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
43
int system_clock_scale;
44
45
/* Conversion factor from qemu timer to SysTick frequencies. */
46
-static inline int64_t systick_scale(nvic_state *s)
47
+static inline int64_t systick_scale(NVICState *s)
48
{
18
{
49
if (s->systick.control & SYSTICK_CLKSOURCE)
19
/* Return true if D16-D31 are implemented */
50
return system_clock_scale;
20
- return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2;
51
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(nvic_state *s)
21
+ return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2;
52
return 1000;
53
}
22
}
54
23
55
-static void systick_reload(nvic_state *s, int reset)
24
static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
56
+static void systick_reload(NVICState *s, int reset)
57
{
25
{
58
/* The Cortex-M3 Devices Generic User Guide says that "When the
26
- return FIELD_EX64(id->mvfr0, MVFR0, FPSHVEC) > 0;
59
* ENABLE bit is set to 1, the counter loads the RELOAD value from the
27
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
60
@@ -XXX,XX +XXX,XX @@ static void systick_reload(nvic_state *s, int reset)
28
}
61
29
62
static void systick_timer_tick(void * opaque)
30
static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
63
{
31
{
64
- nvic_state *s = (nvic_state *)opaque;
32
/* Return true if CPU supports double precision floating point */
65
+ NVICState *s = (NVICState *)opaque;
33
- return FIELD_EX64(id->mvfr0, MVFR0, FPDP) > 0;
66
s->systick.control |= SYSTICK_COUNTFLAG;
34
+ return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
67
if (s->systick.control & SYSTICK_TICKINT) {
68
/* Trigger the interrupt. */
69
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void * opaque)
70
}
71
}
35
}
72
36
73
-static void systick_reset(nvic_state *s)
37
/*
74
+static void systick_reset(NVICState *s)
38
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
39
*/
40
static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
75
{
41
{
76
s->systick.control = 0;
42
- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0;
77
s->systick.reload = 0;
43
+ return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0;
78
@@ -XXX,XX +XXX,XX @@ static void systick_reset(nvic_state *s)
44
}
79
IRQ is #16. The internal GIC routines use #32 as the first IRQ. */
45
80
void armv7m_nvic_set_pending(void *opaque, int irq)
46
static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
81
{
47
{
82
- nvic_state *s = (nvic_state *)opaque;
48
- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1;
83
+ NVICState *s = (NVICState *)opaque;
49
+ return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
84
if (irq >= 16)
50
}
85
irq += 16;
51
86
gic_set_pending_private(&s->gic, 0, irq);
52
static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
87
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
88
/* Make pending IRQ active. */
89
int armv7m_nvic_acknowledge_irq(void *opaque)
90
{
53
{
91
- nvic_state *s = (nvic_state *)opaque;
54
- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1;
92
+ NVICState *s = (NVICState *)opaque;
55
+ return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
93
uint32_t irq;
56
}
94
57
95
irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
58
static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
96
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_acknowledge_irq(void *opaque)
97
98
void armv7m_nvic_complete_irq(void *opaque, int irq)
99
{
59
{
100
- nvic_state *s = (nvic_state *)opaque;
60
- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2;
101
+ NVICState *s = (NVICState *)opaque;
61
+ return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2;
102
if (irq >= 16)
103
irq += 16;
104
gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED);
105
}
62
}
106
63
107
-static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
64
static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
108
+static uint32_t nvic_readl(NVICState *s, uint32_t offset)
109
{
65
{
110
ARMCPU *cpu = s->cpu;
66
- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3;
111
uint32_t val;
67
+ return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3;
112
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
113
}
114
}
68
}
115
69
116
-static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
70
static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
117
+static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
118
{
71
{
119
ARMCPU *cpu = s->cpu;
72
- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
120
uint32_t oldval;
73
+ return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4;
121
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
74
}
122
static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
75
123
unsigned size)
76
static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
124
{
125
- nvic_state *s = (nvic_state *)opaque;
126
+ NVICState *s = (NVICState *)opaque;
127
uint32_t offset = addr;
128
int i;
129
uint32_t val;
130
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
131
static void nvic_sysreg_write(void *opaque, hwaddr addr,
132
uint64_t value, unsigned size)
133
{
134
- nvic_state *s = (nvic_state *)opaque;
135
+ NVICState *s = (NVICState *)opaque;
136
uint32_t offset = addr;
137
int i;
138
139
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_nvic = {
140
.version_id = 1,
141
.minimum_version_id = 1,
142
.fields = (VMStateField[]) {
143
- VMSTATE_UINT32(systick.control, nvic_state),
144
- VMSTATE_UINT32(systick.reload, nvic_state),
145
- VMSTATE_INT64(systick.tick, nvic_state),
146
- VMSTATE_TIMER_PTR(systick.timer, nvic_state),
147
+ VMSTATE_UINT32(systick.control, NVICState),
148
+ VMSTATE_UINT32(systick.reload, NVICState),
149
+ VMSTATE_INT64(systick.tick, NVICState),
150
+ VMSTATE_TIMER_PTR(systick.timer, NVICState),
151
VMSTATE_END_OF_LIST()
152
}
153
};
154
155
static void armv7m_nvic_reset(DeviceState *dev)
156
{
157
- nvic_state *s = NVIC(dev);
158
+ NVICState *s = NVIC(dev);
159
NVICClass *nc = NVIC_GET_CLASS(s);
160
nc->parent_reset(dev);
161
/* Common GIC reset resets to disabled; the NVIC doesn't have
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
163
164
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
165
{
166
- nvic_state *s = NVIC(dev);
167
+ NVICState *s = NVIC(dev);
168
NVICClass *nc = NVIC_GET_CLASS(s);
169
Error *local_err = NULL;
170
171
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
172
*/
173
GICState *s = ARM_GIC_COMMON(obj);
174
DeviceState *dev = DEVICE(obj);
175
- nvic_state *nvic = NVIC(obj);
176
+ NVICState *nvic = NVIC(obj);
177
/* The ARM v7m may have anything from 0 to 496 external interrupt
178
* IRQ lines. We default to 64. Other boards may differ and should
179
* set the num-irq property appropriately.
180
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armv7m_nvic_info = {
181
.name = TYPE_NVIC,
182
.parent = TYPE_ARM_GIC_COMMON,
183
.instance_init = armv7m_nvic_instance_init,
184
- .instance_size = sizeof(nvic_state),
185
+ .instance_size = sizeof(NVICState),
186
.class_init = armv7m_nvic_class_init,
187
.class_size = sizeof(NVICClass),
188
};
189
--
77
--
190
2.7.4
78
2.20.1
191
79
192
80
diff view generated by jsdifflib
1
The M profile condition for when we can take a pending exception or
1
The ACTLR2 and HACTLR2 AArch32 system registers didn't exist in ARMv7
2
interrupt is not the same as that for A/R profile. The code
2
or the original ARMv8. They were later added as optional registers,
3
originally copied from the A/R profile version of the
3
whose presence is signaled by the ID_MMFR4.AC2 field. From ARMv8.2
4
cpu_exec_interrupt function only worked by chance for the
4
they are mandatory (ie ID_MMFR4.AC2 must be non-zero).
5
very simple case of exceptions being masked by PRIMASK.
6
Replace it with a call to a function in the NVIC code that
7
correctly compares the priority of the pending exception
8
against the current execution priority of the CPU.
9
5
10
[Michael Davidsaver's patchset had a patch to do something
6
We implemented HACTLR2 in commit 0e0456ab8895a5e85, but we
11
similar but the implementation ended up being a rewrite.]
7
incorrectly made it exist for all v8 CPUs, and we didn't implement
8
ACTLR2 at all.
12
9
10
Sort this out by implementing both registers only when they are
11
supposed to exist, and setting the ID_MMFR4 bit for -cpu max.
12
13
Note that this removes HACTLR2 from our Cortex-A53, -A47 and -A72
14
CPU models; this is correct, because those CPUs do not implement
15
this register.
16
17
Fixes: 0e0456ab8895a5e85
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20200214175116.9164-22-peter.maydell@linaro.org
15
---
21
---
16
target/arm/cpu.h | 8 ++++++++
22
target/arm/cpu.h | 5 +++++
17
hw/intc/armv7m_nvic.c | 7 +++++++
23
target/arm/cpu.c | 1 +
18
target/arm/cpu.c | 16 ++++++++--------
24
target/arm/cpu64.c | 4 ++++
19
3 files changed, 23 insertions(+), 8 deletions(-)
25
target/arm/helper.c | 32 +++++++++++++++++++++++---------
26
4 files changed, 33 insertions(+), 9 deletions(-)
20
27
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
30
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
26
uint32_t cur_el, bool secure);
33
return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0;
27
34
}
28
/* Interface between CPU and Interrupt controller. */
35
29
+#ifndef CONFIG_USER_ONLY
36
+static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
30
+bool armv7m_nvic_can_take_pending_exception(void *opaque);
31
+#else
32
+static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
33
+{
37
+{
34
+ return true;
38
+ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0;
35
+}
36
+#endif
37
void armv7m_nvic_set_pending(void *opaque, int irq);
38
int armv7m_nvic_acknowledge_irq(void *opaque);
39
void armv7m_nvic_complete_irq(void *opaque, int irq);
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/intc/armv7m_nvic.c
43
+++ b/hw/intc/armv7m_nvic.c
44
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
45
return MIN(running, s->exception_prio);
46
}
47
48
+bool armv7m_nvic_can_take_pending_exception(void *opaque)
49
+{
50
+ NVICState *s = opaque;
51
+
52
+ return nvic_exec_prio(s) > nvic_pending_prio(s);
53
+}
39
+}
54
+
40
+
55
/* caller must call nvic_irq_update() after this */
41
/*
56
static void set_prio(NVICState *s, unsigned irq, uint8_t prio)
42
* 64-bit feature tests via id registers.
57
{
43
*/
58
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
44
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/cpu.c
46
--- a/target/arm/cpu.c
61
+++ b/target/arm/cpu.c
47
+++ b/target/arm/cpu.c
62
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
48
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
63
CPUARMState *env = &cpu->env;
49
64
bool ret = false;
50
t = cpu->isar.id_mmfr4;
65
51
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
66
-
52
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
67
- if (interrupt_request & CPU_INTERRUPT_FIQ
53
cpu->isar.id_mmfr4 = t;
68
- && !(env->daif & PSTATE_F)) {
54
}
69
- cs->exception_index = EXCP_FIQ;
55
#endif
70
- cc->do_interrupt(cs);
56
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
71
- ret = true;
57
index XXXXXXX..XXXXXXX 100644
72
- }
58
--- a/target/arm/cpu64.c
73
/* ARMv7-M interrupt return works by loading a magic value
59
+++ b/target/arm/cpu64.c
74
* into the PC. On real hardware the load causes the
60
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
75
* return to occur. The qemu implementation performs the
61
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
76
@@ -XXX,XX +XXX,XX @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
62
cpu->isar.id_mmfr3 = u;
77
* the stack if an interrupt occurred at the wrong time.
63
78
* We avoid this by disabling interrupts when
64
+ u = cpu->isar.id_mmfr4;
79
* pc contains a magic address.
65
+ u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
80
+ *
66
+ cpu->isar.id_mmfr4 = u;
81
+ * ARMv7-M interrupt masking works differently than -A or -R.
67
+
82
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
68
u = cpu->isar.id_aa64dfr0;
83
+ * masking FIQ and IRQ interrupts, an exception is taken only
69
u = FIELD_DP64(u, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */
84
+ * if it is higher priority than the current execution priority
70
cpu->isar.id_aa64dfr0 = u;
85
+ * (which depends on state like BASEPRI, FAULTMASK and the
71
diff --git a/target/arm/helper.c b/target/arm/helper.c
86
+ * currently active exception).
72
index XXXXXXX..XXXXXXX 100644
87
*/
73
--- a/target/arm/helper.c
88
if (interrupt_request & CPU_INTERRUPT_HARD
74
+++ b/target/arm/helper.c
89
- && !(env->daif & PSTATE_I)
75
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
90
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))
76
};
91
&& (env->regs[15] < 0xfffffff0)) {
77
#endif
92
cs->exception_index = EXCP_IRQ;
78
93
cc->do_interrupt(cs);
79
+/*
80
+ * ACTLR2 and HACTLR2 map to ACTLR_EL1[63:32] and
81
+ * ACTLR_EL2[63:32]. They exist only if the ID_MMFR4.AC2 field
82
+ * is non-zero, which is never for ARMv7, optionally in ARMv8
83
+ * and mandatorily for ARMv8.2 and up.
84
+ * ACTLR2 is banked for S and NS if EL3 is AArch32. Since QEMU's
85
+ * implementation is RAZ/WI we can ignore this detail, as we
86
+ * do for ACTLR.
87
+ */
88
+static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
89
+ { .name = "ACTLR2", .state = ARM_CP_STATE_AA32,
90
+ .cp = 15, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 3,
91
+ .access = PL1_RW, .type = ARM_CP_CONST,
92
+ .resetvalue = 0 },
93
+ { .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
94
+ .cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
95
+ .access = PL2_RW, .type = ARM_CP_CONST,
96
+ .resetvalue = 0 },
97
+ REGINFO_SENTINEL
98
+};
99
+
100
void register_cp_regs_for_features(ARMCPU *cpu)
101
{
102
/* Register all the coprocessor registers based on feature bits */
103
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
104
REGINFO_SENTINEL
105
};
106
define_arm_cp_regs(cpu, auxcr_reginfo);
107
- if (arm_feature(env, ARM_FEATURE_V8)) {
108
- /* HACTLR2 maps to ACTLR_EL2[63:32] and is not in ARMv7 */
109
- ARMCPRegInfo hactlr2_reginfo = {
110
- .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
111
- .cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
112
- .access = PL2_RW, .type = ARM_CP_CONST,
113
- .resetvalue = 0
114
- };
115
- define_one_arm_cp_reg(cpu, &hactlr2_reginfo);
116
+ if (cpu_isar_feature(aa32_ac2, cpu)) {
117
+ define_arm_cp_regs(cpu, actlr2_hactlr2_reginfo);
118
}
119
}
120
94
--
121
--
95
2.7.4
122
2.20.1
96
123
97
124
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
In SDHCI protocol, the 'Block count enable' bit of the Transfer
3
We need to be able to use OHCISysBusState outside hcd-ohci.c, so move it
4
Mode register is relevant only in multi block transfers. We need
4
to its include file.
5
not check it in single block transfers.
6
5
7
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20170214185225.7994-5-ppandit@redhat.com
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Message-id: 20200217204812.9857-2-linux@roeck-us.net
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/sd/sdhci.c | 6 +-----
12
hw/usb/hcd-ohci.h | 16 ++++++++++++++++
13
1 file changed, 1 insertion(+), 5 deletions(-)
13
hw/usb/hcd-ohci.c | 15 ---------------
14
2 files changed, 16 insertions(+), 15 deletions(-)
14
15
15
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/sd/sdhci.c
18
--- a/hw/usb/hcd-ohci.h
18
+++ b/hw/sd/sdhci.c
19
+++ b/hw/usb/hcd-ohci.h
19
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
20
@@ -XXX,XX +XXX,XX @@
21
#define HCD_OHCI_H
22
23
#include "sysemu/dma.h"
24
+#include "hw/usb.h"
25
26
/* Number of Downstream Ports on the root hub: */
27
#define OHCI_MAX_PORTS 15
28
@@ -XXX,XX +XXX,XX @@ typedef struct OHCIState {
29
void (*ohci_die)(struct OHCIState *ohci);
30
} OHCIState;
31
32
+#define TYPE_SYSBUS_OHCI "sysbus-ohci"
33
+#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
34
+
35
+typedef struct {
36
+ /*< private >*/
37
+ SysBusDevice parent_obj;
38
+ /*< public >*/
39
+
40
+ OHCIState ohci;
41
+ char *masterbus;
42
+ uint32_t num_ports;
43
+ uint32_t firstport;
44
+ dma_addr_t dma_offset;
45
+} OHCISysBusState;
46
+
47
extern const VMStateDescription vmstate_ohci_state;
48
49
void usb_ohci_init(OHCIState *ohci, DeviceState *dev, uint32_t num_ports,
50
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/usb/hcd-ohci.c
53
+++ b/hw/usb/hcd-ohci.c
54
@@ -XXX,XX +XXX,XX @@ void ohci_sysbus_die(struct OHCIState *ohci)
55
ohci_bus_stop(ohci);
20
}
56
}
21
57
22
/* single block SDMA transfer */
58
-#define TYPE_SYSBUS_OHCI "sysbus-ohci"
59
-#define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj), TYPE_SYSBUS_OHCI)
23
-
60
-
24
static void sdhci_sdma_transfer_single_block(SDHCIState *s)
61
-typedef struct {
62
- /*< private >*/
63
- SysBusDevice parent_obj;
64
- /*< public >*/
65
-
66
- OHCIState ohci;
67
- char *masterbus;
68
- uint32_t num_ports;
69
- uint32_t firstport;
70
- dma_addr_t dma_offset;
71
-} OHCISysBusState;
72
-
73
static void ohci_realize_pxa(DeviceState *dev, Error **errp)
25
{
74
{
26
int n;
75
OHCISysBusState *s = SYSBUS_OHCI(dev);
27
@@ -XXX,XX +XXX,XX @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
28
sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
29
}
30
}
31
-
32
- if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
33
- s->blkcnt--;
34
- }
35
+ s->blkcnt--;
36
37
sdhci_end_transfer(s);
38
}
39
--
76
--
40
2.7.4
77
2.20.1
41
78
42
79
diff view generated by jsdifflib
New patch
1
From: Guenter Roeck <linux@roeck-us.net>
1
2
3
We'll use this property in a follow-up patch to insantiate an EHCI
4
bus with companion support.
5
6
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
8
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Message-id: 20200217204812.9857-3-linux@roeck-us.net
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/usb/hcd-ehci-sysbus.c | 2 ++
13
1 file changed, 2 insertions(+)
14
15
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/usb/hcd-ehci-sysbus.c
18
+++ b/hw/usb/hcd-ehci-sysbus.c
19
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_ehci_sysbus = {
20
21
static Property ehci_sysbus_properties[] = {
22
DEFINE_PROP_UINT32("maxframes", EHCISysBusState, ehci.maxframes, 128),
23
+ DEFINE_PROP_BOOL("companion-enable", EHCISysBusState, ehci.companion_enable,
24
+ false),
25
DEFINE_PROP_END_OF_LIST(),
26
};
27
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
This adds the BCM2835 GPIO controller.
3
Instantiate EHCI and OHCI controllers on Allwinner A10. OHCI ports are
4
modeled as companions of the respective EHCI ports.
4
5
5
It currently implements:
6
With this patch applied, USB controllers are discovered and instantiated
6
- The 54 GPIOs as outputs (qemu_irq)
7
when booting the cubieboard machine with a recent Linux kernel.
7
- The SD controller selection via alternate function of GPIOs 48-53
8
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
9
ehci-platform 1c14000.usb: EHCI Host Controller
10
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
10
ehci-platform 1c14000.usb: new USB bus registered, assigned bus number 1
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
ehci-platform 1c14000.usb: irq 26, io mem 0x01c14000
12
ehci-platform 1c14000.usb: USB 2.0 started, EHCI 1.00
13
ehci-platform 1c1c000.usb: EHCI Host Controller
14
ehci-platform 1c1c000.usb: new USB bus registered, assigned bus number 2
15
ehci-platform 1c1c000.usb: irq 31, io mem 0x01c1c000
16
ehci-platform 1c1c000.usb: USB 2.0 started, EHCI 1.00
17
ohci-platform 1c14400.usb: Generic Platform OHCI controller
18
ohci-platform 1c14400.usb: new USB bus registered, assigned bus number 3
19
ohci-platform 1c14400.usb: irq 27, io mem 0x01c14400
20
ohci-platform 1c1c400.usb: Generic Platform OHCI controller
21
ohci-platform 1c1c400.usb: new USB bus registered, assigned bus number 4
22
ohci-platform 1c1c400.usb: irq 32, io mem 0x01c1c400
23
usb 2-1: new high-speed USB device number 2 using ehci-platform
24
usb-storage 2-1:1.0: USB Mass Storage device detected
25
scsi host1: usb-storage 2-1:1.0
26
usb 3-1: new full-speed USB device number 2 using ohci-platform
27
input: QEMU QEMU USB Mouse as /devices/platform/soc/1c14400.usb/usb3/3-1/3-1:1.0/0003:0627:0001.0001/input/input0
28
29
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
30
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
31
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
32
Message-id: 20200217204812.9857-4-linux@roeck-us.net
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
34
---
14
hw/gpio/Makefile.objs | 1 +
35
include/hw/arm/allwinner-a10.h | 6 +++++
15
include/hw/gpio/bcm2835_gpio.h | 39 +++++
36
hw/arm/allwinner-a10.c | 43 ++++++++++++++++++++++++++++++++++
16
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
37
2 files changed, 49 insertions(+)
17
3 files changed, 393 insertions(+)
18
create mode 100644 include/hw/gpio/bcm2835_gpio.h
19
create mode 100644 hw/gpio/bcm2835_gpio.c
20
38
21
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
39
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
22
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/gpio/Makefile.objs
41
--- a/include/hw/arm/allwinner-a10.h
24
+++ b/hw/gpio/Makefile.objs
42
+++ b/include/hw/arm/allwinner-a10.h
25
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
26
27
obj-$(CONFIG_OMAP) += omap_gpio.o
28
obj-$(CONFIG_IMX) += imx_gpio.o
29
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
30
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/gpio/bcm2835_gpio.h
35
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@
36
+/*
44
#include "hw/intc/allwinner-a10-pic.h"
37
+ * Raspberry Pi (BCM2835) GPIO Controller
45
#include "hw/net/allwinner_emac.h"
38
+ *
46
#include "hw/ide/ahci.h"
39
+ * Copyright (c) 2017 Antfield SAS
47
+#include "hw/usb/hcd-ohci.h"
40
+ *
48
+#include "hw/usb/hcd-ehci.h"
41
+ * Authors:
49
42
+ * Clement Deschamps <clement.deschamps@antfield.fr>
50
#include "target/arm/cpu.h"
43
+ * Luc Michel <luc.michel@antfield.fr>
51
44
+ *
52
45
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
53
#define AW_A10_SDRAM_BASE 0x40000000
46
+ * See the COPYING file in the top-level directory.
54
47
+ */
55
+#define AW_A10_NUM_USB 2
48
+
56
+
49
+#ifndef BCM2835_GPIO_H
57
#define TYPE_AW_A10 "allwinner-a10"
50
+#define BCM2835_GPIO_H
58
#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
59
60
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
61
AwEmacState emac;
62
AllwinnerAHCIState sata;
63
MemoryRegion sram_a;
64
+ EHCISysBusState ehci[AW_A10_NUM_USB];
65
+ OHCISysBusState ohci[AW_A10_NUM_USB];
66
} AwA10State;
67
68
#endif
69
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/arm/allwinner-a10.c
72
+++ b/hw/arm/allwinner-a10.c
73
@@ -XXX,XX +XXX,XX @@
74
#include "hw/arm/allwinner-a10.h"
75
#include "hw/misc/unimp.h"
76
#include "sysemu/sysemu.h"
77
+#include "hw/boards.h"
78
+#include "hw/usb/hcd-ohci.h"
79
80
#define AW_A10_PIC_REG_BASE 0x01c20400
81
#define AW_A10_PIT_REG_BASE 0x01c20c00
82
#define AW_A10_UART0_REG_BASE 0x01c28000
83
#define AW_A10_EMAC_BASE 0x01c0b000
84
+#define AW_A10_EHCI_BASE 0x01c14000
85
+#define AW_A10_OHCI_BASE 0x01c14400
86
#define AW_A10_SATA_BASE 0x01c18000
87
88
static void aw_a10_init(Object *obj)
89
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
90
91
sysbus_init_child_obj(obj, "sata", &s->sata, sizeof(s->sata),
92
TYPE_ALLWINNER_AHCI);
51
+
93
+
52
+#include "hw/sd/sd.h"
94
+ if (machine_usb(current_machine)) {
95
+ int i;
53
+
96
+
54
+typedef struct BCM2835GpioState {
97
+ for (i = 0; i < AW_A10_NUM_USB; i++) {
55
+ SysBusDevice parent_obj;
98
+ sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]),
56
+
99
+ sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI);
57
+ MemoryRegion iomem;
100
+ sysbus_init_child_obj(obj, "ohci[*]", OBJECT(&s->ohci[i]),
58
+
101
+ sizeof(s->ohci[i]), TYPE_SYSBUS_OHCI);
59
+ /* SDBus selector */
60
+ SDBus sdbus;
61
+ SDBus *sdbus_sdhci;
62
+ SDBus *sdbus_sdhost;
63
+
64
+ uint8_t fsel[54];
65
+ uint32_t lev0, lev1;
66
+ uint8_t sd_fsel;
67
+ qemu_irq out[54];
68
+} BCM2835GpioState;
69
+
70
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
71
+#define BCM2835_GPIO(obj) \
72
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
73
+
74
+#endif
75
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/gpio/bcm2835_gpio.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Raspberry Pi (BCM2835) GPIO Controller
83
+ *
84
+ * Copyright (c) 2017 Antfield SAS
85
+ *
86
+ * Authors:
87
+ * Clement Deschamps <clement.deschamps@antfield.fr>
88
+ * Luc Michel <luc.michel@antfield.fr>
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
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
97
+#include "qapi/error.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/sd/sd.h"
100
+#include "hw/gpio/bcm2835_gpio.h"
101
+
102
+#define GPFSEL0 0x00
103
+#define GPFSEL1 0x04
104
+#define GPFSEL2 0x08
105
+#define GPFSEL3 0x0C
106
+#define GPFSEL4 0x10
107
+#define GPFSEL5 0x14
108
+#define GPSET0 0x1C
109
+#define GPSET1 0x20
110
+#define GPCLR0 0x28
111
+#define GPCLR1 0x2C
112
+#define GPLEV0 0x34
113
+#define GPLEV1 0x38
114
+#define GPEDS0 0x40
115
+#define GPEDS1 0x44
116
+#define GPREN0 0x4C
117
+#define GPREN1 0x50
118
+#define GPFEN0 0x58
119
+#define GPFEN1 0x5C
120
+#define GPHEN0 0x64
121
+#define GPHEN1 0x68
122
+#define GPLEN0 0x70
123
+#define GPLEN1 0x74
124
+#define GPAREN0 0x7C
125
+#define GPAREN1 0x80
126
+#define GPAFEN0 0x88
127
+#define GPAFEN1 0x8C
128
+#define GPPUD 0x94
129
+#define GPPUDCLK0 0x98
130
+#define GPPUDCLK1 0x9C
131
+
132
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
133
+{
134
+ int i;
135
+ uint32_t value = 0;
136
+ for (i = 0; i < 10; i++) {
137
+ uint32_t index = 10 * reg + i;
138
+ if (index < sizeof(s->fsel)) {
139
+ value |= (s->fsel[index] & 0x7) << (3 * i);
140
+ }
102
+ }
141
+ }
103
+ }
142
+ return value;
104
}
143
+}
105
106
static void aw_a10_realize(DeviceState *dev, Error **errp)
107
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
108
serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2,
109
qdev_get_gpio_in(dev, 1),
110
115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
144
+
111
+
145
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
112
+ if (machine_usb(current_machine)) {
146
+{
113
+ int i;
147
+ int i;
114
+
148
+ for (i = 0; i < 10; i++) {
115
+ for (i = 0; i < AW_A10_NUM_USB; i++) {
149
+ uint32_t index = 10 * reg + i;
116
+ char bus[16];
150
+ if (index < sizeof(s->fsel)) {
117
+
151
+ int fsel = (value >> (3 * i)) & 0x7;
118
+ sprintf(bus, "usb-bus.%d", i);
152
+ s->fsel[index] = fsel;
119
+
120
+ object_property_set_bool(OBJECT(&s->ehci[i]), true,
121
+ "companion-enable", &error_fatal);
122
+ object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized",
123
+ &error_fatal);
124
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0,
125
+ AW_A10_EHCI_BASE + i * 0x8000);
126
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
127
+ qdev_get_gpio_in(dev, 39 + i));
128
+
129
+ object_property_set_str(OBJECT(&s->ohci[i]), bus, "masterbus",
130
+ &error_fatal);
131
+ object_property_set_bool(OBJECT(&s->ohci[i]), true, "realized",
132
+ &error_fatal);
133
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci[i]), 0,
134
+ AW_A10_OHCI_BASE + i * 0x8000);
135
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci[i]), 0,
136
+ qdev_get_gpio_in(dev, 64 + i));
153
+ }
137
+ }
154
+ }
138
+ }
155
+
139
}
156
+ /* SD controller selection (48-53) */
140
157
+ if (s->sd_fsel != 0
141
static void aw_a10_class_init(ObjectClass *oc, void *data)
158
+ && (s->fsel[48] == 0) /* SD_CLK_R */
159
+ && (s->fsel[49] == 0) /* SD_CMD_R */
160
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
161
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
162
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
163
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
164
+ ) {
165
+ /* SDHCI controller selected */
166
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
167
+ s->sd_fsel = 0;
168
+ } else if (s->sd_fsel != 4
169
+ && (s->fsel[48] == 4) /* SD_CLK_R */
170
+ && (s->fsel[49] == 4) /* SD_CMD_R */
171
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
172
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
173
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
174
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
175
+ ) {
176
+ /* SDHost controller selected */
177
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
178
+ s->sd_fsel = 4;
179
+ }
180
+}
181
+
182
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
183
+{
184
+ if (index >= 0 && index < 54) {
185
+ return s->fsel[index] == 1;
186
+ }
187
+ return 0;
188
+}
189
+
190
+static void gpset(BCM2835GpioState *s,
191
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
192
+{
193
+ uint32_t changes = val & ~*lev;
194
+ uint32_t cur = 1;
195
+
196
+ int i;
197
+ for (i = 0; i < count; i++) {
198
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
199
+ qemu_set_irq(s->out[start + i], 1);
200
+ }
201
+ cur <<= 1;
202
+ }
203
+
204
+ *lev |= val;
205
+}
206
+
207
+static void gpclr(BCM2835GpioState *s,
208
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
209
+{
210
+ uint32_t changes = val & *lev;
211
+ uint32_t cur = 1;
212
+
213
+ int i;
214
+ for (i = 0; i < count; i++) {
215
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
216
+ qemu_set_irq(s->out[start + i], 0);
217
+ }
218
+ cur <<= 1;
219
+ }
220
+
221
+ *lev &= ~val;
222
+}
223
+
224
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
225
+ unsigned size)
226
+{
227
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
228
+
229
+ switch (offset) {
230
+ case GPFSEL0:
231
+ case GPFSEL1:
232
+ case GPFSEL2:
233
+ case GPFSEL3:
234
+ case GPFSEL4:
235
+ case GPFSEL5:
236
+ return gpfsel_get(s, offset / 4);
237
+ case GPSET0:
238
+ case GPSET1:
239
+ /* Write Only */
240
+ return 0;
241
+ case GPCLR0:
242
+ case GPCLR1:
243
+ /* Write Only */
244
+ return 0;
245
+ case GPLEV0:
246
+ return s->lev0;
247
+ case GPLEV1:
248
+ return s->lev1;
249
+ case GPEDS0:
250
+ case GPEDS1:
251
+ case GPREN0:
252
+ case GPREN1:
253
+ case GPFEN0:
254
+ case GPFEN1:
255
+ case GPHEN0:
256
+ case GPHEN1:
257
+ case GPLEN0:
258
+ case GPLEN1:
259
+ case GPAREN0:
260
+ case GPAREN1:
261
+ case GPAFEN0:
262
+ case GPAFEN1:
263
+ case GPPUD:
264
+ case GPPUDCLK0:
265
+ case GPPUDCLK1:
266
+ /* Not implemented */
267
+ return 0;
268
+ default:
269
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
270
+ __func__, offset);
271
+ break;
272
+ }
273
+
274
+ return 0;
275
+}
276
+
277
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
278
+ uint64_t value, unsigned size)
279
+{
280
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
281
+
282
+ switch (offset) {
283
+ case GPFSEL0:
284
+ case GPFSEL1:
285
+ case GPFSEL2:
286
+ case GPFSEL3:
287
+ case GPFSEL4:
288
+ case GPFSEL5:
289
+ gpfsel_set(s, offset / 4, value);
290
+ break;
291
+ case GPSET0:
292
+ gpset(s, value, 0, 32, &s->lev0);
293
+ break;
294
+ case GPSET1:
295
+ gpset(s, value, 32, 22, &s->lev1);
296
+ break;
297
+ case GPCLR0:
298
+ gpclr(s, value, 0, 32, &s->lev0);
299
+ break;
300
+ case GPCLR1:
301
+ gpclr(s, value, 32, 22, &s->lev1);
302
+ break;
303
+ case GPLEV0:
304
+ case GPLEV1:
305
+ /* Read Only */
306
+ break;
307
+ case GPEDS0:
308
+ case GPEDS1:
309
+ case GPREN0:
310
+ case GPREN1:
311
+ case GPFEN0:
312
+ case GPFEN1:
313
+ case GPHEN0:
314
+ case GPHEN1:
315
+ case GPLEN0:
316
+ case GPLEN1:
317
+ case GPAREN0:
318
+ case GPAREN1:
319
+ case GPAFEN0:
320
+ case GPAFEN1:
321
+ case GPPUD:
322
+ case GPPUDCLK0:
323
+ case GPPUDCLK1:
324
+ /* Not implemented */
325
+ break;
326
+ default:
327
+ goto err_out;
328
+ }
329
+ return;
330
+
331
+err_out:
332
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
333
+ __func__, offset);
334
+}
335
+
336
+static void bcm2835_gpio_reset(DeviceState *dev)
337
+{
338
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
339
+
340
+ int i;
341
+ for (i = 0; i < 6; i++) {
342
+ gpfsel_set(s, i, 0);
343
+ }
344
+
345
+ s->sd_fsel = 0;
346
+
347
+ /* SDHCI is selected by default */
348
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
349
+
350
+ s->lev0 = 0;
351
+ s->lev1 = 0;
352
+}
353
+
354
+static const MemoryRegionOps bcm2835_gpio_ops = {
355
+ .read = bcm2835_gpio_read,
356
+ .write = bcm2835_gpio_write,
357
+ .endianness = DEVICE_NATIVE_ENDIAN,
358
+};
359
+
360
+static const VMStateDescription vmstate_bcm2835_gpio = {
361
+ .name = "bcm2835_gpio",
362
+ .version_id = 1,
363
+ .minimum_version_id = 1,
364
+ .fields = (VMStateField[]) {
365
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
366
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
367
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
368
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
369
+ VMSTATE_END_OF_LIST()
370
+ }
371
+};
372
+
373
+static void bcm2835_gpio_init(Object *obj)
374
+{
375
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
376
+ DeviceState *dev = DEVICE(obj);
377
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
378
+
379
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
380
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
381
+
382
+ memory_region_init_io(&s->iomem, obj,
383
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
384
+ sysbus_init_mmio(sbd, &s->iomem);
385
+ qdev_init_gpio_out(dev, s->out, 54);
386
+}
387
+
388
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
389
+{
390
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
391
+ Object *obj;
392
+ Error *err = NULL;
393
+
394
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
395
+ if (obj == NULL) {
396
+ error_setg(errp, "%s: required sdhci link not found: %s",
397
+ __func__, error_get_pretty(err));
398
+ return;
399
+ }
400
+ s->sdbus_sdhci = SD_BUS(obj);
401
+
402
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
403
+ if (obj == NULL) {
404
+ error_setg(errp, "%s: required sdhost link not found: %s",
405
+ __func__, error_get_pretty(err));
406
+ return;
407
+ }
408
+ s->sdbus_sdhost = SD_BUS(obj);
409
+}
410
+
411
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
415
+ dc->vmsd = &vmstate_bcm2835_gpio;
416
+ dc->realize = &bcm2835_gpio_realize;
417
+ dc->reset = &bcm2835_gpio_reset;
418
+}
419
+
420
+static const TypeInfo bcm2835_gpio_info = {
421
+ .name = TYPE_BCM2835_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(BCM2835GpioState),
424
+ .instance_init = bcm2835_gpio_init,
425
+ .class_init = bcm2835_gpio_class_init,
426
+};
427
+
428
+static void bcm2835_gpio_register_types(void)
429
+{
430
+ type_register_static(&bcm2835_gpio_info);
431
+}
432
+
433
+type_init(bcm2835_gpio_register_types)
434
--
142
--
435
2.7.4
143
2.20.1
436
144
437
145
diff view generated by jsdifflib
1
From: Marcin Chojnacki <marcinch7@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Recent vanilla Raspberry Pi kernels started to make use of
3
These instructions shift left or right depending on the sign
4
the hardware random number generator in BCM2835 SoC. As a
4
of the input, and 7 bits are significant to the shift. This
5
result, those kernels wouldn't work anymore under QEMU
5
requires several masks and selects in addition to the actual
6
but rather just freeze during the boot process.
6
shifts to form the complete answer.
7
7
8
This patch implements a trivial BCM2835 compatible RNG,
8
That said, the operation is still a small improvement even for
9
and adds it as a peripheral to BCM2835 platform, which
9
two 64-bit elements -- 13 vector operations instead of 2 * 7
10
allows to boot a vanilla Raspberry Pi kernel under Qemu.
10
integer operations.
11
11
12
Changes since v1:
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
* Prevented guest from writing [31..20] bits in rng_status
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
* Removed redundant minimum_version_id_old
14
Message-id: 20200216214232.4230-2-richard.henderson@linaro.org
15
* Added field entries for the state
16
* Changed realize function to reset
17
18
Signed-off-by: Marcin Chojnacki <marcinch7@gmail.com>
19
Message-id: 20170210210857.47893-1-marcinch7@gmail.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
16
---
23
hw/misc/Makefile.objs | 1 +
17
target/arm/helper.h | 11 +-
24
include/hw/arm/bcm2835_peripherals.h | 2 +
18
target/arm/translate.h | 6 +
25
include/hw/misc/bcm2835_rng.h | 27 ++++++++
19
target/arm/neon_helper.c | 33 ----
26
hw/arm/bcm2835_peripherals.c | 15 +++++
20
target/arm/translate-a64.c | 18 +--
27
hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++++++
21
target/arm/translate.c | 299 +++++++++++++++++++++++++++++++++++--
28
5 files changed, 169 insertions(+)
22
target/arm/vec_helper.c | 88 +++++++++++
29
create mode 100644 include/hw/misc/bcm2835_rng.h
23
6 files changed, 389 insertions(+), 66 deletions(-)
30
create mode 100644 hw/misc/bcm2835_rng.c
31
24
32
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
25
diff --git a/target/arm/helper.h b/target/arm/helper.h
33
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/misc/Makefile.objs
27
--- a/target/arm/helper.h
35
+++ b/hw/misc/Makefile.objs
28
+++ b/target/arm/helper.h
36
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_OMAP) += omap_sdrc.o
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
37
obj-$(CONFIG_OMAP) += omap_tap.o
30
DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
38
obj-$(CONFIG_RASPI) += bcm2835_mbox.o
31
DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
39
obj-$(CONFIG_RASPI) += bcm2835_property.o
32
40
+obj-$(CONFIG_RASPI) += bcm2835_rng.o
33
-DEF_HELPER_2(neon_shl_u8, i32, i32, i32)
41
obj-$(CONFIG_SLAVIO) += slavio_misc.o
34
-DEF_HELPER_2(neon_shl_s8, i32, i32, i32)
42
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
35
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
43
obj-$(CONFIG_ZYNQ) += zynq-xadc.o
36
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
44
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
37
-DEF_HELPER_2(neon_shl_u32, i32, i32, i32)
38
-DEF_HELPER_2(neon_shl_s32, i32, i32, i32)
39
-DEF_HELPER_2(neon_shl_u64, i64, i64, i64)
40
-DEF_HELPER_2(neon_shl_s64, i64, i64, i64)
41
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
42
DEF_HELPER_2(neon_rshl_s8, i32, i32, i32)
43
DEF_HELPER_2(neon_rshl_u16, i32, i32, i32)
44
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
45
DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
46
DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
47
48
+DEF_HELPER_FLAGS_4(gvec_sshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
+DEF_HELPER_FLAGS_4(gvec_sshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
+DEF_HELPER_FLAGS_4(gvec_ushl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
52
+
53
#ifdef TARGET_AARCH64
54
#include "helper-a64.h"
55
#include "helper-sve.h"
56
diff --git a/target/arm/translate.h b/target/arm/translate.h
45
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/bcm2835_peripherals.h
58
--- a/target/arm/translate.h
47
+++ b/include/hw/arm/bcm2835_peripherals.h
59
+++ b/target/arm/translate.h
48
@@ -XXX,XX +XXX,XX @@
60
@@ -XXX,XX +XXX,XX @@ uint64_t vfp_expand_imm(int size, uint8_t imm8);
49
#include "hw/dma/bcm2835_dma.h"
61
extern const GVecGen3 mla_op[4];
50
#include "hw/intc/bcm2835_ic.h"
62
extern const GVecGen3 mls_op[4];
51
#include "hw/misc/bcm2835_property.h"
63
extern const GVecGen3 cmtst_op[4];
52
+#include "hw/misc/bcm2835_rng.h"
64
+extern const GVecGen3 sshl_op[4];
53
#include "hw/misc/bcm2835_mbox.h"
65
+extern const GVecGen3 ushl_op[4];
54
#include "hw/sd/sdhci.h"
66
extern const GVecGen2i ssra_op[4];
55
67
extern const GVecGen2i usra_op[4];
56
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
68
extern const GVecGen2i sri_op[4];
57
BCM2835DMAState dma;
69
@@ -XXX,XX +XXX,XX @@ extern const GVecGen4 sqadd_op[4];
58
BCM2835ICState ic;
70
extern const GVecGen4 uqsub_op[4];
59
BCM2835PropertyState property;
71
extern const GVecGen4 sqsub_op[4];
60
+ BCM2835RngState rng;
72
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
61
BCM2835MboxState mboxes;
73
+void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
62
SDHCIState sdhci;
74
+void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
63
} BCM2835PeripheralState;
75
+void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
64
diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h
76
+void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
65
new file mode 100644
77
66
index XXXXXXX..XXXXXXX
78
/*
67
--- /dev/null
79
* Forward to the isar_feature_* tests given a DisasContext pointer.
68
+++ b/include/hw/misc/bcm2835_rng.h
80
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
69
@@ -XXX,XX +XXX,XX @@
70
+/*
71
+ * BCM2835 Random Number Generator emulation
72
+ *
73
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
74
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
77
+ */
78
+
79
+#ifndef BCM2835_RNG_H
80
+#define BCM2835_RNG_H
81
+
82
+#include "hw/sysbus.h"
83
+
84
+#define TYPE_BCM2835_RNG "bcm2835-rng"
85
+#define BCM2835_RNG(obj) \
86
+ OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG)
87
+
88
+typedef struct {
89
+ SysBusDevice busdev;
90
+ MemoryRegion iomem;
91
+
92
+ uint32_t rng_ctrl;
93
+ uint32_t rng_status;
94
+} BCM2835RngState;
95
+
96
+#endif
97
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
98
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
99
--- a/hw/arm/bcm2835_peripherals.c
82
--- a/target/arm/neon_helper.c
100
+++ b/hw/arm/bcm2835_peripherals.c
83
+++ b/target/arm/neon_helper.c
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
84
@@ -XXX,XX +XXX,XX @@ NEON_VOP(abd_u32, neon_u32, 1)
102
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
85
} else { \
103
OBJECT(&s->gpu_bus_mr), &error_abort);
86
dest = src1 << tmp; \
104
87
}} while (0)
105
+ /* Random Number Generator */
88
-NEON_VOP(shl_u8, neon_u8, 4)
106
+ object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG);
89
NEON_VOP(shl_u16, neon_u16, 2)
107
+ object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL);
90
-NEON_VOP(shl_u32, neon_u32, 1)
108
+ qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default());
91
#undef NEON_FN
109
+
92
110
/* Extended Mass Media Controller */
93
-uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop)
111
object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
94
-{
112
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
95
- int8_t shift = (int8_t)shiftop;
113
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
96
- if (shift >= 64 || shift <= -64) {
114
sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
97
- val = 0;
115
qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
98
- } else if (shift < 0) {
116
99
- val >>= -shift;
117
+ /* Random Number Generator */
100
- } else {
118
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
101
- val <<= shift;
119
+ if (err) {
102
- }
120
+ error_propagate(errp, err);
103
- return val;
104
-}
105
-
106
#define NEON_FN(dest, src1, src2) do { \
107
int8_t tmp; \
108
tmp = (int8_t)src2; \
109
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop)
110
} else { \
111
dest = src1 << tmp; \
112
}} while (0)
113
-NEON_VOP(shl_s8, neon_s8, 4)
114
NEON_VOP(shl_s16, neon_s16, 2)
115
-NEON_VOP(shl_s32, neon_s32, 1)
116
#undef NEON_FN
117
118
-uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
119
-{
120
- int8_t shift = (int8_t)shiftop;
121
- int64_t val = valop;
122
- if (shift >= 64) {
123
- val = 0;
124
- } else if (shift <= -64) {
125
- val >>= 63;
126
- } else if (shift < 0) {
127
- val >>= -shift;
128
- } else {
129
- val <<= shift;
130
- }
131
- return val;
132
-}
133
-
134
#define NEON_FN(dest, src1, src2) do { \
135
int8_t tmp; \
136
tmp = (int8_t)src2; \
137
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/arm/translate-a64.c
140
+++ b/target/arm/translate-a64.c
141
@@ -XXX,XX +XXX,XX @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
142
break;
143
case 0x8: /* SSHL, USHL */
144
if (u) {
145
- gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
146
+ gen_ushl_i64(tcg_rd, tcg_rn, tcg_rm);
147
} else {
148
- gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
149
+ gen_sshl_i64(tcg_rd, tcg_rn, tcg_rm);
150
}
151
break;
152
case 0x9: /* SQSHL, UQSHL */
153
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
154
is_q ? 16 : 8, vec_full_reg_size(s),
155
(u ? uqsub_op : sqsub_op) + size);
156
return;
157
+ case 0x08: /* SSHL, USHL */
158
+ gen_gvec_op3(s, is_q, rd, rn, rm,
159
+ u ? &ushl_op[size] : &sshl_op[size]);
121
+ return;
160
+ return;
122
+ }
161
case 0x0c: /* SMAX, UMAX */
123
+
162
if (u) {
124
+ memory_region_add_subregion(&s->peri_mr, RNG_OFFSET,
163
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
125
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0));
164
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
126
+
165
genfn = fns[size][u];
127
/* Extended Mass Media Controller */
166
break;
128
object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
167
}
129
&err);
168
- case 0x8: /* SSHL, USHL */
130
diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c
169
- {
131
new file mode 100644
170
- static NeonGenTwoOpFn * const fns[3][2] = {
132
index XXXXXXX..XXXXXXX
171
- { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
133
--- /dev/null
172
- { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
134
+++ b/hw/misc/bcm2835_rng.c
173
- { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
135
@@ -XXX,XX +XXX,XX @@
174
- };
136
+/*
175
- genfn = fns[size][u];
137
+ * BCM2835 Random Number Generator emulation
176
- break;
138
+ *
177
- }
139
+ * Copyright (C) 2017 Marcin Chojnacki <marcinch7@gmail.com>
178
case 0x9: /* SQSHL, UQSHL */
140
+ *
179
{
141
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
180
static NeonGenTwoOpEnvFn * const fns[3][2] = {
142
+ * See the COPYING file in the top-level directory.
181
diff --git a/target/arm/translate.c b/target/arm/translate.c
143
+ */
182
index XXXXXXX..XXXXXXX 100644
144
+
183
--- a/target/arm/translate.c
145
+#include "qemu/osdep.h"
184
+++ b/target/arm/translate.c
146
+#include "qemu/log.h"
185
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
147
+#include "hw/misc/bcm2835_rng.h"
186
if (u) {
148
+
187
switch (size) {
149
+static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset,
188
case 1: gen_helper_neon_shl_u16(var, var, shift); break;
150
+ unsigned size)
189
- case 2: gen_helper_neon_shl_u32(var, var, shift); break;
151
+{
190
+ case 2: gen_ushl_i32(var, var, shift); break;
152
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
191
default: abort();
153
+ uint32_t res = 0;
192
}
154
+
193
} else {
155
+ assert(size == 4);
194
switch (size) {
156
+
195
case 1: gen_helper_neon_shl_s16(var, var, shift); break;
157
+ switch (offset) {
196
- case 2: gen_helper_neon_shl_s32(var, var, shift); break;
158
+ case 0x0: /* rng_ctrl */
197
+ case 2: gen_sshl_i32(var, var, shift); break;
159
+ res = s->rng_ctrl;
198
default: abort();
160
+ break;
199
}
161
+ case 0x4: /* rng_status */
200
}
162
+ res = s->rng_status | (1 << 24);
201
@@ -XXX,XX +XXX,XX @@ const GVecGen3 cmtst_op[4] = {
163
+ break;
202
.vece = MO_64 },
164
+ case 0x8: /* rng_data */
203
};
165
+ res = rand();
204
166
+ break;
205
+void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
167
+
206
+{
168
+ default:
207
+ TCGv_i32 lval = tcg_temp_new_i32();
169
+ qemu_log_mask(LOG_GUEST_ERROR,
208
+ TCGv_i32 rval = tcg_temp_new_i32();
170
+ "bcm2835_rng_read: Bad offset %x\n",
209
+ TCGv_i32 lsh = tcg_temp_new_i32();
171
+ (int)offset);
210
+ TCGv_i32 rsh = tcg_temp_new_i32();
172
+ res = 0;
211
+ TCGv_i32 zero = tcg_const_i32(0);
173
+ break;
212
+ TCGv_i32 max = tcg_const_i32(32);
174
+ }
213
+
175
+
214
+ /*
176
+ return res;
215
+ * Rely on the TCG guarantee that out of range shifts produce
177
+}
216
+ * unspecified results, not undefined behaviour (i.e. no trap).
178
+
217
+ * Discard out-of-range results after the fact.
179
+static void bcm2835_rng_write(void *opaque, hwaddr offset,
218
+ */
180
+ uint64_t value, unsigned size)
219
+ tcg_gen_ext8s_i32(lsh, shift);
181
+{
220
+ tcg_gen_neg_i32(rsh, lsh);
182
+ BCM2835RngState *s = (BCM2835RngState *)opaque;
221
+ tcg_gen_shl_i32(lval, src, lsh);
183
+
222
+ tcg_gen_shr_i32(rval, src, rsh);
184
+ assert(size == 4);
223
+ tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
185
+
224
+ tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
186
+ switch (offset) {
225
+
187
+ case 0x0: /* rng_ctrl */
226
+ tcg_temp_free_i32(lval);
188
+ s->rng_ctrl = value;
227
+ tcg_temp_free_i32(rval);
189
+ break;
228
+ tcg_temp_free_i32(lsh);
190
+ case 0x4: /* rng_status */
229
+ tcg_temp_free_i32(rsh);
191
+ /* we shouldn't let the guest write to bits [31..20] */
230
+ tcg_temp_free_i32(zero);
192
+ s->rng_status &= ~0xFFFFF; /* clear 20 lower bits */
231
+ tcg_temp_free_i32(max);
193
+ s->rng_status |= value & 0xFFFFF; /* set them to new value */
232
+}
194
+ break;
233
+
195
+
234
+void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
196
+ default:
235
+{
197
+ qemu_log_mask(LOG_GUEST_ERROR,
236
+ TCGv_i64 lval = tcg_temp_new_i64();
198
+ "bcm2835_rng_write: Bad offset %x\n",
237
+ TCGv_i64 rval = tcg_temp_new_i64();
199
+ (int)offset);
238
+ TCGv_i64 lsh = tcg_temp_new_i64();
200
+ break;
239
+ TCGv_i64 rsh = tcg_temp_new_i64();
201
+ }
240
+ TCGv_i64 zero = tcg_const_i64(0);
202
+}
241
+ TCGv_i64 max = tcg_const_i64(64);
203
+
242
+
204
+static const MemoryRegionOps bcm2835_rng_ops = {
243
+ /*
205
+ .read = bcm2835_rng_read,
244
+ * Rely on the TCG guarantee that out of range shifts produce
206
+ .write = bcm2835_rng_write,
245
+ * unspecified results, not undefined behaviour (i.e. no trap).
207
+ .endianness = DEVICE_NATIVE_ENDIAN,
246
+ * Discard out-of-range results after the fact.
247
+ */
248
+ tcg_gen_ext8s_i64(lsh, shift);
249
+ tcg_gen_neg_i64(rsh, lsh);
250
+ tcg_gen_shl_i64(lval, src, lsh);
251
+ tcg_gen_shr_i64(rval, src, rsh);
252
+ tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
253
+ tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
254
+
255
+ tcg_temp_free_i64(lval);
256
+ tcg_temp_free_i64(rval);
257
+ tcg_temp_free_i64(lsh);
258
+ tcg_temp_free_i64(rsh);
259
+ tcg_temp_free_i64(zero);
260
+ tcg_temp_free_i64(max);
261
+}
262
+
263
+static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
264
+ TCGv_vec src, TCGv_vec shift)
265
+{
266
+ TCGv_vec lval = tcg_temp_new_vec_matching(dst);
267
+ TCGv_vec rval = tcg_temp_new_vec_matching(dst);
268
+ TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
269
+ TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
270
+ TCGv_vec msk, max;
271
+
272
+ tcg_gen_neg_vec(vece, rsh, shift);
273
+ if (vece == MO_8) {
274
+ tcg_gen_mov_vec(lsh, shift);
275
+ } else {
276
+ msk = tcg_temp_new_vec_matching(dst);
277
+ tcg_gen_dupi_vec(vece, msk, 0xff);
278
+ tcg_gen_and_vec(vece, lsh, shift, msk);
279
+ tcg_gen_and_vec(vece, rsh, rsh, msk);
280
+ tcg_temp_free_vec(msk);
281
+ }
282
+
283
+ /*
284
+ * Rely on the TCG guarantee that out of range shifts produce
285
+ * unspecified results, not undefined behaviour (i.e. no trap).
286
+ * Discard out-of-range results after the fact.
287
+ */
288
+ tcg_gen_shlv_vec(vece, lval, src, lsh);
289
+ tcg_gen_shrv_vec(vece, rval, src, rsh);
290
+
291
+ max = tcg_temp_new_vec_matching(dst);
292
+ tcg_gen_dupi_vec(vece, max, 8 << vece);
293
+
294
+ /*
295
+ * The choice of LT (signed) and GEU (unsigned) are biased toward
296
+ * the instructions of the x86_64 host. For MO_8, the whole byte
297
+ * is significant so we must use an unsigned compare; otherwise we
298
+ * have already masked to a byte and so a signed compare works.
299
+ * Other tcg hosts have a full set of comparisons and do not care.
300
+ */
301
+ if (vece == MO_8) {
302
+ tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
303
+ tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
304
+ tcg_gen_andc_vec(vece, lval, lval, lsh);
305
+ tcg_gen_andc_vec(vece, rval, rval, rsh);
306
+ } else {
307
+ tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
308
+ tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
309
+ tcg_gen_and_vec(vece, lval, lval, lsh);
310
+ tcg_gen_and_vec(vece, rval, rval, rsh);
311
+ }
312
+ tcg_gen_or_vec(vece, dst, lval, rval);
313
+
314
+ tcg_temp_free_vec(max);
315
+ tcg_temp_free_vec(lval);
316
+ tcg_temp_free_vec(rval);
317
+ tcg_temp_free_vec(lsh);
318
+ tcg_temp_free_vec(rsh);
319
+}
320
+
321
+static const TCGOpcode ushl_list[] = {
322
+ INDEX_op_neg_vec, INDEX_op_shlv_vec,
323
+ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
208
+};
324
+};
209
+
325
+
210
+static const VMStateDescription vmstate_bcm2835_rng = {
326
+const GVecGen3 ushl_op[4] = {
211
+ .name = TYPE_BCM2835_RNG,
327
+ { .fniv = gen_ushl_vec,
212
+ .version_id = 1,
328
+ .fno = gen_helper_gvec_ushl_b,
213
+ .minimum_version_id = 1,
329
+ .opt_opc = ushl_list,
214
+ .fields = (VMStateField[]) {
330
+ .vece = MO_8 },
215
+ VMSTATE_UINT32(rng_ctrl, BCM2835RngState),
331
+ { .fniv = gen_ushl_vec,
216
+ VMSTATE_UINT32(rng_status, BCM2835RngState),
332
+ .fno = gen_helper_gvec_ushl_h,
217
+ VMSTATE_END_OF_LIST()
333
+ .opt_opc = ushl_list,
218
+ }
334
+ .vece = MO_16 },
335
+ { .fni4 = gen_ushl_i32,
336
+ .fniv = gen_ushl_vec,
337
+ .opt_opc = ushl_list,
338
+ .vece = MO_32 },
339
+ { .fni8 = gen_ushl_i64,
340
+ .fniv = gen_ushl_vec,
341
+ .opt_opc = ushl_list,
342
+ .vece = MO_64 },
219
+};
343
+};
220
+
344
+
221
+static void bcm2835_rng_init(Object *obj)
345
+void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
222
+{
346
+{
223
+ BCM2835RngState *s = BCM2835_RNG(obj);
347
+ TCGv_i32 lval = tcg_temp_new_i32();
224
+
348
+ TCGv_i32 rval = tcg_temp_new_i32();
225
+ memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s,
349
+ TCGv_i32 lsh = tcg_temp_new_i32();
226
+ TYPE_BCM2835_RNG, 0x10);
350
+ TCGv_i32 rsh = tcg_temp_new_i32();
227
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
351
+ TCGv_i32 zero = tcg_const_i32(0);
228
+}
352
+ TCGv_i32 max = tcg_const_i32(31);
229
+
353
+
230
+static void bcm2835_rng_reset(DeviceState *dev)
354
+ /*
231
+{
355
+ * Rely on the TCG guarantee that out of range shifts produce
232
+ BCM2835RngState *s = BCM2835_RNG(dev);
356
+ * unspecified results, not undefined behaviour (i.e. no trap).
233
+
357
+ * Discard out-of-range results after the fact.
234
+ s->rng_ctrl = 0;
358
+ */
235
+ s->rng_status = 0;
359
+ tcg_gen_ext8s_i32(lsh, shift);
236
+}
360
+ tcg_gen_neg_i32(rsh, lsh);
237
+
361
+ tcg_gen_shl_i32(lval, src, lsh);
238
+static void bcm2835_rng_class_init(ObjectClass *klass, void *data)
362
+ tcg_gen_umin_i32(rsh, rsh, max);
239
+{
363
+ tcg_gen_sar_i32(rval, src, rsh);
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
364
+ tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
241
+
365
+ tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
242
+ dc->reset = bcm2835_rng_reset;
366
+
243
+ dc->vmsd = &vmstate_bcm2835_rng;
367
+ tcg_temp_free_i32(lval);
244
+}
368
+ tcg_temp_free_i32(rval);
245
+
369
+ tcg_temp_free_i32(lsh);
246
+static TypeInfo bcm2835_rng_info = {
370
+ tcg_temp_free_i32(rsh);
247
+ .name = TYPE_BCM2835_RNG,
371
+ tcg_temp_free_i32(zero);
248
+ .parent = TYPE_SYS_BUS_DEVICE,
372
+ tcg_temp_free_i32(max);
249
+ .instance_size = sizeof(BCM2835RngState),
373
+}
250
+ .class_init = bcm2835_rng_class_init,
374
+
251
+ .instance_init = bcm2835_rng_init,
375
+void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
376
+{
377
+ TCGv_i64 lval = tcg_temp_new_i64();
378
+ TCGv_i64 rval = tcg_temp_new_i64();
379
+ TCGv_i64 lsh = tcg_temp_new_i64();
380
+ TCGv_i64 rsh = tcg_temp_new_i64();
381
+ TCGv_i64 zero = tcg_const_i64(0);
382
+ TCGv_i64 max = tcg_const_i64(63);
383
+
384
+ /*
385
+ * Rely on the TCG guarantee that out of range shifts produce
386
+ * unspecified results, not undefined behaviour (i.e. no trap).
387
+ * Discard out-of-range results after the fact.
388
+ */
389
+ tcg_gen_ext8s_i64(lsh, shift);
390
+ tcg_gen_neg_i64(rsh, lsh);
391
+ tcg_gen_shl_i64(lval, src, lsh);
392
+ tcg_gen_umin_i64(rsh, rsh, max);
393
+ tcg_gen_sar_i64(rval, src, rsh);
394
+ tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
395
+ tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
396
+
397
+ tcg_temp_free_i64(lval);
398
+ tcg_temp_free_i64(rval);
399
+ tcg_temp_free_i64(lsh);
400
+ tcg_temp_free_i64(rsh);
401
+ tcg_temp_free_i64(zero);
402
+ tcg_temp_free_i64(max);
403
+}
404
+
405
+static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
406
+ TCGv_vec src, TCGv_vec shift)
407
+{
408
+ TCGv_vec lval = tcg_temp_new_vec_matching(dst);
409
+ TCGv_vec rval = tcg_temp_new_vec_matching(dst);
410
+ TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
411
+ TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
412
+ TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
413
+
414
+ /*
415
+ * Rely on the TCG guarantee that out of range shifts produce
416
+ * unspecified results, not undefined behaviour (i.e. no trap).
417
+ * Discard out-of-range results after the fact.
418
+ */
419
+ tcg_gen_neg_vec(vece, rsh, shift);
420
+ if (vece == MO_8) {
421
+ tcg_gen_mov_vec(lsh, shift);
422
+ } else {
423
+ tcg_gen_dupi_vec(vece, tmp, 0xff);
424
+ tcg_gen_and_vec(vece, lsh, shift, tmp);
425
+ tcg_gen_and_vec(vece, rsh, rsh, tmp);
426
+ }
427
+
428
+ /* Bound rsh so out of bound right shift gets -1. */
429
+ tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
430
+ tcg_gen_umin_vec(vece, rsh, rsh, tmp);
431
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
432
+
433
+ tcg_gen_shlv_vec(vece, lval, src, lsh);
434
+ tcg_gen_sarv_vec(vece, rval, src, rsh);
435
+
436
+ /* Select in-bound left shift. */
437
+ tcg_gen_andc_vec(vece, lval, lval, tmp);
438
+
439
+ /* Select between left and right shift. */
440
+ if (vece == MO_8) {
441
+ tcg_gen_dupi_vec(vece, tmp, 0);
442
+ tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
443
+ } else {
444
+ tcg_gen_dupi_vec(vece, tmp, 0x80);
445
+ tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
446
+ }
447
+
448
+ tcg_temp_free_vec(lval);
449
+ tcg_temp_free_vec(rval);
450
+ tcg_temp_free_vec(lsh);
451
+ tcg_temp_free_vec(rsh);
452
+ tcg_temp_free_vec(tmp);
453
+}
454
+
455
+static const TCGOpcode sshl_list[] = {
456
+ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
457
+ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
252
+};
458
+};
253
+
459
+
254
+static void bcm2835_rng_register_types(void)
460
+const GVecGen3 sshl_op[4] = {
255
+{
461
+ { .fniv = gen_sshl_vec,
256
+ type_register_static(&bcm2835_rng_info);
462
+ .fno = gen_helper_gvec_sshl_b,
257
+}
463
+ .opt_opc = sshl_list,
258
+
464
+ .vece = MO_8 },
259
+type_init(bcm2835_rng_register_types)
465
+ { .fniv = gen_sshl_vec,
466
+ .fno = gen_helper_gvec_sshl_h,
467
+ .opt_opc = sshl_list,
468
+ .vece = MO_16 },
469
+ { .fni4 = gen_sshl_i32,
470
+ .fniv = gen_sshl_vec,
471
+ .opt_opc = sshl_list,
472
+ .vece = MO_32 },
473
+ { .fni8 = gen_sshl_i64,
474
+ .fniv = gen_sshl_vec,
475
+ .opt_opc = sshl_list,
476
+ .vece = MO_64 },
477
+};
478
+
479
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
480
TCGv_vec a, TCGv_vec b)
481
{
482
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
483
vec_size, vec_size);
484
}
485
return 0;
486
+
487
+ case NEON_3R_VSHL:
488
+ /* Note the operation is vshl vd,vm,vn */
489
+ tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
490
+ u ? &ushl_op[size] : &sshl_op[size]);
491
+ return 0;
492
}
493
494
if (size == 3) {
495
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
496
neon_load_reg64(cpu_V0, rn + pass);
497
neon_load_reg64(cpu_V1, rm + pass);
498
switch (op) {
499
- case NEON_3R_VSHL:
500
- if (u) {
501
- gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
502
- } else {
503
- gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
504
- }
505
- break;
506
case NEON_3R_VQSHL:
507
if (u) {
508
gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
509
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
510
}
511
pairwise = 0;
512
switch (op) {
513
- case NEON_3R_VSHL:
514
case NEON_3R_VQSHL:
515
case NEON_3R_VRSHL:
516
case NEON_3R_VQRSHL:
517
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
518
case NEON_3R_VHSUB:
519
GEN_NEON_INTEGER_OP(hsub);
520
break;
521
- case NEON_3R_VSHL:
522
- GEN_NEON_INTEGER_OP(shl);
523
- break;
524
case NEON_3R_VQSHL:
525
GEN_NEON_INTEGER_OP_ENV(qshl);
526
break;
527
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
528
}
529
} else {
530
if (input_unsigned) {
531
- gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
532
+ gen_ushl_i64(cpu_V0, in, tmp64);
533
} else {
534
- gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
535
+ gen_sshl_i64(cpu_V0, in, tmp64);
536
}
537
}
538
tmp = tcg_temp_new_i32();
539
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
540
index XXXXXXX..XXXXXXX 100644
541
--- a/target/arm/vec_helper.c
542
+++ b/target/arm/vec_helper.c
543
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm,
544
do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc,
545
get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
546
}
547
+
548
+void HELPER(gvec_sshl_b)(void *vd, void *vn, void *vm, uint32_t desc)
549
+{
550
+ intptr_t i, opr_sz = simd_oprsz(desc);
551
+ int8_t *d = vd, *n = vn, *m = vm;
552
+
553
+ for (i = 0; i < opr_sz; ++i) {
554
+ int8_t mm = m[i];
555
+ int8_t nn = n[i];
556
+ int8_t res = 0;
557
+ if (mm >= 0) {
558
+ if (mm < 8) {
559
+ res = nn << mm;
560
+ }
561
+ } else {
562
+ res = nn >> (mm > -8 ? -mm : 7);
563
+ }
564
+ d[i] = res;
565
+ }
566
+ clear_tail(d, opr_sz, simd_maxsz(desc));
567
+}
568
+
569
+void HELPER(gvec_sshl_h)(void *vd, void *vn, void *vm, uint32_t desc)
570
+{
571
+ intptr_t i, opr_sz = simd_oprsz(desc);
572
+ int16_t *d = vd, *n = vn, *m = vm;
573
+
574
+ for (i = 0; i < opr_sz / 2; ++i) {
575
+ int8_t mm = m[i]; /* only 8 bits of shift are significant */
576
+ int16_t nn = n[i];
577
+ int16_t res = 0;
578
+ if (mm >= 0) {
579
+ if (mm < 16) {
580
+ res = nn << mm;
581
+ }
582
+ } else {
583
+ res = nn >> (mm > -16 ? -mm : 15);
584
+ }
585
+ d[i] = res;
586
+ }
587
+ clear_tail(d, opr_sz, simd_maxsz(desc));
588
+}
589
+
590
+void HELPER(gvec_ushl_b)(void *vd, void *vn, void *vm, uint32_t desc)
591
+{
592
+ intptr_t i, opr_sz = simd_oprsz(desc);
593
+ uint8_t *d = vd, *n = vn, *m = vm;
594
+
595
+ for (i = 0; i < opr_sz; ++i) {
596
+ int8_t mm = m[i];
597
+ uint8_t nn = n[i];
598
+ uint8_t res = 0;
599
+ if (mm >= 0) {
600
+ if (mm < 8) {
601
+ res = nn << mm;
602
+ }
603
+ } else {
604
+ if (mm > -8) {
605
+ res = nn >> -mm;
606
+ }
607
+ }
608
+ d[i] = res;
609
+ }
610
+ clear_tail(d, opr_sz, simd_maxsz(desc));
611
+}
612
+
613
+void HELPER(gvec_ushl_h)(void *vd, void *vn, void *vm, uint32_t desc)
614
+{
615
+ intptr_t i, opr_sz = simd_oprsz(desc);
616
+ uint16_t *d = vd, *n = vn, *m = vm;
617
+
618
+ for (i = 0; i < opr_sz / 2; ++i) {
619
+ int8_t mm = m[i]; /* only 8 bits of shift are significant */
620
+ uint16_t nn = n[i];
621
+ uint16_t res = 0;
622
+ if (mm >= 0) {
623
+ if (mm < 16) {
624
+ res = nn << mm;
625
+ }
626
+ } else {
627
+ if (mm > -16) {
628
+ res = nn >> -mm;
629
+ }
630
+ }
631
+ d[i] = res;
632
+ }
633
+ clear_tail(d, opr_sz, simd_maxsz(desc));
634
+}
260
--
635
--
261
2.7.4
636
2.20.1
262
637
263
638
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The gvec form will be needed for implementing SVE2.
4
5
Extend the implementation to operate on uint64_t instead of uint32_t.
6
Use a counted inner loop instead of terminating when op1 goes to zero,
7
looking toward the required implementation for ARMv8.4-DIT.
8
9
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200216214232.4230-3-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
target/arm/helper.h | 3 ++-
16
target/arm/neon_helper.c | 22 ----------------------
17
target/arm/translate-a64.c | 10 +++-------
18
target/arm/translate.c | 11 ++++-------
19
target/arm/vec_helper.c | 30 ++++++++++++++++++++++++++++++
20
5 files changed, 39 insertions(+), 37 deletions(-)
21
22
diff --git a/target/arm/helper.h b/target/arm/helper.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.h
25
+++ b/target/arm/helper.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_sub_u8, i32, i32, i32)
27
DEF_HELPER_2(neon_sub_u16, i32, i32, i32)
28
DEF_HELPER_2(neon_mul_u8, i32, i32, i32)
29
DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
30
-DEF_HELPER_2(neon_mul_p8, i32, i32, i32)
31
DEF_HELPER_2(neon_mull_p8, i64, i32, i32)
32
33
DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_sshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
DEF_HELPER_FLAGS_4(gvec_ushl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
38
+DEF_HELPER_FLAGS_4(gvec_pmul_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+
40
#ifdef TARGET_AARCH64
41
#include "helper-a64.h"
42
#include "helper-sve.h"
43
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/neon_helper.c
46
+++ b/target/arm/neon_helper.c
47
@@ -XXX,XX +XXX,XX @@ NEON_VOP(mul_u16, neon_u16, 2)
48
49
/* Polynomial multiplication is like integer multiplication except the
50
partial products are XORed, not added. */
51
-uint32_t HELPER(neon_mul_p8)(uint32_t op1, uint32_t op2)
52
-{
53
- uint32_t mask;
54
- uint32_t result;
55
- result = 0;
56
- while (op1) {
57
- mask = 0;
58
- if (op1 & 1)
59
- mask |= 0xff;
60
- if (op1 & (1 << 8))
61
- mask |= (0xff << 8);
62
- if (op1 & (1 << 16))
63
- mask |= (0xff << 16);
64
- if (op1 & (1 << 24))
65
- mask |= (0xff << 24);
66
- result ^= op2 & mask;
67
- op1 = (op1 >> 1) & 0x7f7f7f7f;
68
- op2 = (op2 << 1) & 0xfefefefe;
69
- }
70
- return result;
71
-}
72
-
73
uint64_t HELPER(neon_mull_p8)(uint32_t op1, uint32_t op2)
74
{
75
uint64_t result = 0;
76
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/target/arm/translate-a64.c
79
+++ b/target/arm/translate-a64.c
80
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
81
case 0x13: /* MUL, PMUL */
82
if (!u) { /* MUL */
83
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_mul, size);
84
- return;
85
+ } else { /* PMUL */
86
+ gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0, gen_helper_gvec_pmul_b);
87
}
88
- break;
89
+ return;
90
case 0x12: /* MLA, MLS */
91
if (u) {
92
gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
93
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
94
genfn = fns[size][u];
95
break;
96
}
97
- case 0x13: /* MUL, PMUL */
98
- assert(u); /* PMUL */
99
- assert(size == 0);
100
- genfn = gen_helper_neon_mul_p8;
101
- break;
102
case 0x16: /* SQDMULH, SQRDMULH */
103
{
104
static NeonGenTwoOpEnvFn * const fns[2][2] = {
105
diff --git a/target/arm/translate.c b/target/arm/translate.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate.c
108
+++ b/target/arm/translate.c
109
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
110
111
case NEON_3R_VMUL: /* VMUL */
112
if (u) {
113
- /* Polynomial case allows only P8 and is handled below. */
114
+ /* Polynomial case allows only P8. */
115
if (size != 0) {
116
return 1;
117
}
118
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
119
+ 0, gen_helper_gvec_pmul_b);
120
} else {
121
tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
122
vec_size, vec_size);
123
- return 0;
124
}
125
- break;
126
+ return 0;
127
128
case NEON_3R_VML: /* VMLA, VMLS */
129
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
130
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
131
tmp2 = neon_load_reg(rd, pass);
132
gen_neon_add(size, tmp, tmp2);
133
break;
134
- case NEON_3R_VMUL:
135
- /* VMUL.P8; other cases already eliminated. */
136
- gen_helper_neon_mul_p8(tmp, tmp, tmp2);
137
- break;
138
case NEON_3R_VPMAX:
139
GEN_NEON_INTEGER_OP(pmax);
140
break;
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
144
+++ b/target/arm/vec_helper.c
145
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_ushl_h)(void *vd, void *vn, void *vm, uint32_t desc)
146
}
147
clear_tail(d, opr_sz, simd_maxsz(desc));
148
}
149
+
150
+/*
151
+ * 8x8->8 polynomial multiply.
152
+ *
153
+ * Polynomial multiplication is like integer multiplication except the
154
+ * partial products are XORed, not added.
155
+ *
156
+ * TODO: expose this as a generic vector operation, as it is a common
157
+ * crypto building block.
158
+ */
159
+void HELPER(gvec_pmul_b)(void *vd, void *vn, void *vm, uint32_t desc)
160
+{
161
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
162
+ uint64_t *d = vd, *n = vn, *m = vm;
163
+
164
+ for (i = 0; i < opr_sz / 8; ++i) {
165
+ uint64_t nn = n[i];
166
+ uint64_t mm = m[i];
167
+ uint64_t rr = 0;
168
+
169
+ for (j = 0; j < 8; ++j) {
170
+ uint64_t mask = (nn & 0x0101010101010101ull) * 0xff;
171
+ rr ^= mm & mask;
172
+ mm = (mm << 1) & 0xfefefefefefefefeull;
173
+ nn >>= 1;
174
+ }
175
+ d[i] = rr;
176
+ }
177
+ clear_tail(d, opr_sz, simd_maxsz(desc));
178
+}
179
--
180
2.20.1
181
182
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The gvec form will be needed for implementing SVE2.
4
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200216214232.4230-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.h | 4 +---
12
target/arm/neon_helper.c | 30 ------------------------------
13
target/arm/translate-a64.c | 28 +++-------------------------
14
target/arm/translate.c | 16 ++--------------
15
target/arm/vec_helper.c | 33 +++++++++++++++++++++++++++++++++
16
5 files changed, 39 insertions(+), 72 deletions(-)
17
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
21
+++ b/target/arm/helper.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
23
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
24
DEF_HELPER_2(dc_zva, void, env, i64)
25
26
-DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
27
-DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
28
-
29
DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
30
void, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_4(gvec_ushl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
35
DEF_HELPER_FLAGS_4(gvec_pmul_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
38
#ifdef TARGET_AARCH64
39
#include "helper-a64.h"
40
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/neon_helper.c
43
+++ b/target/arm/neon_helper.c
44
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_zip16)(void *vd, void *vm)
45
rm[0] = m0;
46
rd[0] = d0;
47
}
48
-
49
-/* Helper function for 64 bit polynomial multiply case:
50
- * perform PolynomialMult(op1, op2) and return either the top or
51
- * bottom half of the 128 bit result.
52
- */
53
-uint64_t HELPER(neon_pmull_64_lo)(uint64_t op1, uint64_t op2)
54
-{
55
- int bitnum;
56
- uint64_t res = 0;
57
-
58
- for (bitnum = 0; bitnum < 64; bitnum++) {
59
- if (op1 & (1ULL << bitnum)) {
60
- res ^= op2 << bitnum;
61
- }
62
- }
63
- return res;
64
-}
65
-uint64_t HELPER(neon_pmull_64_hi)(uint64_t op1, uint64_t op2)
66
-{
67
- int bitnum;
68
- uint64_t res = 0;
69
-
70
- /* bit 0 of op1 can't influence the high 64 bits at all */
71
- for (bitnum = 1; bitnum < 64; bitnum++) {
72
- if (op1 & (1ULL << bitnum)) {
73
- res ^= op2 >> (64 - bitnum);
74
- }
75
- }
76
- return res;
77
-}
78
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/translate-a64.c
81
+++ b/target/arm/translate-a64.c
82
@@ -XXX,XX +XXX,XX @@ static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
83
clear_vec_high(s, is_q, rd);
84
}
85
86
-static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
87
-{
88
- /* PMULL of 64 x 64 -> 128 is an odd special case because it
89
- * is the only three-reg-diff instruction which produces a
90
- * 128-bit wide result from a single operation. However since
91
- * it's possible to calculate the two halves more or less
92
- * separately we just use two helper calls.
93
- */
94
- TCGv_i64 tcg_op1 = tcg_temp_new_i64();
95
- TCGv_i64 tcg_op2 = tcg_temp_new_i64();
96
- TCGv_i64 tcg_res = tcg_temp_new_i64();
97
-
98
- read_vec_element(s, tcg_op1, rn, is_q, MO_64);
99
- read_vec_element(s, tcg_op2, rm, is_q, MO_64);
100
- gen_helper_neon_pmull_64_lo(tcg_res, tcg_op1, tcg_op2);
101
- write_vec_element(s, tcg_res, rd, 0, MO_64);
102
- gen_helper_neon_pmull_64_hi(tcg_res, tcg_op1, tcg_op2);
103
- write_vec_element(s, tcg_res, rd, 1, MO_64);
104
-
105
- tcg_temp_free_i64(tcg_op1);
106
- tcg_temp_free_i64(tcg_op2);
107
- tcg_temp_free_i64(tcg_res);
108
-}
109
-
110
/* AdvSIMD three different
111
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 0
112
* +---+---+---+-----------+------+---+------+--------+-----+------+------+
113
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
114
if (!fp_access_check(s)) {
115
return;
116
}
117
- handle_pmull_64(s, is_q, rd, rn, rm);
118
+ /* The Q field specifies lo/hi half input for this insn. */
119
+ gen_gvec_op3_ool(s, true, rd, rn, rm, is_q,
120
+ gen_helper_gvec_pmull_q);
121
return;
122
}
123
goto is_widening;
124
diff --git a/target/arm/translate.c b/target/arm/translate.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/target/arm/translate.c
127
+++ b/target/arm/translate.c
128
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
129
* outside the loop below as it only performs a single pass.
130
*/
131
if (op == 14 && size == 2) {
132
- TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
133
-
134
if (!dc_isar_feature(aa32_pmull, s)) {
135
return 1;
136
}
137
- tcg_rn = tcg_temp_new_i64();
138
- tcg_rm = tcg_temp_new_i64();
139
- tcg_rd = tcg_temp_new_i64();
140
- neon_load_reg64(tcg_rn, rn);
141
- neon_load_reg64(tcg_rm, rm);
142
- gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
143
- neon_store_reg64(tcg_rd, rd);
144
- gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
145
- neon_store_reg64(tcg_rd, rd + 1);
146
- tcg_temp_free_i64(tcg_rn);
147
- tcg_temp_free_i64(tcg_rm);
148
- tcg_temp_free_i64(tcg_rd);
149
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
150
+ 0, gen_helper_gvec_pmull_q);
151
return 0;
152
}
153
154
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/vec_helper.c
157
+++ b/target/arm/vec_helper.c
158
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_pmul_b)(void *vd, void *vn, void *vm, uint32_t desc)
159
}
160
clear_tail(d, opr_sz, simd_maxsz(desc));
161
}
162
+
163
+/*
164
+ * 64x64->128 polynomial multiply.
165
+ * Because of the lanes are not accessed in strict columns,
166
+ * this probably cannot be turned into a generic helper.
167
+ */
168
+void HELPER(gvec_pmull_q)(void *vd, void *vn, void *vm, uint32_t desc)
169
+{
170
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
171
+ intptr_t hi = simd_data(desc);
172
+ uint64_t *d = vd, *n = vn, *m = vm;
173
+
174
+ for (i = 0; i < opr_sz / 8; i += 2) {
175
+ uint64_t nn = n[i + hi];
176
+ uint64_t mm = m[i + hi];
177
+ uint64_t rhi = 0;
178
+ uint64_t rlo = 0;
179
+
180
+ /* Bit 0 can only influence the low 64-bit result. */
181
+ if (nn & 1) {
182
+ rlo = mm;
183
+ }
184
+
185
+ for (j = 1; j < 64; ++j) {
186
+ uint64_t mask = -((nn >> j) & 1);
187
+ rlo ^= (mm << j) & mask;
188
+ rhi ^= (mm >> (64 - j)) & mask;
189
+ }
190
+ d[i] = rlo;
191
+ d[i + 1] = rhi;
192
+ }
193
+ clear_tail(d, opr_sz, simd_maxsz(desc));
194
+}
195
--
196
2.20.1
197
198
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We still need two different helpers, since NEON and SVE2 get the
4
inputs from different locations within the source vector. However,
5
we can convert both to the same internal form for computation.
6
7
The sve2 helper is not used yet, but adding it with this patch
8
helps illustrate why the neon changes are helpful.
9
10
Tested-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200216214232.4230-5-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/helper-sve.h | 2 ++
17
target/arm/helper.h | 3 +-
18
target/arm/neon_helper.c | 32 --------------------
19
target/arm/translate-a64.c | 27 +++++++++++------
20
target/arm/translate.c | 26 ++++++++---------
21
target/arm/vec_helper.c | 60 ++++++++++++++++++++++++++++++++++++++
22
6 files changed, 95 insertions(+), 55 deletions(-)
23
24
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper-sve.h
27
+++ b/target/arm/helper-sve.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_stdd_le_zd, TCG_CALL_NO_WG,
29
void, env, ptr, ptr, ptr, tl, i32)
30
DEF_HELPER_FLAGS_6(sve_stdd_be_zd, TCG_CALL_NO_WG,
31
void, env, ptr, ptr, ptr, tl, i32)
32
+
33
+DEF_HELPER_FLAGS_4(sve2_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
diff --git a/target/arm/helper.h b/target/arm/helper.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/helper.h
37
+++ b/target/arm/helper.h
38
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_sub_u8, i32, i32, i32)
39
DEF_HELPER_2(neon_sub_u16, i32, i32, i32)
40
DEF_HELPER_2(neon_mul_u8, i32, i32, i32)
41
DEF_HELPER_2(neon_mul_u16, i32, i32, i32)
42
-DEF_HELPER_2(neon_mull_p8, i64, i32, i32)
43
44
DEF_HELPER_2(neon_tst_u8, i32, i32, i32)
45
DEF_HELPER_2(neon_tst_u16, i32, i32, i32)
46
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_ushl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
47
DEF_HELPER_FLAGS_4(gvec_pmul_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
48
DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
50
+DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
+
52
#ifdef TARGET_AARCH64
53
#include "helper-a64.h"
54
#include "helper-sve.h"
55
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/neon_helper.c
58
+++ b/target/arm/neon_helper.c
59
@@ -XXX,XX +XXX,XX @@ NEON_VOP(mul_u8, neon_u8, 4)
60
NEON_VOP(mul_u16, neon_u16, 2)
61
#undef NEON_FN
62
63
-/* Polynomial multiplication is like integer multiplication except the
64
- partial products are XORed, not added. */
65
-uint64_t HELPER(neon_mull_p8)(uint32_t op1, uint32_t op2)
66
-{
67
- uint64_t result = 0;
68
- uint64_t mask;
69
- uint64_t op2ex = op2;
70
- op2ex = (op2ex & 0xff) |
71
- ((op2ex & 0xff00) << 8) |
72
- ((op2ex & 0xff0000) << 16) |
73
- ((op2ex & 0xff000000) << 24);
74
- while (op1) {
75
- mask = 0;
76
- if (op1 & 1) {
77
- mask |= 0xffff;
78
- }
79
- if (op1 & (1 << 8)) {
80
- mask |= (0xffffU << 16);
81
- }
82
- if (op1 & (1 << 16)) {
83
- mask |= (0xffffULL << 32);
84
- }
85
- if (op1 & (1 << 24)) {
86
- mask |= (0xffffULL << 48);
87
- }
88
- result ^= op2ex & mask;
89
- op1 = (op1 >> 1) & 0x7f7f7f7f;
90
- op2ex <<= 1;
91
- }
92
- return result;
93
-}
94
-
95
#define NEON_FN(dest, src1, src2) dest = (src1 & src2) ? -1 : 0
96
NEON_VOP(tst_u8, neon_u8, 4)
97
NEON_VOP(tst_u16, neon_u16, 2)
98
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/arm/translate-a64.c
101
+++ b/target/arm/translate-a64.c
102
@@ -XXX,XX +XXX,XX @@ static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
103
gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
104
tcg_passres, tcg_passres);
105
break;
106
- case 14: /* PMULL */
107
- assert(size == 0);
108
- gen_helper_neon_mull_p8(tcg_passres, tcg_op1, tcg_op2);
109
- break;
110
default:
111
g_assert_not_reached();
112
}
113
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
114
handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
115
break;
116
case 14: /* PMULL, PMULL2 */
117
- if (is_u || size == 1 || size == 2) {
118
+ if (is_u) {
119
unallocated_encoding(s);
120
return;
121
}
122
- if (size == 3) {
123
+ switch (size) {
124
+ case 0: /* PMULL.P8 */
125
+ if (!fp_access_check(s)) {
126
+ return;
127
+ }
128
+ /* The Q field specifies lo/hi half input for this insn. */
129
+ gen_gvec_op3_ool(s, true, rd, rn, rm, is_q,
130
+ gen_helper_neon_pmull_h);
131
+ break;
132
+
133
+ case 3: /* PMULL.P64 */
134
if (!dc_isar_feature(aa64_pmull, s)) {
135
unallocated_encoding(s);
136
return;
137
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
138
/* The Q field specifies lo/hi half input for this insn. */
139
gen_gvec_op3_ool(s, true, rd, rn, rm, is_q,
140
gen_helper_gvec_pmull_q);
141
- return;
142
+ break;
143
+
144
+ default:
145
+ unallocated_encoding(s);
146
+ break;
147
}
148
- goto is_widening;
149
+ return;
150
case 9: /* SQDMLAL, SQDMLAL2 */
151
case 11: /* SQDMLSL, SQDMLSL2 */
152
case 13: /* SQDMULL, SQDMULL2 */
153
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
154
unallocated_encoding(s);
155
return;
156
}
157
- is_widening:
158
if (!fp_access_check(s)) {
159
return;
160
}
161
diff --git a/target/arm/translate.c b/target/arm/translate.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/translate.c
164
+++ b/target/arm/translate.c
165
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
166
return 1;
167
}
168
169
- /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
170
- * outside the loop below as it only performs a single pass.
171
- */
172
- if (op == 14 && size == 2) {
173
- if (!dc_isar_feature(aa32_pmull, s)) {
174
- return 1;
175
+ /* Handle polynomial VMULL in a single pass. */
176
+ if (op == 14) {
177
+ if (size == 0) {
178
+ /* VMULL.P8 */
179
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
180
+ 0, gen_helper_neon_pmull_h);
181
+ } else {
182
+ /* VMULL.P64 */
183
+ if (!dc_isar_feature(aa32_pmull, s)) {
184
+ return 1;
185
+ }
186
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
187
+ 0, gen_helper_gvec_pmull_q);
188
}
189
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
190
- 0, gen_helper_gvec_pmull_q);
191
return 0;
192
}
193
194
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
195
/* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
196
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
197
break;
198
- case 14: /* Polynomial VMULL */
199
- gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
200
- tcg_temp_free_i32(tmp2);
201
- tcg_temp_free_i32(tmp);
202
- break;
203
default: /* 15 is RESERVED: caught earlier */
204
abort();
205
}
206
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
207
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/vec_helper.c
209
+++ b/target/arm/vec_helper.c
210
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_pmull_q)(void *vd, void *vn, void *vm, uint32_t desc)
211
}
212
clear_tail(d, opr_sz, simd_maxsz(desc));
213
}
214
+
215
+/*
216
+ * 8x8->16 polynomial multiply.
217
+ *
218
+ * The byte inputs are expanded to (or extracted from) half-words.
219
+ * Note that neon and sve2 get the inputs from different positions.
220
+ * This allows 4 bytes to be processed in parallel with uint64_t.
221
+ */
222
+
223
+static uint64_t expand_byte_to_half(uint64_t x)
224
+{
225
+ return (x & 0x000000ff)
226
+ | ((x & 0x0000ff00) << 8)
227
+ | ((x & 0x00ff0000) << 16)
228
+ | ((x & 0xff000000) << 24);
229
+}
230
+
231
+static uint64_t pmull_h(uint64_t op1, uint64_t op2)
232
+{
233
+ uint64_t result = 0;
234
+ int i;
235
+
236
+ for (i = 0; i < 8; ++i) {
237
+ uint64_t mask = (op1 & 0x0001000100010001ull) * 0xffff;
238
+ result ^= op2 & mask;
239
+ op1 >>= 1;
240
+ op2 <<= 1;
241
+ }
242
+ return result;
243
+}
244
+
245
+void HELPER(neon_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc)
246
+{
247
+ int hi = simd_data(desc);
248
+ uint64_t *d = vd, *n = vn, *m = vm;
249
+ uint64_t nn = n[hi], mm = m[hi];
250
+
251
+ d[0] = pmull_h(expand_byte_to_half(nn), expand_byte_to_half(mm));
252
+ nn >>= 32;
253
+ mm >>= 32;
254
+ d[1] = pmull_h(expand_byte_to_half(nn), expand_byte_to_half(mm));
255
+
256
+ clear_tail(d, 16, simd_maxsz(desc));
257
+}
258
+
259
+#ifdef TARGET_AARCH64
260
+void HELPER(sve2_pmull_h)(void *vd, void *vn, void *vm, uint32_t desc)
261
+{
262
+ int shift = simd_data(desc) * 8;
263
+ intptr_t i, opr_sz = simd_oprsz(desc);
264
+ uint64_t *d = vd, *n = vn, *m = vm;
265
+
266
+ for (i = 0; i < opr_sz / 8; ++i) {
267
+ uint64_t nn = (n[i] >> shift) & 0x00ff00ff00ff00ffull;
268
+ uint64_t mm = (m[i] >> shift) & 0x00ff00ff00ff00ffull;
269
+
270
+ d[i] = pmull_h(nn, mm);
271
+ }
272
+}
273
+#endif
274
--
275
2.20.1
276
277
diff view generated by jsdifflib
New patch
1
From: Francisco Iglesias <francisco.iglesias@xilinx.com>
1
2
3
Correct the number of dummy cycles required by the FAST_READ_4 command (to
4
be eight, one dummy byte).
5
6
Fixes: ef06ca3946 ("xilinx_spips: Add support for RX discard and RX drain")
7
Suggested-by: Cédric Le Goater <clg@kaod.org>
8
Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20200218113350.6090-1-frasse.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/ssi/xilinx_spips.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/xilinx_spips.c
19
+++ b/hw/ssi/xilinx_spips.c
20
@@ -XXX,XX +XXX,XX @@ static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
21
case FAST_READ:
22
case DOR:
23
case QOR:
24
+ case FAST_READ_4:
25
case DOR_4:
26
case QOR_4:
27
return 1;
28
case DIOR:
29
- case FAST_READ_4:
30
case DIOR_4:
31
return 2;
32
case QIOR:
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
In 2.9 ITS will block save/restore and migration use cases. As such,
3
Booting the r2d machine from flash fails because flash is not discovered.
4
let's introduce a user option that allows to turn its instantiation
4
Looking at the flattened memory tree, we see the following.
5
off, along with GICv3. With the "its" option turned false, migration
6
will be possible, obviously at the expense of MSI support (with GICv3).
7
5
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
FlatView #1
9
Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com
7
AS "memory", root: system
8
AS "cpu-memory-0", root: system
9
AS "sh_pci_host", root: bus master container
10
Root memory region: system
11
0000000000000000-000000000000ffff (prio 0, i/o): io
12
0000000000010000-0000000000ffffff (prio 0, i/o): r2d.flash @0000000000010000
13
14
The overlapping memory region is sh_pci.isa, ie the ISA I/O region bridge.
15
This region is initially assigned to address 0xfe240000, but overwritten
16
with a write into the PCIIOBR register. This write is expected to adjust
17
the PCI memory window, but not to change the region's base adddress.
18
19
Peter Maydell provided the following detailed explanation.
20
21
"Section 22.3.7 and in particular figure 22.3 (of "SSH7751R user's manual:
22
hardware") are clear about how this is supposed to work: there is a window
23
at 0xfe240000 in the system register space for PCI I/O space. When the CPU
24
makes an access into that area, the PCI controller calculates the PCI
25
address to use by combining bits 0..17 of the system address with the
26
bits 31..18 value that the guest has put into the PCIIOBR. That is, writing
27
to the PCIIOBR changes which section of the IO address space is visible in
28
the 0xfe240000 window. Instead what QEMU's implementation does is move the
29
window to whatever value the guest writes to the PCIIOBR register -- so if
30
the guest writes 0 we put the window at 0 in system address space."
31
32
Fix the problem by calling memory_region_set_alias_offset() instead of
33
removing and re-adding the PCI ISA subregion on writes into PCIIOBR.
34
At the same time, in sh_pci_device_realize(), don't set iobr since
35
it is overwritten later anyway. Instead, pass the base address to
36
memory_region_add_subregion() directly.
37
38
Many thanks to Peter Maydell for the detailed problem analysis, and for
39
providing suggestions on how to fix the problem.
40
41
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
42
Message-id: 20200218201050.15273-1-linux@roeck-us.net
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
45
---
13
include/hw/arm/virt.h | 1 +
46
hw/sh4/sh_pci.c | 11 +++--------
14
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++--
47
1 file changed, 3 insertions(+), 8 deletions(-)
15
2 files changed, 30 insertions(+), 2 deletions(-)
16
48
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
49
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
18
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
51
--- a/hw/sh4/sh_pci.c
20
+++ b/include/hw/arm/virt.h
52
+++ b/hw/sh4/sh_pci.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
53
@@ -XXX,XX +XXX,XX @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
22
FWCfgState *fw_cfg;
54
pcic->mbr = val & 0xff000001;
23
bool secure;
55
break;
24
bool highmem;
56
case 0x1c8:
25
+ bool its;
57
- if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
26
bool virt;
58
- memory_region_del_subregion(get_system_memory(), &pcic->isa);
27
int32_t gic_version;
59
- pcic->iobr = val & 0xfffc0001;
28
struct arm_boot_info bootinfo;
60
- memory_region_add_subregion(get_system_memory(),
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
61
- pcic->iobr & 0xfffc0000, &pcic->isa);
30
index XXXXXXX..XXXXXXX 100644
62
- }
31
--- a/hw/arm/virt.c
63
+ pcic->iobr = val & 0xfffc0001;
32
+++ b/hw/arm/virt.c
64
+ memory_region_set_alias_offset(&pcic->isa, val & 0xfffc0000);
33
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
65
break;
34
static void create_gic(VirtMachineState *vms, qemu_irq *pic)
66
case 0x220:
35
{
67
pci_data_write(phb->bus, pcic->par, val, 4);
36
/* We create a standalone GIC */
68
@@ -XXX,XX +XXX,XX @@ static void sh_pci_device_realize(DeviceState *dev, Error **errp)
37
- VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
69
get_system_io(), 0, 0x40000);
38
DeviceState *gicdev;
70
sysbus_init_mmio(sbd, &s->memconfig_p4);
39
SysBusDevice *gicbusdev;
71
sysbus_init_mmio(sbd, &s->memconfig_a7);
40
const char *gictype;
72
- s->iobr = 0xfe240000;
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
73
- memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
42
74
+ memory_region_add_subregion(get_system_memory(), 0xfe240000, &s->isa);
43
fdt_add_gic_node(vms);
75
44
76
s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host");
45
- if (type == 3 && !vmc->no_its) {
46
+ if (type == 3 && vms->its) {
47
create_its(vms, gicdev);
48
} else if (type == 2) {
49
create_v2m(vms, pic);
50
@@ -XXX,XX +XXX,XX @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
51
vms->highmem = value;
52
}
53
54
+static bool virt_get_its(Object *obj, Error **errp)
55
+{
56
+ VirtMachineState *vms = VIRT_MACHINE(obj);
57
+
58
+ return vms->its;
59
+}
60
+
61
+static void virt_set_its(Object *obj, bool value, Error **errp)
62
+{
63
+ VirtMachineState *vms = VIRT_MACHINE(obj);
64
+
65
+ vms->its = value;
66
+}
67
+
68
static char *virt_get_gic_version(Object *obj, Error **errp)
69
{
70
VirtMachineState *vms = VIRT_MACHINE(obj);
71
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
72
static void virt_2_9_instance_init(Object *obj)
73
{
74
VirtMachineState *vms = VIRT_MACHINE(obj);
75
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
76
77
/* EL3 is disabled by default on virt: this makes us consistent
78
* between KVM and TCG for this board, and it also allows us to
79
@@ -XXX,XX +XXX,XX @@ static void virt_2_9_instance_init(Object *obj)
80
"Set GIC version. "
81
"Valid values are 2, 3 and host", NULL);
82
83
+ if (vmc->no_its) {
84
+ vms->its = false;
85
+ } else {
86
+ /* Default allows ITS instantiation */
87
+ vms->its = true;
88
+ object_property_add_bool(obj, "its", virt_get_its,
89
+ virt_set_its, NULL);
90
+ object_property_set_description(obj, "its",
91
+ "Set on/off to enable/disable "
92
+ "ITS instantiation",
93
+ NULL);
94
+ }
95
+
96
vms->memmap = a15memmap;
97
vms->irqmap = a15irqmap;
98
}
77
}
99
--
78
--
100
2.7.4
79
2.20.1
101
80
102
81
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
The old name, isar_feature_aa32_fp_d32, does not reflect
4
the MVFR0 field name, SIMDReg.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20200214181547.21408-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
[PMM: wrapped one long line]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.h | 2 +-
14
target/arm/translate-vfp.inc.c | 53 +++++++++++++++++-----------------
15
2 files changed, 28 insertions(+), 27 deletions(-)
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
22
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
23
}
24
25
-static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id)
26
+static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
27
{
28
/* Return true if D16-D31 are implemented */
29
return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2;
30
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-vfp.inc.c
33
+++ b/target/arm/translate-vfp.inc.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
35
}
36
37
/* UNDEF accesses to D16-D31 if they don't exist */
38
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
39
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
40
((a->vm | a->vn | a->vd) & 0x10)) {
41
return false;
42
}
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
44
}
45
46
/* UNDEF accesses to D16-D31 if they don't exist */
47
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
48
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
49
((a->vm | a->vn | a->vd) & 0x10)) {
50
return false;
51
}
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
53
}
54
55
/* UNDEF accesses to D16-D31 if they don't exist */
56
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
57
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
58
((a->vm | a->vd) & 0x10)) {
59
return false;
60
}
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
62
}
63
64
/* UNDEF accesses to D16-D31 if they don't exist */
65
- if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
66
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
67
return false;
68
}
69
70
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
71
uint32_t offset;
72
73
/* UNDEF accesses to D16-D31 if they don't exist */
74
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
75
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
76
return false;
77
}
78
79
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
80
uint32_t offset;
81
82
/* UNDEF accesses to D16-D31 if they don't exist */
83
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
84
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
85
return false;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
89
}
90
91
/* UNDEF accesses to D16-D31 if they don't exist */
92
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
93
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
94
return false;
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
98
*/
99
100
/* UNDEF accesses to D16-D31 if they don't exist */
101
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
102
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
103
return false;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
107
TCGv_i64 tmp;
108
109
/* UNDEF accesses to D16-D31 if they don't exist */
110
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
111
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
112
return false;
113
}
114
115
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
116
}
117
118
/* UNDEF accesses to D16-D31 if they don't exist */
119
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd + n) > 16) {
120
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd + n) > 16) {
121
return false;
122
}
123
124
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
125
TCGv_ptr fpst;
126
127
/* UNDEF accesses to D16-D31 if they don't exist */
128
- if (!dc_isar_feature(aa32_fp_d32, s) && ((vd | vn | vm) & 0x10)) {
129
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
130
return false;
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
134
TCGv_i64 f0, fd;
135
136
/* UNDEF accesses to D16-D31 if they don't exist */
137
- if (!dc_isar_feature(aa32_fp_d32, s) && ((vd | vm) & 0x10)) {
138
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
139
return false;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
143
}
144
145
/* UNDEF accesses to D16-D31 if they don't exist. */
146
- if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vn | a->vm) & 0x10)) {
147
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
148
+ ((a->vd | a->vn | a->vm) & 0x10)) {
149
return false;
150
}
151
152
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
153
vd = a->vd;
154
155
/* UNDEF accesses to D16-D31 if they don't exist. */
156
- if (!dc_isar_feature(aa32_fp_d32, s) && (vd & 0x10)) {
157
+ if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
158
return false;
159
}
160
161
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
162
}
163
164
/* UNDEF accesses to D16-D31 if they don't exist. */
165
- if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
166
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
167
return false;
168
}
169
170
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
171
}
172
173
/* UNDEF accesses to D16-D31 if they don't exist. */
174
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
175
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
176
return false;
177
}
178
179
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
180
}
181
182
/* UNDEF accesses to D16-D31 if they don't exist. */
183
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
184
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
185
return false;
186
}
187
188
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
189
}
190
191
/* UNDEF accesses to D16-D31 if they don't exist. */
192
- if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
193
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
194
return false;
195
}
196
197
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
198
}
199
200
/* UNDEF accesses to D16-D31 if they don't exist. */
201
- if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
202
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
203
return false;
204
}
205
206
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
207
}
208
209
/* UNDEF accesses to D16-D31 if they don't exist. */
210
- if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
211
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
212
return false;
213
}
214
215
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
216
TCGv_i32 vm;
217
218
/* UNDEF accesses to D16-D31 if they don't exist. */
219
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
220
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
221
return false;
222
}
223
224
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
225
TCGv_i32 vd;
226
227
/* UNDEF accesses to D16-D31 if they don't exist. */
228
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
229
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
230
return false;
231
}
232
233
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
234
TCGv_ptr fpst;
235
236
/* UNDEF accesses to D16-D31 if they don't exist. */
237
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
238
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
239
return false;
240
}
241
242
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
243
}
244
245
/* UNDEF accesses to D16-D31 if they don't exist. */
246
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
247
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
248
return false;
249
}
250
251
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
252
}
253
254
/* UNDEF accesses to D16-D31 if they don't exist. */
255
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
256
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
257
return false;
258
}
259
260
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
261
TCGv_ptr fpst;
262
263
/* UNDEF accesses to D16-D31 if they don't exist. */
264
- if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
265
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
266
return false;
267
}
268
269
--
270
2.20.1
271
272
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Many uses of ARM_FEATURE_VFP3 are testing for the number of simd
4
registers implemented. Use the proper test vs MVFR0.SIMDReg.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200214181547.21408-4-richard.henderson@linaro.org
8
[PMM: fix typo in commit message]
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.c | 9 ++++-----
13
target/arm/helper.c | 13 ++++++-------
14
target/arm/translate.c | 2 +-
15
3 files changed, 11 insertions(+), 13 deletions(-)
16
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.c
20
+++ b/target/arm/cpu.c
21
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
22
23
if (flags & CPU_DUMP_FPU) {
24
int numvfpregs = 0;
25
- if (arm_feature(env, ARM_FEATURE_VFP)) {
26
- numvfpregs += 16;
27
- }
28
- if (arm_feature(env, ARM_FEATURE_VFP3)) {
29
- numvfpregs += 16;
30
+ if (cpu_isar_feature(aa32_simd_r32, cpu)) {
31
+ numvfpregs = 32;
32
+ } else if (arm_feature(env, ARM_FEATURE_VFP)) {
33
+ numvfpregs = 16;
34
}
35
for (i = 0; i < numvfpregs; i++) {
36
uint64_t v = *aa32_vfp_dreg(env, i);
37
diff --git a/target/arm/helper.c b/target/arm/helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/helper.c
40
+++ b/target/arm/helper.c
41
@@ -XXX,XX +XXX,XX @@ static void switch_mode(CPUARMState *env, int mode);
42
43
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
44
{
45
- int nregs;
46
+ ARMCPU *cpu = env_archcpu(env);
47
+ int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
48
49
/* VFP data registers are always little-endian. */
50
- nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
51
if (reg < nregs) {
52
stq_le_p(buf, *aa32_vfp_dreg(env, reg));
53
return 8;
54
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
55
56
static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
57
{
58
- int nregs;
59
+ ARMCPU *cpu = env_archcpu(env);
60
+ int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
61
62
- nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
63
if (reg < nregs) {
64
*aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
65
return 8;
66
@@ -XXX,XX +XXX,XX @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
/* VFPv3 and upwards with NEON implement 32 double precision
68
* registers (D0-D31).
69
*/
70
- if (!arm_feature(env, ARM_FEATURE_NEON) ||
71
- !arm_feature(env, ARM_FEATURE_VFP3)) {
72
+ if (!cpu_isar_feature(aa32_simd_r32, env_archcpu(env))) {
73
/* D32DIS [30] is RAO/WI if D16-31 are not implemented. */
74
value |= (1 << 30);
75
}
76
@@ -XXX,XX +XXX,XX @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
77
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
78
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
79
51, "arm-neon.xml", 0);
80
- } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
81
+ } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
82
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
83
35, "arm-vfp3.xml", 0);
84
} else if (arm_feature(env, ARM_FEATURE_VFP)) {
85
diff --git a/target/arm/translate.c b/target/arm/translate.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate.c
88
+++ b/target/arm/translate.c
89
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
90
#define VFP_SREG(insn, bigbit, smallbit) \
91
((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
92
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
93
- if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
94
+ if (dc_isar_feature(aa32_simd_r32, s)) { \
95
reg = (((insn) >> (bigbit)) & 0x0f) \
96
| (((insn) >> ((smallbit) - 4)) & 0x10); \
97
} else { \
98
--
99
2.20.1
100
101
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
We are going to convert FEATURE tests to ISAR tests,
4
so FPSP needs to be set for these cpus, like we have
5
already for FPDP.
4
6
5
For supporting the SD controller selection (alternate function of GPIOs
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
48-53), the bcm2835_gpio now exposes an sdbus.
8
Message-id: 20200214181547.21408-5-richard.henderson@linaro.org
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
8
and the card is reparented from one bus to another when the alternate
9
function of GPIOs 48-53 is modified.
10
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
12
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
include/hw/arm/bcm2835_peripherals.h | 4 ++++
12
target/arm/cpu.c | 10 ++++++----
17
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
13
1 file changed, 6 insertions(+), 4 deletions(-)
18
2 files changed, 45 insertions(+), 2 deletions(-)
19
14
20
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/bcm2835_peripherals.h
17
--- a/target/arm/cpu.c
23
+++ b/include/hw/arm/bcm2835_peripherals.h
18
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj)
25
#include "hw/misc/bcm2835_rng.h"
20
*/
26
#include "hw/misc/bcm2835_mbox.h"
21
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
27
#include "hw/sd/sdhci.h"
22
/*
28
+#include "hw/sd/bcm2835_sdhost.h"
23
- * Similarly, we need to set MVFR0 fields to enable double precision
29
+#include "hw/gpio/bcm2835_gpio.h"
24
- * and short vector support even though ARMv5 doesn't have this register.
30
25
+ * Similarly, we need to set MVFR0 fields to enable vfp and short vector
31
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
26
+ * support even though ARMv5 doesn't have this register.
32
#define BCM2835_PERIPHERALS(obj) \
27
*/
33
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
28
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
34
BCM2835RngState rng;
29
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
35
BCM2835MboxState mboxes;
30
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
36
SDHCIState sdhci;
37
+ BCM2835SDHostState sdhost;
38
+ BCM2835GpioState gpio;
39
} BCM2835PeripheralState;
40
41
#endif /* BCM2835_PERIPHERALS_H */
42
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/bcm2835_peripherals.c
45
+++ b/hw/arm/bcm2835_peripherals.c
46
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
47
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
48
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
49
50
+ /* SDHOST */
51
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
52
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
53
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
54
+
55
/* DMA Channels */
56
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
57
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
58
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
59
60
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
61
OBJECT(&s->gpu_bus_mr), &error_abort);
62
+
63
+ /* GPIO */
64
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
65
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
66
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
67
+
68
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
69
+ OBJECT(&s->sdhci.sdbus), &error_abort);
70
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
71
+ OBJECT(&s->sdhost.sdbus), &error_abort);
72
}
31
}
73
32
74
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
33
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
75
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
34
*/
76
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
35
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
77
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
/*
78
INTERRUPT_ARASANSDIO));
37
- * Similarly, we need to set MVFR0 fields to enable double precision
79
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
38
- * and short vector support even though ARMv5 doesn't have this register.
80
- &err);
39
+ * Similarly, we need to set MVFR0 fields to enable vfp and short vector
81
+
40
+ * support even though ARMv5 doesn't have this register.
82
+ /* SDHOST */
41
*/
83
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
42
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
84
if (err) {
43
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
85
error_propagate(errp, err);
44
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
86
return;
45
87
}
46
{
88
89
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
90
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
91
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
92
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
93
+ INTERRUPT_SDIO));
94
+
95
/* DMA Channels */
96
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
97
if (err) {
98
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
99
BCM2835_IC_GPU_IRQ,
100
INTERRUPT_DMA0 + n));
101
}
102
+
103
+ /* GPIO */
104
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
105
+ if (err) {
106
+ error_propagate(errp, err);
107
+ return;
108
+ }
109
+
110
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
111
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
112
+
113
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
114
+ &err);
115
+ if (err) {
116
+ error_propagate(errp, err);
117
+ return;
118
+ }
119
}
120
121
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
122
--
47
--
123
2.7.4
48
2.20.1
124
49
125
50
diff view generated by jsdifflib
1
From: Michael Davidsaver <mdavidsaver@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The v7M exception architecture requires that if a synchronous
3
Use this in the places that were checking ARM_FEATURE_VFP, and
4
exception cannot be taken immediately (because it is disabled
4
are obviously testing for the existance of the register set
5
or at too low a priority) then it should be escalated to
5
as opposed to testing for some particular instruction extension.
6
HardFault (and the HardFault exception is then taken).
6
7
Implement this escalation logic.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
8
Message-id: 20200214181547.21408-6-richard.henderson@linaro.org
9
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
[PMM: extracted from another patch]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
---
11
---
14
hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
12
target/arm/cpu.h | 6 ++++++
15
target/arm/helper.c | 2 --
13
hw/intc/armv7m_nvic.c | 20 ++++++++++----------
16
2 files changed, 53 insertions(+), 2 deletions(-)
14
linux-user/arm/signal.c | 4 ++--
17
15
target/arm/arch_dump.c | 11 ++++++-----
16
target/arm/cpu.c | 8 ++++----
17
target/arm/helper.c | 4 ++--
18
target/arm/m_helper.c | 11 ++++++-----
19
target/arm/machine.c | 3 +--
20
8 files changed, 37 insertions(+), 30 deletions(-)
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 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
27
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
28
}
29
30
+static inline bool isar_feature_aa32_simd_r16(const ARMISARegisters *id)
31
+{
32
+ /* Return true if D0-D15 are implemented */
33
+ return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
34
+}
35
+
36
static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
37
{
38
/* Return true if D16-D31 are implemented */
18
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/intc/armv7m_nvic.c
41
--- a/hw/intc/armv7m_nvic.c
21
+++ b/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq)
43
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
23
44
case 0xd84: /* CSSELR */
24
vec = &s->vectors[irq];
45
return cpu->env.v7m.csselr[attrs.secure];
25
trace_nvic_set_pending(irq, vec->enabled, vec->prio);
46
case 0xd88: /* CPACR */
26
+
47
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
27
+
48
+ if (!cpu_isar_feature(aa32_simd_r16, cpu)) {
28
+ if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
49
return 0;
29
+ /* If a synchronous exception is pending then it may be
50
}
30
+ * escalated to HardFault if:
51
return cpu->env.v7m.cpacr[attrs.secure];
31
+ * * it is equal or lower priority to current execution
52
case 0xd8c: /* NSACR */
32
+ * * it is disabled
53
- if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
33
+ * (ie we need to take it immediately but we can't do so).
54
+ if (!attrs.secure || !cpu_isar_feature(aa32_simd_r16, cpu)) {
34
+ * Asynchronous exceptions (and interrupts) simply remain pending.
55
return 0;
35
+ *
56
}
36
+ * For QEMU, we don't have any imprecise (asynchronous) faults,
57
return cpu->env.v7m.nsacr;
37
+ * so we can assume that PREFETCH_ABORT and DATA_ABORT are always
58
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
38
+ * synchronous.
59
}
39
+ * Debug exceptions are awkward because only Debug exceptions
60
return cpu->env.v7m.sfar;
40
+ * resulting from the BKPT instruction should be escalated,
61
case 0xf34: /* FPCCR */
41
+ * but we don't currently implement any Debug exceptions other
62
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
42
+ * than those that result from BKPT, so we treat all debug exceptions
63
+ if (!cpu_isar_feature(aa32_simd_r16, cpu)) {
43
+ * as needing escalation.
64
return 0;
44
+ *
65
}
45
+ * This all means we can identify whether to escalate based only on
66
if (attrs.secure) {
46
+ * the exception number and don't (yet) need the caller to explicitly
67
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
47
+ * tell us whether this exception is synchronous or not.
68
return value;
48
+ */
69
}
49
+ int running = nvic_exec_prio(s);
70
case 0xf38: /* FPCAR */
50
+ bool escalate = false;
71
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
51
+
72
+ if (!cpu_isar_feature(aa32_simd_r16, cpu)) {
52
+ if (vec->prio >= running) {
73
return 0;
53
+ trace_nvic_escalate_prio(irq, vec->prio, running);
74
}
54
+ escalate = true;
75
return cpu->env.v7m.fpcar[attrs.secure];
55
+ } else if (!vec->enabled) {
76
case 0xf3c: /* FPDSCR */
56
+ trace_nvic_escalate_disabled(irq);
77
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
57
+ escalate = true;
78
+ if (!cpu_isar_feature(aa32_simd_r16, cpu)) {
58
+ }
79
return 0;
59
+
80
}
60
+ if (escalate) {
81
return cpu->env.v7m.fpdscr[attrs.secure];
61
+ if (running < 0) {
82
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
62
+ /* We want to escalate to HardFault but we can't take a
83
}
63
+ * synchronous HardFault at this point either. This is a
84
break;
64
+ * Lockup condition due to a guest bug. We don't model
85
case 0xd88: /* CPACR */
65
+ * Lockup, so report via cpu_abort() instead.
86
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
66
+ */
87
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
67
+ cpu_abort(&s->cpu->parent_obj,
88
/* We implement only the Floating Point extension's CP10/CP11 */
68
+ "Lockup: can't escalate %d to HardFault "
89
cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
69
+ "(current priority %d)\n", irq, running);
90
}
70
+ }
91
break;
71
+
92
case 0xd8c: /* NSACR */
72
+ /* We can do the escalation, so we take HardFault instead */
93
- if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
73
+ irq = ARMV7M_EXCP_HARD;
94
+ if (attrs.secure && cpu_isar_feature(aa32_simd_r16, cpu)) {
74
+ vec = &s->vectors[irq];
95
/* We implement only the Floating Point extension's CP10/CP11 */
75
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
96
cpu->env.v7m.nsacr = value & (3 << 10);
76
+ }
97
}
77
+ }
98
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
78
+
99
break;
79
if (!vec->pending) {
100
}
80
vec->pending = 1;
101
case 0xf34: /* FPCCR */
81
nvic_irq_update(s);
102
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
103
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
104
/* Not all bits here are banked. */
105
uint32_t fpccr_s;
106
107
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
108
}
109
break;
110
case 0xf38: /* FPCAR */
111
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
112
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
113
value &= ~7;
114
cpu->env.v7m.fpcar[attrs.secure] = value;
115
}
116
break;
117
case 0xf3c: /* FPDSCR */
118
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
119
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
120
value &= 0x07c00000;
121
cpu->env.v7m.fpdscr[attrs.secure] = value;
122
}
123
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/linux-user/arm/signal.c
126
+++ b/linux-user/arm/signal.c
127
@@ -XXX,XX +XXX,XX @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
128
setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
129
/* Save coprocessor signal frame. */
130
regspace = uc->tuc_regspace;
131
- if (arm_feature(env, ARM_FEATURE_VFP)) {
132
+ if (cpu_isar_feature(aa32_simd_r16, env_archcpu(env))) {
133
regspace = setup_sigframe_v2_vfp(regspace, env);
134
}
135
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
136
@@ -XXX,XX +XXX,XX @@ static int do_sigframe_return_v2(CPUARMState *env,
137
138
/* Restore coprocessor signal frame */
139
regspace = uc->tuc_regspace;
140
- if (arm_feature(env, ARM_FEATURE_VFP)) {
141
+ if (cpu_isar_feature(aa32_simd_r16, env_archcpu(env))) {
142
regspace = restore_sigframe_v2_vfp(env, regspace);
143
if (!regspace) {
144
return 1;
145
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/arch_dump.c
148
+++ b/target/arm/arch_dump.c
149
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
150
int cpuid, void *opaque)
151
{
152
struct arm_note note;
153
- CPUARMState *env = &ARM_CPU(cs)->env;
154
+ ARMCPU *cpu = ARM_CPU(cs);
155
+ CPUARMState *env = &cpu->env;
156
DumpState *s = opaque;
157
- int ret, i, fpvalid = !!arm_feature(env, ARM_FEATURE_VFP);
158
+ int ret, i;
159
+ bool fpvalid = cpu_isar_feature(aa32_simd_r16, cpu);
160
161
arm_note_init(&note, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
162
163
@@ -XXX,XX +XXX,XX @@ int cpu_get_dump_info(ArchDumpInfo *info,
164
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
165
{
166
ARMCPU *cpu = ARM_CPU(first_cpu);
167
- CPUARMState *env = &cpu->env;
168
size_t note_size;
169
170
if (class == ELFCLASS64) {
171
@@ -XXX,XX +XXX,XX @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
172
note_size += AARCH64_PRFPREG_NOTE_SIZE;
173
#ifdef TARGET_AARCH64
174
if (cpu_isar_feature(aa64_sve, cpu)) {
175
- note_size += AARCH64_SVE_NOTE_SIZE(env);
176
+ note_size += AARCH64_SVE_NOTE_SIZE(&cpu->env);
177
}
178
#endif
179
} else {
180
note_size = ARM_PRSTATUS_NOTE_SIZE;
181
- if (arm_feature(env, ARM_FEATURE_VFP)) {
182
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
183
note_size += ARM_VFP_NOTE_SIZE;
184
}
185
}
186
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/arm/cpu.c
189
+++ b/target/arm/cpu.c
190
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
191
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
192
}
193
194
- if (arm_feature(env, ARM_FEATURE_VFP)) {
195
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
196
env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
197
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
198
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
199
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
200
int numvfpregs = 0;
201
if (cpu_isar_feature(aa32_simd_r32, cpu)) {
202
numvfpregs = 32;
203
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
204
+ } else if (cpu_isar_feature(aa32_simd_r16, cpu)) {
205
numvfpregs = 16;
206
}
207
for (i = 0; i < numvfpregs; i++) {
208
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
209
* KVM does not currently allow us to lie to the guest about its
210
* ID/feature registers, so the guest always sees what the host has.
211
*/
212
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
213
+ if (cpu_isar_feature(aa32_simd_r16, cpu)) {
214
cpu->has_vfp = true;
215
if (!kvm_enabled()) {
216
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_vfp_property);
217
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
218
* We rely on no XScale CPU having VFP so we can use the same bits in the
219
* TB flags field for VECSTRIDE and XSCALE_CPAR.
220
*/
221
- assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
222
+ assert(!(cpu_isar_feature(aa32_simd_r16, cpu) &&
223
arm_feature(env, ARM_FEATURE_XSCALE)));
224
225
if (arm_feature(env, ARM_FEATURE_V7) &&
82
diff --git a/target/arm/helper.c b/target/arm/helper.c
226
diff --git a/target/arm/helper.c b/target/arm/helper.c
83
index XXXXXXX..XXXXXXX 100644
227
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/helper.c
228
--- a/target/arm/helper.c
85
+++ b/target/arm/helper.c
229
+++ b/target/arm/helper.c
86
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
230
@@ -XXX,XX +XXX,XX @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
87
231
* ASEDIS [31] and D32DIS [30] are both UNK/SBZP without VFP.
88
/* For exceptions we just mark as pending on the NVIC, and let that
232
* TRCDIS [28] is RAZ/WI since we do not implement a trace macrocell.
89
handle it. */
233
*/
90
- /* TODO: Need to escalate if the current priority is higher than the
234
- if (arm_feature(env, ARM_FEATURE_VFP)) {
91
- one we're raising. */
235
+ if (cpu_isar_feature(aa32_simd_r16, env_archcpu(env))) {
92
switch (cs->exception_index) {
236
/* VFP coprocessor: cp10 & cp11 [23:20] */
93
case EXCP_UDEF:
237
mask |= (1 << 31) | (1 << 30) | (0xf << 20);
94
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
238
239
@@ -XXX,XX +XXX,XX @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
240
} else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
241
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
242
35, "arm-vfp3.xml", 0);
243
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
244
+ } else if (cpu_isar_feature(aa32_simd_r16, cpu)) {
245
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
246
19, "arm-vfp.xml", 0);
247
}
248
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
249
index XXXXXXX..XXXXXXX 100644
250
--- a/target/arm/m_helper.c
251
+++ b/target/arm/m_helper.c
252
@@ -XXX,XX +XXX,XX @@ static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
253
*/
254
uint32_t sig = 0xfefa125a;
255
256
- if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
257
+ if (!cpu_isar_feature(aa32_simd_r16, env_archcpu(env))
258
+ || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
259
sig |= 1;
260
}
261
return sig;
262
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
263
264
if (dotailchain) {
265
/* Sanitize LR FType and PREFIX bits */
266
- if (!arm_feature(env, ARM_FEATURE_VFP)) {
267
+ if (!cpu_isar_feature(aa32_simd_r16, cpu)) {
268
lr |= R_V7M_EXCRET_FTYPE_MASK;
269
}
270
lr = deposit32(lr, 24, 8, 0xff);
271
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
272
273
ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
274
275
- if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
276
+ if (!ftype && !cpu_isar_feature(aa32_simd_r16, cpu)) {
277
qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
278
"exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
279
"if FPU not present\n",
280
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
281
* SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
282
* RES0 if the FPU is not present, and is stored in the S bank
283
*/
284
- if (arm_feature(env, ARM_FEATURE_VFP) &&
285
+ if (cpu_isar_feature(aa32_simd_r16, env_archcpu(env)) &&
286
extract32(env->v7m.nsacr, 10, 1)) {
287
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
288
env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
289
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
290
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
291
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
292
}
293
- if (arm_feature(env, ARM_FEATURE_VFP)) {
294
+ if (cpu_isar_feature(aa32_simd_r16, env_archcpu(env))) {
295
/*
296
* SFPA is RAZ/WI from NS or if no FPU.
297
* FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
298
diff --git a/target/arm/machine.c b/target/arm/machine.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/target/arm/machine.c
301
+++ b/target/arm/machine.c
302
@@ -XXX,XX +XXX,XX @@
303
static bool vfp_needed(void *opaque)
304
{
305
ARMCPU *cpu = opaque;
306
- CPUARMState *env = &cpu->env;
307
308
- return arm_feature(env, ARM_FEATURE_VFP);
309
+ return cpu_isar_feature(aa32_simd_r16, cpu);
310
}
311
312
static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
95
--
313
--
96
2.7.4
314
2.20.1
97
315
98
316
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
The old name, isar_feature_aa32_fpdp, does not reflect
4
that the test includes VFPv2. We will introduce further
5
feature tests for VFPv3.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20200214181547.21408-7-richard.henderson@linaro.org
10
[PMM: fixed grammar in commit message]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.h | 4 ++--
15
target/arm/translate-vfp.inc.c | 40 +++++++++++++++++-----------------
16
2 files changed, 22 insertions(+), 22 deletions(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
23
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
24
}
25
26
-static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
27
+static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
28
{
29
- /* Return true if CPU supports double precision floating point */
30
+ /* Return true if CPU supports double precision floating point, VFPv2 */
31
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
32
}
33
34
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-vfp.inc.c
37
+++ b/target/arm/translate-vfp.inc.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
39
return false;
40
}
41
42
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
43
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
44
return false;
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
48
return false;
49
}
50
51
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
52
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
53
return false;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
57
return false;
58
}
59
60
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
61
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
62
return false;
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
66
return false;
67
}
68
69
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
70
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
71
return false;
72
}
73
74
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
75
return false;
76
}
77
78
- if (!dc_isar_feature(aa32_fpdp, s)) {
79
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
80
return false;
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
84
return false;
85
}
86
87
- if (!dc_isar_feature(aa32_fpdp, s)) {
88
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
89
return false;
90
}
91
92
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
93
return false;
94
}
95
96
- if (!dc_isar_feature(aa32_fpdp, s)) {
97
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
98
return false;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
102
return false;
103
}
104
105
- if (!dc_isar_feature(aa32_fpdp, s)) {
106
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
107
return false;
108
}
109
110
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
111
return false;
112
}
113
114
- if (!dc_isar_feature(aa32_fpdp, s)) {
115
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
116
return false;
117
}
118
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
120
return false;
121
}
122
123
- if (!dc_isar_feature(aa32_fpdp, s)) {
124
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
125
return false;
126
}
127
128
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
129
return false;
130
}
131
132
- if (!dc_isar_feature(aa32_fpdp, s)) {
133
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
134
return false;
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
138
return false;
139
}
140
141
- if (!dc_isar_feature(aa32_fpdp, s)) {
142
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
143
return false;
144
}
145
146
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
147
return false;
148
}
149
150
- if (!dc_isar_feature(aa32_fpdp, s)) {
151
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
152
return false;
153
}
154
155
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
156
return false;
157
}
158
159
- if (!dc_isar_feature(aa32_fpdp, s)) {
160
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
161
return false;
162
}
163
164
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
165
return false;
166
}
167
168
- if (!dc_isar_feature(aa32_fpdp, s)) {
169
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
170
return false;
171
}
172
173
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
174
return false;
175
}
176
177
- if (!dc_isar_feature(aa32_fpdp, s)) {
178
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
179
return false;
180
}
181
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
183
return false;
184
}
185
186
- if (!dc_isar_feature(aa32_fpdp, s)) {
187
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
188
return false;
189
}
190
191
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
192
return false;
193
}
194
195
- if (!dc_isar_feature(aa32_fpdp, s)) {
196
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
197
return false;
198
}
199
200
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
201
return false;
202
}
203
204
- if (!dc_isar_feature(aa32_fpdp, s)) {
205
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
206
return false;
207
}
208
209
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
210
return false;
211
}
212
213
- if (!dc_isar_feature(aa32_fpdp, s)) {
214
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
215
return false;
216
}
217
218
--
219
2.20.1
220
221
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds the BCM2835 SDHost controller from Arasan.
3
We will shortly use these to test for VFPv2 and VFPv3
4
in different situations.
4
5
5
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr
7
Message-id: 20200214181547.21408-8-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
hw/sd/Makefile.objs | 1 +
11
target/arm/cpu.h | 18 ++++++++++++++++++
11
include/hw/sd/bcm2835_sdhost.h | 48 +++++
12
1 file changed, 18 insertions(+)
12
hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++++++
13
3 files changed, 478 insertions(+)
14
create mode 100644 include/hw/sd/bcm2835_sdhost.h
15
create mode 100644 hw/sd/bcm2835_sdhost.c
16
13
17
diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/sd/Makefile.objs
16
--- a/target/arm/cpu.h
20
+++ b/hw/sd/Makefile.objs
17
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SDHCI) += sdhci.o
18
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
22
obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
19
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
23
obj-$(CONFIG_OMAP) += omap_mmc.o
20
}
24
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
21
25
+obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
22
+static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
26
diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h
27
new file mode 100644
28
index XXXXXXX..XXXXXXX
29
--- /dev/null
30
+++ b/include/hw/sd/bcm2835_sdhost.h
31
@@ -XXX,XX +XXX,XX @@
32
+/*
33
+ * Raspberry Pi (BCM2835) SD Host Controller
34
+ *
35
+ * Copyright (c) 2017 Antfield SAS
36
+ *
37
+ * Authors:
38
+ * Clement Deschamps <clement.deschamps@antfield.fr>
39
+ * Luc Michel <luc.michel@antfield.fr>
40
+ *
41
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
42
+ * See the COPYING file in the top-level directory.
43
+ */
44
+
45
+#ifndef BCM2835_SDHOST_H
46
+#define BCM2835_SDHOST_H
47
+
48
+#include "hw/sysbus.h"
49
+#include "hw/sd/sd.h"
50
+
51
+#define TYPE_BCM2835_SDHOST "bcm2835-sdhost"
52
+#define BCM2835_SDHOST(obj) \
53
+ OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST)
54
+
55
+#define BCM2835_SDHOST_FIFO_LEN 16
56
+
57
+typedef struct {
58
+ SysBusDevice busdev;
59
+ SDBus sdbus;
60
+ MemoryRegion iomem;
61
+
62
+ uint32_t cmd;
63
+ uint32_t cmdarg;
64
+ uint32_t status;
65
+ uint32_t rsp[4];
66
+ uint32_t config;
67
+ uint32_t edm;
68
+ uint32_t vdd;
69
+ uint32_t hbct;
70
+ uint32_t hblc;
71
+ int32_t fifo_pos;
72
+ int32_t fifo_len;
73
+ uint32_t fifo[BCM2835_SDHOST_FIFO_LEN];
74
+ uint32_t datacnt;
75
+
76
+ qemu_irq irq;
77
+} BCM2835SDHostState;
78
+
79
+#endif
80
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/hw/sd/bcm2835_sdhost.c
85
@@ -XXX,XX +XXX,XX @@
86
+/*
87
+ * Raspberry Pi (BCM2835) SD Host Controller
88
+ *
89
+ * Copyright (c) 2017 Antfield SAS
90
+ *
91
+ * Authors:
92
+ * Clement Deschamps <clement.deschamps@antfield.fr>
93
+ * Luc Michel <luc.michel@antfield.fr>
94
+ *
95
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
96
+ * See the COPYING file in the top-level directory.
97
+ */
98
+
99
+#include "qemu/osdep.h"
100
+#include "qemu/log.h"
101
+#include "sysemu/blockdev.h"
102
+#include "hw/sd/bcm2835_sdhost.h"
103
+
104
+#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus"
105
+#define BCM2835_SDHOST_BUS(obj) \
106
+ OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS)
107
+
108
+#define SDCMD 0x00 /* Command to SD card - 16 R/W */
109
+#define SDARG 0x04 /* Argument to SD card - 32 R/W */
110
+#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
111
+#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
112
+#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */
113
+#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */
114
+#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */
115
+#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */
116
+#define SDHSTS 0x20 /* SD host status - 11 R */
117
+#define SDVDD 0x30 /* SD card power control - 1 R/W */
118
+#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
119
+#define SDHCFG 0x38 /* Host configuration - 2 R/W */
120
+#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
121
+#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
122
+#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
123
+
124
+#define SDCMD_NEW_FLAG 0x8000
125
+#define SDCMD_FAIL_FLAG 0x4000
126
+#define SDCMD_BUSYWAIT 0x800
127
+#define SDCMD_NO_RESPONSE 0x400
128
+#define SDCMD_LONG_RESPONSE 0x200
129
+#define SDCMD_WRITE_CMD 0x80
130
+#define SDCMD_READ_CMD 0x40
131
+#define SDCMD_CMD_MASK 0x3f
132
+
133
+#define SDCDIV_MAX_CDIV 0x7ff
134
+
135
+#define SDHSTS_BUSY_IRPT 0x400
136
+#define SDHSTS_BLOCK_IRPT 0x200
137
+#define SDHSTS_SDIO_IRPT 0x100
138
+#define SDHSTS_REW_TIME_OUT 0x80
139
+#define SDHSTS_CMD_TIME_OUT 0x40
140
+#define SDHSTS_CRC16_ERROR 0x20
141
+#define SDHSTS_CRC7_ERROR 0x10
142
+#define SDHSTS_FIFO_ERROR 0x08
143
+/* Reserved */
144
+/* Reserved */
145
+#define SDHSTS_DATA_FLAG 0x01
146
+
147
+#define SDHCFG_BUSY_IRPT_EN (1 << 10)
148
+#define SDHCFG_BLOCK_IRPT_EN (1 << 8)
149
+#define SDHCFG_SDIO_IRPT_EN (1 << 5)
150
+#define SDHCFG_DATA_IRPT_EN (1 << 4)
151
+#define SDHCFG_SLOW_CARD (1 << 3)
152
+#define SDHCFG_WIDE_EXT_BUS (1 << 2)
153
+#define SDHCFG_WIDE_INT_BUS (1 << 1)
154
+#define SDHCFG_REL_CMD_LINE (1 << 0)
155
+
156
+#define SDEDM_FORCE_DATA_MODE (1 << 19)
157
+#define SDEDM_CLOCK_PULSE (1 << 20)
158
+#define SDEDM_BYPASS (1 << 21)
159
+
160
+#define SDEDM_WRITE_THRESHOLD_SHIFT 9
161
+#define SDEDM_READ_THRESHOLD_SHIFT 14
162
+#define SDEDM_THRESHOLD_MASK 0x1f
163
+
164
+#define SDEDM_FSM_MASK 0xf
165
+#define SDEDM_FSM_IDENTMODE 0x0
166
+#define SDEDM_FSM_DATAMODE 0x1
167
+#define SDEDM_FSM_READDATA 0x2
168
+#define SDEDM_FSM_WRITEDATA 0x3
169
+#define SDEDM_FSM_READWAIT 0x4
170
+#define SDEDM_FSM_READCRC 0x5
171
+#define SDEDM_FSM_WRITECRC 0x6
172
+#define SDEDM_FSM_WRITEWAIT1 0x7
173
+#define SDEDM_FSM_POWERDOWN 0x8
174
+#define SDEDM_FSM_POWERUP 0x9
175
+#define SDEDM_FSM_WRITESTART1 0xa
176
+#define SDEDM_FSM_WRITESTART2 0xb
177
+#define SDEDM_FSM_GENPULSES 0xc
178
+#define SDEDM_FSM_WRITEWAIT2 0xd
179
+#define SDEDM_FSM_STARTPOWDOWN 0xf
180
+
181
+#define SDDATA_FIFO_WORDS 16
182
+
183
+static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s)
184
+{
23
+{
185
+ uint32_t irq = s->status &
24
+ /* Return true if CPU supports single precision floating point, VFPv2 */
186
+ (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT);
25
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
187
+ qemu_set_irq(s->irq, !!irq);
188
+}
26
+}
189
+
27
+
190
+static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
28
+static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
191
+{
29
+{
192
+ SDRequest request;
30
+ /* Return true if CPU supports single precision floating point, VFPv3 */
193
+ uint8_t rsp[16];
31
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
194
+ int rlen;
195
+
196
+ request.cmd = s->cmd & SDCMD_CMD_MASK;
197
+ request.arg = s->cmdarg;
198
+
199
+ rlen = sdbus_do_command(&s->sdbus, &request, rsp);
200
+ if (rlen < 0) {
201
+ goto error;
202
+ }
203
+ if (!(s->cmd & SDCMD_NO_RESPONSE)) {
204
+#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
205
+ | (rsp[n + 2] << 8) | rsp[n + 3])
206
+ if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
207
+ goto error;
208
+ }
209
+ if (rlen != 4 && rlen != 16) {
210
+ goto error;
211
+ }
212
+ if (rlen == 4) {
213
+ s->rsp[0] = RWORD(0);
214
+ s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
215
+ } else {
216
+ s->rsp[0] = RWORD(12);
217
+ s->rsp[1] = RWORD(8);
218
+ s->rsp[2] = RWORD(4);
219
+ s->rsp[3] = RWORD(0);
220
+ }
221
+#undef RWORD
222
+ }
223
+ return;
224
+
225
+error:
226
+ s->cmd |= SDCMD_FAIL_FLAG;
227
+ s->status |= SDHSTS_CMD_TIME_OUT;
228
+}
32
+}
229
+
33
+
230
+static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value)
34
static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
35
{
36
/* Return true if CPU supports double precision floating point, VFPv2 */
37
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
38
}
39
40
+static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
231
+{
41
+{
232
+ int n;
42
+ /* Return true if CPU supports double precision floating point, VFPv3 */
233
+
43
+ return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
234
+ if (s->fifo_len == BCM2835_SDHOST_FIFO_LEN) {
235
+ /* FIFO overflow */
236
+ return;
237
+ }
238
+ n = (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1);
239
+ s->fifo_len++;
240
+ s->fifo[n] = value;
241
+}
44
+}
242
+
45
+
243
+static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s)
46
/*
244
+{
47
* We always set the FP and SIMD FP16 fields to indicate identical
245
+ uint32_t value;
48
* levels of support (assuming SIMD is implemented at all), so
246
+
247
+ if (s->fifo_len == 0) {
248
+ /* FIFO underflow */
249
+ return 0;
250
+ }
251
+ value = s->fifo[s->fifo_pos];
252
+ s->fifo_len--;
253
+ s->fifo_pos = (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1);
254
+ return value;
255
+}
256
+
257
+static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s)
258
+{
259
+ uint32_t value = 0;
260
+ int n;
261
+ int is_read;
262
+
263
+ is_read = (s->cmd & SDCMD_READ_CMD) != 0;
264
+ if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) {
265
+ if (is_read) {
266
+ n = 0;
267
+ while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) {
268
+ value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
269
+ s->datacnt--;
270
+ n++;
271
+ if (n == 4) {
272
+ bcm2835_sdhost_fifo_push(s, value);
273
+ n = 0;
274
+ value = 0;
275
+ }
276
+ }
277
+ if (n != 0) {
278
+ bcm2835_sdhost_fifo_push(s, value);
279
+ }
280
+ } else { /* write */
281
+ n = 0;
282
+ while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
283
+ if (n == 0) {
284
+ value = bcm2835_sdhost_fifo_pop(s);
285
+ n = 4;
286
+ }
287
+ n--;
288
+ s->datacnt--;
289
+ sdbus_write_data(&s->sdbus, value & 0xff);
290
+ value >>= 8;
291
+ }
292
+ }
293
+ }
294
+ if (s->datacnt == 0) {
295
+ s->status |= SDHSTS_DATA_FLAG;
296
+
297
+ s->edm &= ~0xf;
298
+ s->edm |= SDEDM_FSM_DATAMODE;
299
+
300
+ if (s->config & SDHCFG_DATA_IRPT_EN) {
301
+ s->status |= SDHSTS_SDIO_IRPT;
302
+ }
303
+
304
+ if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)) {
305
+ s->status |= SDHSTS_BUSY_IRPT;
306
+ }
307
+
308
+ if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_EN)) {
309
+ s->status |= SDHSTS_BLOCK_IRPT;
310
+ }
311
+
312
+ bcm2835_sdhost_update_irq(s);
313
+ }
314
+
315
+ s->edm &= ~(0x1f << 4);
316
+ s->edm |= ((s->fifo_len & 0x1f) << 4);
317
+}
318
+
319
+static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset,
320
+ unsigned size)
321
+{
322
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
323
+ uint32_t res = 0;
324
+
325
+ switch (offset) {
326
+ case SDCMD:
327
+ res = s->cmd;
328
+ break;
329
+ case SDHSTS:
330
+ res = s->status;
331
+ break;
332
+ case SDRSP0:
333
+ res = s->rsp[0];
334
+ break;
335
+ case SDRSP1:
336
+ res = s->rsp[1];
337
+ break;
338
+ case SDRSP2:
339
+ res = s->rsp[2];
340
+ break;
341
+ case SDRSP3:
342
+ res = s->rsp[3];
343
+ break;
344
+ case SDEDM:
345
+ res = s->edm;
346
+ break;
347
+ case SDVDD:
348
+ res = s->vdd;
349
+ break;
350
+ case SDDATA:
351
+ res = bcm2835_sdhost_fifo_pop(s);
352
+ bcm2835_sdhost_fifo_run(s);
353
+ break;
354
+ case SDHBCT:
355
+ res = s->hbct;
356
+ break;
357
+ case SDHBLC:
358
+ res = s->hblc;
359
+ break;
360
+
361
+ default:
362
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
363
+ __func__, offset);
364
+ res = 0;
365
+ break;
366
+ }
367
+
368
+ return res;
369
+}
370
+
371
+static void bcm2835_sdhost_write(void *opaque, hwaddr offset,
372
+ uint64_t value, unsigned size)
373
+{
374
+ BCM2835SDHostState *s = (BCM2835SDHostState *)opaque;
375
+
376
+ switch (offset) {
377
+ case SDCMD:
378
+ s->cmd = value;
379
+ if (value & SDCMD_NEW_FLAG) {
380
+ bcm2835_sdhost_send_command(s);
381
+ bcm2835_sdhost_fifo_run(s);
382
+ s->cmd &= ~SDCMD_NEW_FLAG;
383
+ }
384
+ break;
385
+ case SDTOUT:
386
+ break;
387
+ case SDCDIV:
388
+ break;
389
+ case SDHSTS:
390
+ s->status &= ~value;
391
+ bcm2835_sdhost_update_irq(s);
392
+ break;
393
+ case SDARG:
394
+ s->cmdarg = value;
395
+ break;
396
+ case SDEDM:
397
+ if ((value & 0xf) == 0xf) {
398
+ /* power down */
399
+ value &= ~0xf;
400
+ }
401
+ s->edm = value;
402
+ break;
403
+ case SDHCFG:
404
+ s->config = value;
405
+ bcm2835_sdhost_fifo_run(s);
406
+ break;
407
+ case SDVDD:
408
+ s->vdd = value;
409
+ break;
410
+ case SDDATA:
411
+ bcm2835_sdhost_fifo_push(s, value);
412
+ bcm2835_sdhost_fifo_run(s);
413
+ break;
414
+ case SDHBCT:
415
+ s->hbct = value;
416
+ break;
417
+ case SDHBLC:
418
+ s->hblc = value;
419
+ s->datacnt = s->hblc * s->hbct;
420
+ bcm2835_sdhost_fifo_run(s);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
425
+ __func__, offset);
426
+ break;
427
+ }
428
+}
429
+
430
+static const MemoryRegionOps bcm2835_sdhost_ops = {
431
+ .read = bcm2835_sdhost_read,
432
+ .write = bcm2835_sdhost_write,
433
+ .endianness = DEVICE_NATIVE_ENDIAN,
434
+};
435
+
436
+static const VMStateDescription vmstate_bcm2835_sdhost = {
437
+ .name = TYPE_BCM2835_SDHOST,
438
+ .version_id = 1,
439
+ .minimum_version_id = 1,
440
+ .fields = (VMStateField[]) {
441
+ VMSTATE_UINT32(cmd, BCM2835SDHostState),
442
+ VMSTATE_UINT32(cmdarg, BCM2835SDHostState),
443
+ VMSTATE_UINT32(status, BCM2835SDHostState),
444
+ VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4),
445
+ VMSTATE_UINT32(config, BCM2835SDHostState),
446
+ VMSTATE_UINT32(edm, BCM2835SDHostState),
447
+ VMSTATE_UINT32(vdd, BCM2835SDHostState),
448
+ VMSTATE_UINT32(hbct, BCM2835SDHostState),
449
+ VMSTATE_UINT32(hblc, BCM2835SDHostState),
450
+ VMSTATE_INT32(fifo_pos, BCM2835SDHostState),
451
+ VMSTATE_INT32(fifo_len, BCM2835SDHostState),
452
+ VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO_LEN),
453
+ VMSTATE_UINT32(datacnt, BCM2835SDHostState),
454
+ VMSTATE_END_OF_LIST()
455
+ }
456
+};
457
+
458
+static void bcm2835_sdhost_init(Object *obj)
459
+{
460
+ BCM2835SDHostState *s = BCM2835_SDHOST(obj);
461
+
462
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
463
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
464
+
465
+ memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
466
+ TYPE_BCM2835_SDHOST, 0x1000);
467
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
468
+ sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
469
+}
470
+
471
+static void bcm2835_sdhost_reset(DeviceState *dev)
472
+{
473
+ BCM2835SDHostState *s = BCM2835_SDHOST(dev);
474
+
475
+ s->cmd = 0;
476
+ s->cmdarg = 0;
477
+ s->edm = 0x0000c60f;
478
+ s->config = 0;
479
+ s->hbct = 0;
480
+ s->hblc = 0;
481
+ s->datacnt = 0;
482
+ s->fifo_pos = 0;
483
+ s->fifo_len = 0;
484
+}
485
+
486
+static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data)
487
+{
488
+ DeviceClass *dc = DEVICE_CLASS(klass);
489
+
490
+ dc->reset = bcm2835_sdhost_reset;
491
+ dc->vmsd = &vmstate_bcm2835_sdhost;
492
+}
493
+
494
+static TypeInfo bcm2835_sdhost_info = {
495
+ .name = TYPE_BCM2835_SDHOST,
496
+ .parent = TYPE_SYS_BUS_DEVICE,
497
+ .instance_size = sizeof(BCM2835SDHostState),
498
+ .class_init = bcm2835_sdhost_class_init,
499
+ .instance_init = bcm2835_sdhost_init,
500
+};
501
+
502
+static const TypeInfo bcm2835_sdhost_bus_info = {
503
+ .name = TYPE_BCM2835_SDHOST_BUS,
504
+ .parent = TYPE_SD_BUS,
505
+ .instance_size = sizeof(SDBus),
506
+};
507
+
508
+static void bcm2835_sdhost_register_types(void)
509
+{
510
+ type_register_static(&bcm2835_sdhost_info);
511
+ type_register_static(&bcm2835_sdhost_bus_info);
512
+}
513
+
514
+type_init(bcm2835_sdhost_register_types)
515
--
49
--
516
2.7.4
50
2.20.1
517
51
518
52
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Shuffle the order of the checks so that we test the ISA
4
before we test anything else, such as the register arguments.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200214181547.21408-9-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-vfp.inc.c | 144 ++++++++++++++++-----------------
12
1 file changed, 72 insertions(+), 72 deletions(-)
13
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-vfp.inc.c
17
+++ b/target/arm/translate-vfp.inc.c
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
19
return false;
20
}
21
22
- /* UNDEF accesses to D16-D31 if they don't exist */
23
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
24
- ((a->vm | a->vn | a->vd) & 0x10)) {
25
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
26
return false;
27
}
28
29
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
30
+ /* UNDEF accesses to D16-D31 if they don't exist */
31
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
32
+ ((a->vm | a->vn | a->vd) & 0x10)) {
33
return false;
34
}
35
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
37
return false;
38
}
39
40
- /* UNDEF accesses to D16-D31 if they don't exist */
41
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
42
- ((a->vm | a->vn | a->vd) & 0x10)) {
43
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
44
return false;
45
}
46
47
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
48
+ /* UNDEF accesses to D16-D31 if they don't exist */
49
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
50
+ ((a->vm | a->vn | a->vd) & 0x10)) {
51
return false;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
55
return false;
56
}
57
58
- /* UNDEF accesses to D16-D31 if they don't exist */
59
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
60
- ((a->vm | a->vd) & 0x10)) {
61
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
62
return false;
63
}
64
65
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
66
+ /* UNDEF accesses to D16-D31 if they don't exist */
67
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
68
+ ((a->vm | a->vd) & 0x10)) {
69
return false;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
73
return false;
74
}
75
76
- /* UNDEF accesses to D16-D31 if they don't exist */
77
- if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
78
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
79
return false;
80
}
81
82
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
83
+ /* UNDEF accesses to D16-D31 if they don't exist */
84
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
85
return false;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
89
TCGv_i64 f0, f1, fd;
90
TCGv_ptr fpst;
91
92
- /* UNDEF accesses to D16-D31 if they don't exist */
93
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
94
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
95
return false;
96
}
97
98
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
99
+ /* UNDEF accesses to D16-D31 if they don't exist */
100
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
101
return false;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
105
int veclen = s->vec_len;
106
TCGv_i64 f0, fd;
107
108
- /* UNDEF accesses to D16-D31 if they don't exist */
109
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
110
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
111
return false;
112
}
113
114
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
115
+ /* UNDEF accesses to D16-D31 if they don't exist */
116
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
117
return false;
118
}
119
120
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
121
return false;
122
}
123
124
- /* UNDEF accesses to D16-D31 if they don't exist. */
125
- if (!dc_isar_feature(aa32_simd_r32, s) &&
126
- ((a->vd | a->vn | a->vm) & 0x10)) {
127
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
128
return false;
129
}
130
131
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
132
+ /* UNDEF accesses to D16-D31 if they don't exist. */
133
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
134
+ ((a->vd | a->vn | a->vm) & 0x10)) {
135
return false;
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
139
140
vd = a->vd;
141
142
- /* UNDEF accesses to D16-D31 if they don't exist. */
143
- if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
144
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
145
return false;
146
}
147
148
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
149
+ /* UNDEF accesses to D16-D31 if they don't exist. */
150
+ if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
151
return false;
152
}
153
154
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
155
{
156
TCGv_i64 vd, vm;
157
158
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
159
+ return false;
160
+ }
161
+
162
/* Vm/M bits must be zero for the Z variant */
163
if (a->z && a->vm != 0) {
164
return false;
165
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
166
return false;
167
}
168
169
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
170
- return false;
171
- }
172
-
173
if (!vfp_access_check(s)) {
174
return true;
175
}
176
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
177
TCGv_i32 tmp;
178
TCGv_i64 vd;
179
180
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
181
+ return false;
182
+ }
183
+
184
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
185
return false;
186
}
187
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
188
return false;
189
}
190
191
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
192
- return false;
193
- }
194
-
195
if (!vfp_access_check(s)) {
196
return true;
197
}
198
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
199
TCGv_i32 tmp;
200
TCGv_i64 vm;
201
202
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
203
+ return false;
204
+ }
205
+
206
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
207
return false;
208
}
209
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
210
return false;
211
}
212
213
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
214
- return false;
215
- }
216
-
217
if (!vfp_access_check(s)) {
218
return true;
219
}
220
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
221
TCGv_ptr fpst;
222
TCGv_i64 tmp;
223
224
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
225
+ return false;
226
+ }
227
+
228
if (!dc_isar_feature(aa32_vrint, s)) {
229
return false;
230
}
231
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
232
return false;
233
}
234
235
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
236
- return false;
237
- }
238
-
239
if (!vfp_access_check(s)) {
240
return true;
241
}
242
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
243
TCGv_i64 tmp;
244
TCGv_i32 tcg_rmode;
245
246
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
247
+ return false;
248
+ }
249
+
250
if (!dc_isar_feature(aa32_vrint, s)) {
251
return false;
252
}
253
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
254
return false;
255
}
256
257
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
258
- return false;
259
- }
260
-
261
if (!vfp_access_check(s)) {
262
return true;
263
}
264
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
265
TCGv_ptr fpst;
266
TCGv_i64 tmp;
267
268
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
269
+ return false;
270
+ }
271
+
272
if (!dc_isar_feature(aa32_vrint, s)) {
273
return false;
274
}
275
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
276
return false;
277
}
278
279
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
280
- return false;
281
- }
282
-
283
if (!vfp_access_check(s)) {
284
return true;
285
}
286
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
287
TCGv_i64 vd;
288
TCGv_i32 vm;
289
290
- /* UNDEF accesses to D16-D31 if they don't exist. */
291
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
292
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
293
return false;
294
}
295
296
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
297
+ /* UNDEF accesses to D16-D31 if they don't exist. */
298
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
299
return false;
300
}
301
302
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
303
TCGv_i64 vm;
304
TCGv_i32 vd;
305
306
- /* UNDEF accesses to D16-D31 if they don't exist. */
307
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
308
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
309
return false;
310
}
311
312
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
313
+ /* UNDEF accesses to D16-D31 if they don't exist. */
314
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
315
return false;
316
}
317
318
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
319
TCGv_i64 vd;
320
TCGv_ptr fpst;
321
322
- /* UNDEF accesses to D16-D31 if they don't exist. */
323
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
324
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
325
return false;
326
}
327
328
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
329
+ /* UNDEF accesses to D16-D31 if they don't exist. */
330
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
331
return false;
332
}
333
334
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
335
TCGv_i32 vd;
336
TCGv_i64 vm;
337
338
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
339
+ return false;
340
+ }
341
+
342
if (!dc_isar_feature(aa32_jscvt, s)) {
343
return false;
344
}
345
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
346
return false;
347
}
348
349
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
350
- return false;
351
- }
352
-
353
if (!vfp_access_check(s)) {
354
return true;
355
}
356
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
357
TCGv_ptr fpst;
358
int frac_bits;
359
360
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
361
+ return false;
362
+ }
363
+
364
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
365
return false;
366
}
367
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
368
return false;
369
}
370
371
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
372
- return false;
373
- }
374
-
375
if (!vfp_access_check(s)) {
376
return true;
377
}
378
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
379
TCGv_i64 vm;
380
TCGv_ptr fpst;
381
382
- /* UNDEF accesses to D16-D31 if they don't exist. */
383
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
384
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
385
return false;
386
}
387
388
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
389
+ /* UNDEF accesses to D16-D31 if they don't exist. */
390
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
391
return false;
392
}
393
394
--
395
2.20.1
396
397
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
In sdhci_write invoke multi block transfer if it is enabled
3
Sort this check to the start of a trans_* function.
4
in the transfer mode register 's->trnmod'.
4
Merge this with any existing test for fpdp_v2.
5
5
6
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20170214185225.7994-4-ppandit@redhat.com
7
Message-id: 20200214181547.21408-10-richard.henderson@linaro.org
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
hw/sd/sdhci.c | 6 +++++-
11
target/arm/translate-vfp.inc.c | 24 ++++++++----------------
12
1 file changed, 5 insertions(+), 1 deletion(-)
12
1 file changed, 8 insertions(+), 16 deletions(-)
13
13
14
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/sd/sdhci.c
16
--- a/target/arm/translate-vfp.inc.c
17
+++ b/hw/sd/sdhci.c
17
+++ b/target/arm/translate-vfp.inc.c
18
@@ -XXX,XX +XXX,XX @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
19
/* Writing to last byte of sdmasysad might trigger transfer */
19
* VFPv2 allows access to FPSID from userspace; VFPv3 restricts
20
if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
20
* all ID registers to privileged access only.
21
s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
21
*/
22
- sdhci_sdma_transfer_multi_blocks(s);
22
- if (IS_USER(s) && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
23
+ if (s->trnmod & SDHC_TRNS_MULTI) {
23
+ if (IS_USER(s) && dc_isar_feature(aa32_fpsp_v3, s)) {
24
+ sdhci_sdma_transfer_multi_blocks(s);
24
return false;
25
+ } else {
25
}
26
+ sdhci_sdma_transfer_single_block(s);
26
ignore_vfp_enabled = true;
27
+ }
27
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
28
case ARM_VFP_FPINST:
29
case ARM_VFP_FPINST2:
30
/* Not present in VFPv3 */
31
- if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
32
+ if (IS_USER(s) || dc_isar_feature(aa32_fpsp_v3, s)) {
33
return false;
28
}
34
}
29
break;
35
break;
30
case SDHC_BLKSIZE:
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
37
38
vd = a->vd;
39
40
- if (!dc_isar_feature(aa32_fpshvec, s) &&
41
- (veclen != 0 || s->vec_stride != 0)) {
42
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
43
return false;
44
}
45
46
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
47
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
48
+ (veclen != 0 || s->vec_stride != 0)) {
49
return false;
50
}
51
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
53
54
vd = a->vd;
55
56
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
57
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
58
return false;
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
62
return false;
63
}
64
65
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
66
- return false;
67
- }
68
-
69
if (!vfp_access_check(s)) {
70
return true;
71
}
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
73
TCGv_ptr fpst;
74
int frac_bits;
75
76
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
77
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
78
return false;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
82
TCGv_ptr fpst;
83
int frac_bits;
84
85
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
86
- return false;
87
- }
88
-
89
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
90
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
91
return false;
92
}
93
31
--
94
--
32
2.7.4
95
2.20.1
33
96
34
97
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We will eventually remove the early ARM_FEATURE_VFP test,
4
so add a proper test for each trans_* that does not already
5
have another ISA test.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200214181547.21408-11-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-vfp.inc.c | 78 ++++++++++++++++++++++++++++++----
13
1 file changed, 69 insertions(+), 9 deletions(-)
14
15
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.inc.c
18
+++ b/target/arm/translate-vfp.inc.c
19
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
20
int pass;
21
uint32_t offset;
22
23
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
24
+ if (a->size == 2
25
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
26
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
27
+ return false;
28
+ }
29
+
30
/* UNDEF accesses to D16-D31 if they don't exist */
31
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
32
return false;
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
34
pass = extract32(offset, 2, 1);
35
offset = extract32(offset, 0, 2) * 8;
36
37
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
38
- return false;
39
- }
40
-
41
if (!vfp_access_check(s)) {
42
return true;
43
}
44
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
45
int pass;
46
uint32_t offset;
47
48
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
49
+ if (a->size == 2
50
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
51
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
52
+ return false;
53
+ }
54
+
55
/* UNDEF accesses to D16-D31 if they don't exist */
56
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
57
return false;
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
59
pass = extract32(offset, 2, 1);
60
offset = extract32(offset, 0, 2) * 8;
61
62
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
63
- return false;
64
- }
65
-
66
if (!vfp_access_check(s)) {
67
return true;
68
}
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
70
TCGv_i32 tmp;
71
bool ignore_vfp_enabled = false;
72
73
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
74
+ return false;
75
+ }
76
+
77
if (arm_dc_feature(s, ARM_FEATURE_M)) {
78
/*
79
* The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
81
{
82
TCGv_i32 tmp;
83
84
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
85
+ return false;
86
+ }
87
+
88
if (!vfp_access_check(s)) {
89
return true;
90
}
91
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
92
{
93
TCGv_i32 tmp;
94
95
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
96
+ return false;
97
+ }
98
+
99
/*
100
* VMOV between two general-purpose registers and two single precision
101
* floating point registers
102
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
103
104
/*
105
* VMOV between two general-purpose registers and one double precision
106
- * floating point register
107
+ * floating point register. Note that this does not require support
108
+ * for double precision arithmetic.
109
*/
110
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
111
+ return false;
112
+ }
113
114
/* UNDEF accesses to D16-D31 if they don't exist */
115
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
117
uint32_t offset;
118
TCGv_i32 addr, tmp;
119
120
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
121
+ return false;
122
+ }
123
+
124
if (!vfp_access_check(s)) {
125
return true;
126
}
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
128
TCGv_i32 addr;
129
TCGv_i64 tmp;
130
131
+ /* Note that this does not require support for double arithmetic. */
132
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
133
+ return false;
134
+ }
135
+
136
/* UNDEF accesses to D16-D31 if they don't exist */
137
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
138
return false;
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
140
TCGv_i32 addr, tmp;
141
int i, n;
142
143
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
144
+ return false;
145
+ }
146
+
147
n = a->imm;
148
149
if (n == 0 || (a->vd + n) > 32) {
150
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
151
TCGv_i64 tmp;
152
int i, n;
153
154
+ /* Note that this does not require support for double arithmetic. */
155
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
156
+ return false;
157
+ }
158
+
159
n = a->imm >> 1;
160
161
if (n == 0 || (a->vd + n) > 32 || n > 16) {
162
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
163
TCGv_i32 f0, f1, fd;
164
TCGv_ptr fpst;
165
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
167
+ return false;
168
+ }
169
+
170
if (!dc_isar_feature(aa32_fpshvec, s) &&
171
(veclen != 0 || s->vec_stride != 0)) {
172
return false;
173
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
174
int veclen = s->vec_len;
175
TCGv_i32 f0, fd;
176
177
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
178
+ return false;
179
+ }
180
+
181
if (!dc_isar_feature(aa32_fpshvec, s) &&
182
(veclen != 0 || s->vec_stride != 0)) {
183
return false;
184
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
185
{
186
TCGv_i32 vd, vm;
187
188
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
189
+ return false;
190
+ }
191
+
192
/* Vm/M bits must be zero for the Z variant */
193
if (a->z && a->vm != 0) {
194
return false;
195
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
196
TCGv_i32 vm;
197
TCGv_ptr fpst;
198
199
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
200
+ return false;
201
+ }
202
+
203
if (!vfp_access_check(s)) {
204
return true;
205
}
206
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
207
TCGv_i32 vm;
208
TCGv_ptr fpst;
209
210
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
211
+ return false;
212
+ }
213
+
214
if (!vfp_access_check(s)) {
215
return true;
216
}
217
--
218
2.20.1
219
220
diff view generated by jsdifflib