1
First arm pullreq of the 2.11 cycle. I know I still have some
1
Arm queue -- mostly the first slice of my Musca patches.
2
more stuff on my queue to review, but 36 patches is big enough
3
as it is; I expect I'll do another pull later this week.
4
2
5
thanks
3
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit 32f0f68bb77289b75a82925f712bb52e16eac3ba:
6
The following changes since commit fc3dbb90f2eb069801bfb4cfe9cbc83cf9c5f4a9:
9
7
10
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-and-machine-pull-request' into staging (2017-09-01 17:28:54 +0100)
8
Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into staging (2019-02-21 13:09:33 +0000)
11
9
12
are available in the git repository at:
10
are available in the Git repository at:
13
11
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170904
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190221
15
13
16
for you to fetch changes up to 1e35c4ce33a94cf78dbf639695cb877ef35920b0:
14
for you to fetch changes up to 3733f80308d2a7f23f5e39b039e0547aba6c07f1:
17
15
18
arm_gicv3_kvm: Fix compile warning (2017-09-04 12:09:32 +0100)
16
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices (2019-02-21 18:17:48 +0000)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm:
19
target-arm queue:
22
* collection of M profile cleanups and minor bugfixes
20
* Model the Arm "Musca" development boards: "musca-a" and "musca-b1"
23
* loader: handle ELF files with overlapping zero-init data
21
* Implement the ARMv8.3-JSConv extension
24
* virt: allow PMU instantiation with userspace irqchip
22
* v8M MPU should use background region as default, not always
25
* wdt_aspeed: Add support for the reset width register
23
* Stop unintentional sign extension in pmu_init
26
* cpu: Define new cpu_transaction_failed() hook
27
* arm: Support generating CPU exceptions on memory
28
transaction failures (bus faults)
29
* Mark some SoC devices as not user-creatable
30
* arm: Fix aa64 ldp register writeback
31
* arm_gicv3_kvm: Fix compile warning
32
24
33
----------------------------------------------------------------
25
----------------------------------------------------------------
34
Andrew Jeffery (2):
26
Aaron Lindsay OS (1):
35
watchdog: wdt_aspeed: Add support for the reset width register
27
target/arm: Stop unintentional sign extension in pmu_init
36
aspeed_soc: Propagate silicon-rev to watchdog
37
28
38
Andrew Jones (4):
29
Peter Maydell (16):
39
hw/arm/virt: add pmu interrupt state
30
hw/arm/armsse: Fix memory leak in error-exit path
40
target/arm/kvm: pmu: split init and set-irq stages
31
target/arm: v8M MPU should use background region as default, not always
41
hw/arm/virt: allow pmu instantiation with userspace irqchip
32
hw/misc/tz-ppc: Support having unused ports in the middle of the range
42
target/arm/kvm: pmu: improve error handling
33
hw/timer/pl031: Allow use as an embedded-struct device
34
hw/timer/pl031: Convert to using trace events
35
hw/char/pl011: Allow use as an embedded-struct device
36
hw/char/pl011: Support all interrupt lines
37
hw/char/pl011: Use '0x' prefix when logging hex numbers
38
hw/arm/armsse: Document SRAM_ADDR_WIDTH property in header comment
39
hw/arm/armsse: Allow boards to specify init-svtor
40
hw/arm/musca.c: Implement models of the Musca-A and -B1 boards
41
hw/arm/musca: Add PPCs
42
hw/arm/musca: Add MPCs
43
hw/arm/musca: Wire up PL031 RTC
44
hw/arm/musca: Wire up PL011 UARTs
45
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices
43
46
44
Peter Maydell (25):
47
Richard Henderson (4):
45
target/arm: Use MMUAccessType enum rather than int
48
target/arm: Restructure disas_fp_int_conv
46
target/arm: Don't trap WFI/WFE for M profile
49
target/arm: Split out vfp_helper.c
47
target/arm: Consolidate PMSA handling in get_phys_addr()
50
target/arm: Rearrange Floating-point data-processing (2 regs)
48
target/arm: Tighten up Thumb decode where new v8M insns will be
51
target/arm: Implement ARMv8.3-JSConv
49
hw/intc/armv7m_nvic.c: Remove out of date comment
50
target/arm: Remove incorrect comment about MPU_CTRL
51
target/arm: Fix outdated comment about exception exit
52
target/arm: Define and use XPSR bit masks
53
target/arm: Don't store M profile PRIMASK and FAULTMASK in daif
54
target/arm: Don't use cpsr_write/cpsr_read to transfer M profile XPSR
55
target/arm: Make arm_cpu_dump_state() handle the M-profile XPSR
56
target/arm: Don't calculate lr in arm_v7m_cpu_do_interrupt() until needed
57
target/arm: Create and use new function arm_v7m_is_handler_mode()
58
armv7m_nvic.h: Move from include/hw/arm to include/hw/intc
59
nvic: Implement "user accesses BusFault" SCS region behaviour
60
loader: Handle ELF files with overlapping zero-initialized data
61
loader: Ignore zero-sized ELF segments
62
memory.h: Move MemTxResult type to memattrs.h
63
cpu: Define new cpu_transaction_failed() hook
64
cputlb: Support generating CPU exceptions on memory transaction failures
65
boards.h: Define new flag ignore_memory_transaction_failures
66
hw/arm: Set ignore_memory_transaction_failures for most ARM boards
67
target/arm: Factor out fault delivery code
68
target/arm: Allow deliver_fault() caller to specify EA bit
69
target/arm: Implement new do_transaction_failed hook
70
52
71
Philippe Mathieu-Daudé (1):
53
hw/arm/Makefile.objs | 1 +
72
hw/arm: use defined type name instead of hard-coded string
54
target/arm/Makefile.objs | 2 +-
55
include/hw/arm/armsse.h | 7 +-
56
include/hw/char/pl011.h | 34 ++
57
include/hw/misc/tz-ppc.h | 8 +-
58
include/hw/timer/pl031.h | 44 ++
59
target/arm/cpu.h | 10 +
60
target/arm/helper.h | 3 +
61
hw/arm/armsse.c | 44 +-
62
hw/arm/musca.c | 669 ++++++++++++++++++++++
63
hw/char/pl011.c | 81 +--
64
hw/misc/tz-ppc.c | 32 ++
65
hw/timer/pl031.c | 80 ++-
66
target/arm/cpu.c | 1 +
67
target/arm/cpu64.c | 2 +
68
target/arm/helper.c | 1072 +----------------------------------
69
target/arm/translate-a64.c | 120 ++--
70
target/arm/translate.c | 237 ++++----
71
target/arm/vfp_helper.c | 1176 +++++++++++++++++++++++++++++++++++++++
72
MAINTAINERS | 7 +
73
default-configs/arm-softmmu.mak | 1 +
74
hw/timer/trace-events | 6 +
75
22 files changed, 2307 insertions(+), 1330 deletions(-)
76
create mode 100644 include/hw/timer/pl031.h
77
create mode 100644 hw/arm/musca.c
78
create mode 100644 target/arm/vfp_helper.c
73
79
74
Pranith Kumar (1):
75
arm_gicv3_kvm: Fix compile warning
76
77
Richard Henderson (1):
78
target/arm: Fix aa64 ldp register writeback
79
80
Thomas Huth (2):
81
hw/arm/aspeed_soc: Mark devices as user_creatable = false
82
hw/arm/digic: Mark device with user_creatable = false
83
84
include/exec/memattrs.h | 10 +++
85
include/exec/memory.h | 10 ---
86
include/hw/arm/armv7m.h | 2 +-
87
include/hw/boards.h | 11 +++
88
include/hw/elf_ops.h | 72 +++++++++++++--
89
include/hw/{arm => intc}/armv7m_nvic.h | 0
90
include/hw/watchdog/wdt_aspeed.h | 2 +
91
include/qom/cpu.h | 27 ++++++
92
softmmu_template.h | 4 +-
93
target/arm/cpu.h | 56 +++++++++---
94
target/arm/internals.h | 15 +++-
95
target/arm/kvm_arm.h | 9 +-
96
accel/tcg/cputlb.c | 32 ++++++-
97
hw/arm/armv7m.c | 4 +-
98
hw/arm/aspeed.c | 3 +
99
hw/arm/aspeed_soc.c | 4 +
100
hw/arm/collie.c | 1 +
101
hw/arm/cubieboard.c | 1 +
102
hw/arm/digic.c | 2 +
103
hw/arm/digic_boards.c | 1 +
104
hw/arm/exynos4210.c | 4 +-
105
hw/arm/exynos4_boards.c | 2 +
106
hw/arm/gumstix.c | 2 +
107
hw/arm/highbank.c | 13 ++-
108
hw/arm/imx25_pdk.c | 1 +
109
hw/arm/integratorcp.c | 1 +
110
hw/arm/kzm.c | 1 +
111
hw/arm/mainstone.c | 1 +
112
hw/arm/musicpal.c | 1 +
113
hw/arm/netduino2.c | 1 +
114
hw/arm/nseries.c | 2 +
115
hw/arm/omap_sx1.c | 2 +
116
hw/arm/palm.c | 1 +
117
hw/arm/raspi.c | 1 +
118
hw/arm/realview.c | 10 ++-
119
hw/arm/sabrelite.c | 1 +
120
hw/arm/spitz.c | 4 +
121
hw/arm/stellaris.c | 2 +
122
hw/arm/tosa.c | 1 +
123
hw/arm/versatilepb.c | 2 +
124
hw/arm/vexpress.c | 7 +-
125
hw/arm/virt.c | 12 ++-
126
hw/arm/xilinx_zynq.c | 15 ++--
127
hw/arm/xlnx-ep108.c | 2 +
128
hw/arm/z2.c | 1 +
129
hw/intc/arm_gicv3_kvm.c | 2 +-
130
hw/intc/armv7m_nvic.c | 68 +++++++++-----
131
hw/watchdog/wdt_aspeed.c | 93 ++++++++++++++++---
132
qom/cpu.c | 7 ++
133
target/arm/cpu.c | 8 +-
134
target/arm/helper.c | 124 ++++++++++++-------------
135
target/arm/kvm.c | 6 +-
136
target/arm/kvm32.c | 7 +-
137
target/arm/kvm64.c | 63 +++++++------
138
target/arm/machine.c | 54 ++++++++++-
139
target/arm/op_helper.c | 160 ++++++++++++++++++++++-----------
140
target/arm/translate-a64.c | 29 +++---
141
target/arm/translate.c | 106 ++++++++++++++++------
142
58 files changed, 795 insertions(+), 288 deletions(-)
143
rename include/hw/{arm => intc}/armv7m_nvic.h (100%)
144
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Coverity points out (CID 1398632, CID 1398650) that we
2
leak a couple of allocated strings in the error-exit
3
code path for setting up the MHUs in the ARMSSE.
4
Fix this bug by moving the allocate-and-free of each
5
string to be closer to the use, so we do the free before
6
doing the error-exit check.
2
7
3
If a KVM PMU init or set-irq attr call fails we just silently stop
8
Fixes: f8574705f62b38a ("hw/arm/armsse: Add unimplemented-device stubs for MHUs")
4
the PMU DT node generation. The only way they could fail, though,
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
is if the attr's respective KVM has-attr call fails. But that should
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
never happen if KVM advertises the PMU capability, because both
11
Message-id: 20190215113707.24553-1-peter.maydell@linaro.org
7
attrs have been available since the capability was introduced. Let's
12
---
8
just abort if this should-never-happen stuff does happen, because,
13
hw/arm/armsse.c | 10 ++++++----
9
if it does, then something is obviously horribly wrong.
14
1 file changed, 6 insertions(+), 4 deletions(-)
10
15
11
Signed-off-by: Andrew Jones <drjones@redhat.com>
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
12
Reviewed-by: Christoffer Dall <cdall@linaro.org>
13
Message-id: 1500471597-2517-5-git-send-email-drjones@redhat.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/kvm_arm.h | 15 ++++-----------
18
hw/arm/virt.c | 9 +++------
19
target/arm/kvm32.c | 3 +--
20
target/arm/kvm64.c | 28 ++++++++++++++++++++--------
21
4 files changed, 28 insertions(+), 27 deletions(-)
22
23
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/kvm_arm.h
18
--- a/hw/arm/armsse.c
26
+++ b/target/arm/kvm_arm.h
19
+++ b/hw/arm/armsse.c
27
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
20
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
28
21
29
int kvm_arm_vgic_probe(void);
22
if (info->has_mhus) {
30
23
for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
31
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq);
24
- char *name = g_strdup_printf("MHU%d", i);
32
-int kvm_arm_pmu_init(CPUState *cs);
25
- char *port = g_strdup_printf("port[%d]", i + 3);
33
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
26
+ char *name;
34
+void kvm_arm_pmu_init(CPUState *cs);
27
+ char *port;
35
28
36
#else
29
+ name = g_strdup_printf("MHU%d", i);
37
30
qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
38
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
31
qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
39
return 0;
32
object_property_set_bool(OBJECT(&s->mhu[i]), true,
40
}
33
"realized", &err);
41
34
+ g_free(name);
42
-static inline int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
35
if (err) {
43
-{
36
error_propagate(errp, err);
44
- return 0;
37
return;
45
-}
46
-
47
-static inline int kvm_arm_pmu_init(CPUState *cs)
48
-{
49
- return 0;
50
-}
51
+static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
52
+static inline void kvm_arm_pmu_init(CPUState *cs) {}
53
54
#endif
55
56
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/arm/virt.c
59
+++ b/hw/arm/virt.c
60
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
61
return;
62
}
63
if (kvm_enabled()) {
64
- if (kvm_irqchip_in_kernel() &&
65
- !kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
66
- return;
67
- }
68
- if (!kvm_arm_pmu_init(cpu)) {
69
- return;
70
+ if (kvm_irqchip_in_kernel()) {
71
+ kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
72
}
38
}
73
+ kvm_arm_pmu_init(cpu);
39
+ port = g_strdup_printf("port[%d]", i + 3);
40
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
41
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
42
port, &err);
43
+ g_free(port);
44
if (err) {
45
error_propagate(errp, err);
46
return;
47
}
48
- g_free(name);
49
- g_free(port);
74
}
50
}
75
}
51
}
76
52
77
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/kvm32.c
80
+++ b/target/arm/kvm32.c
81
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_hw_debug_active(CPUState *cs)
82
return false;
83
}
84
85
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
86
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
87
{
88
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
89
- return 0;
90
}
91
92
int kvm_arm_pmu_init(CPUState *cs)
93
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/kvm64.c
96
+++ b/target/arm/kvm64.c
97
@@ -XXX,XX +XXX,XX @@ static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr)
98
99
err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
100
if (err != 0) {
101
+ error_report("PMU: KVM_HAS_DEVICE_ATTR: %s", strerror(-err));
102
return false;
103
}
104
105
err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
106
- if (err < 0) {
107
- fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
108
- strerror(-err));
109
- abort();
110
+ if (err != 0) {
111
+ error_report("PMU: KVM_SET_DEVICE_ATTR: %s", strerror(-err));
112
+ return false;
113
}
114
115
return true;
116
}
117
118
-int kvm_arm_pmu_init(CPUState *cs)
119
+void kvm_arm_pmu_init(CPUState *cs)
120
{
121
struct kvm_device_attr attr = {
122
.group = KVM_ARM_VCPU_PMU_V3_CTRL,
123
.attr = KVM_ARM_VCPU_PMU_V3_INIT,
124
};
125
126
- return kvm_arm_pmu_set_attr(cs, &attr);
127
+ if (!ARM_CPU(cs)->has_pmu) {
128
+ return;
129
+ }
130
+ if (!kvm_arm_pmu_set_attr(cs, &attr)) {
131
+ error_report("failed to init PMU");
132
+ abort();
133
+ }
134
}
135
136
-int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
137
+void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
138
{
139
struct kvm_device_attr attr = {
140
.group = KVM_ARM_VCPU_PMU_V3_CTRL,
141
@@ -XXX,XX +XXX,XX @@ int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
142
.attr = KVM_ARM_VCPU_PMU_V3_IRQ,
143
};
144
145
- return kvm_arm_pmu_set_attr(cs, &attr);
146
+ if (!ARM_CPU(cs)->has_pmu) {
147
+ return;
148
+ }
149
+ if (!kvm_arm_pmu_set_attr(cs, &attr)) {
150
+ error_report("failed to set irq for PMU");
151
+ abort();
152
+ }
153
}
154
155
static inline void set_feature(uint64_t *features, int feature)
156
--
53
--
157
2.7.4
54
2.20.1
158
55
159
56
diff view generated by jsdifflib
1
Move the code in arm_v7m_cpu_do_interrupt() that calculates the
1
The "background region" for a v8M MPU is a default which will be used
2
magic LR value down to when we're actually going to use it.
2
(if enabled, and if the access is privileged) if the access does
3
Having the calculation and use so far apart makes the code
3
not match any specific MPU region. We were incorrectly using it
4
a little harder to understand than it needs to be.
4
always (by putting the condition at the wrong nesting level). This
5
meant that we would always return the default background permissions
6
rather than the correct permissions for a specific region, and also
7
that we would not return the right information in response to a
8
TT instruction.
9
10
Move the check for the background region to the same place in the
11
logic as the equivalent v8M MPUCheck() pseudocode puts it.
12
This in turn means we must adjust the condition we use to detect
13
matches in multiple regions to avoid false-positives.
5
14
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-13-git-send-email-peter.maydell@linaro.org
17
Message-id: 20190214113408.10214-1-peter.maydell@linaro.org
11
---
18
---
12
target/arm/helper.c | 15 ++++++++-------
19
target/arm/helper.c | 8 +++++---
13
1 file changed, 8 insertions(+), 7 deletions(-)
20
1 file changed, 5 insertions(+), 3 deletions(-)
14
21
15
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
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
24
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
25
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
26
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
20
27
hit = true;
21
arm_log_exception(cs->exception_index);
28
} else if (m_is_ppb_region(env, address)) {
22
29
hit = true;
23
- lr = 0xfffffff1;
30
- } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
24
- if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
31
- hit = true;
25
- lr |= 4;
32
} else {
26
- }
33
+ if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
27
- if (env->v7m.exception == 0)
34
+ hit = true;
28
- lr |= 8;
35
+ }
29
-
30
/* For exceptions we just mark as pending on the NVIC, and let that
31
handle it. */
32
switch (cs->exception_index) {
33
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
34
return; /* Never happens. Keep compiler happy. */
35
}
36
37
+ lr = 0xfffffff1;
38
+ if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
39
+ lr |= 4;
40
+ }
41
+ if (env->v7m.exception == 0) {
42
+ lr |= 8;
43
+ }
44
+
36
+
45
v7m_push_stack(cpu);
37
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
46
v7m_exception_taken(cpu, lr);
38
/* region search */
47
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
39
/* Note that the base address is bits [31:5] from the register
40
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
41
*is_subpage = true;
42
}
43
44
- if (hit) {
45
+ if (matchregion != -1) {
46
/* Multiple regions match -- always a failure (unlike
47
* PMSAv7 where highest-numbered-region wins)
48
*/
48
--
49
--
49
2.7.4
50
2.20.1
50
51
51
52
diff view generated by jsdifflib
1
When we switched our handling of exception exit to detect
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
2
the magic addresses at translate time rather than via
3
a do_unassigned_access hook, we forgot to update a
4
comment; correct the omission.
5
2
3
This was introduced by
4
commit bf8d09694ccc07487cd73d7562081fdaec3370c8
5
target/arm: Don't clear supported PMU events when initializing PMCEID1
6
and identified by Coverity (CID 1398645).
7
8
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20190219144621.450-1-aaron@os.amperecomputing.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-8-git-send-email-peter.maydell@linaro.org
10
---
13
---
11
target/arm/helper.c | 2 +-
14
target/arm/helper.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
16
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu)
19
bool rettobase = false;
22
20
23
if (cnt->supported(&cpu->env)) {
21
/* We can only get here from an EXCP_EXCEPTION_EXIT, and
24
supported_event_map[cnt->number] = i;
22
- * arm_v7m_do_unassigned_access() enforces the architectural rule
25
- uint64_t event_mask = 1 << (cnt->number & 0x1f);
23
+ * gen_bx_excret() enforces the architectural rule
26
+ uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
24
* that jumps to magic addresses don't have magic behaviour unless
27
if (cnt->number & 0x20) {
25
* we're in Handler mode (compare pseudocode BXWritePC()).
28
cpu->pmceid1 |= event_mask;
26
*/
29
} else {
27
--
30
--
28
2.7.4
31
2.20.1
29
32
30
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
For "ldp x0, x1, [x0]", if the second load is on a second page and
3
For opcodes 0-5, move some if conditions into the structure
4
the second page is unmapped, the exception would be raised with x0
4
of a switch statement. For opcodes 6 & 7, decode everything
5
already modified. This means the instruction couldn't be restarted.
5
at once with a second switch.
6
6
7
Cc: qemu-arm@nongnu.org
8
Cc: qemu-stable@nongnu.org
9
Reported-by: Andrew <andrew@fubar.geek.nz>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20170825224833.4463-1-richard.henderson@linaro.org
8
Message-id: 20190215192302.27855-2-richard.henderson@linaro.org
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1713066
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
[PMM: tweaked comment format]
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
target/arm/translate-a64.c | 29 +++++++++++++++++------------
12
target/arm/translate-a64.c | 94 ++++++++++++++++++++------------------
19
1 file changed, 17 insertions(+), 12 deletions(-)
13
1 file changed, 49 insertions(+), 45 deletions(-)
20
14
21
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/translate-a64.c
17
--- a/target/arm/translate-a64.c
24
+++ b/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
25
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
26
} else {
20
int type = extract32(insn, 22, 2);
27
do_fp_st(s, rt, tcg_addr, size);
21
bool sbit = extract32(insn, 29, 1);
22
bool sf = extract32(insn, 31, 1);
23
+ bool itof = false;
24
25
if (sbit) {
26
- unallocated_encoding(s);
27
- return;
28
+ goto do_unallocated;
29
}
30
31
- if (opcode > 5) {
32
- /* FMOV */
33
- bool itof = opcode & 1;
34
-
35
- if (rmode >= 2) {
36
- unallocated_encoding(s);
37
- return;
38
- }
39
-
40
- switch (sf << 3 | type << 1 | rmode) {
41
- case 0x0: /* 32 bit */
42
- case 0xa: /* 64 bit */
43
- case 0xd: /* 64 bit to top half of quad */
44
- break;
45
- case 0x6: /* 16-bit float, 32-bit int */
46
- case 0xe: /* 16-bit float, 64-bit int */
47
- if (dc_isar_feature(aa64_fp16, s)) {
48
- break;
49
- }
50
- /* fallthru */
51
- default:
52
- /* all other sf/type/rmode combinations are invalid */
53
- unallocated_encoding(s);
54
- return;
55
- }
56
-
57
- if (!fp_access_check(s)) {
58
- return;
59
- }
60
- handle_fmov(s, rd, rn, type, itof);
61
- } else {
62
- /* actual FP conversions */
63
- bool itof = extract32(opcode, 1, 1);
64
-
65
- if (rmode != 0 && opcode > 1) {
66
- unallocated_encoding(s);
67
- return;
68
+ switch (opcode) {
69
+ case 2: /* SCVTF */
70
+ case 3: /* UCVTF */
71
+ itof = true;
72
+ /* fallthru */
73
+ case 4: /* FCVTAS */
74
+ case 5: /* FCVTAU */
75
+ if (rmode != 0) {
76
+ goto do_unallocated;
28
}
77
}
29
- } else {
78
+ /* fallthru */
30
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
79
+ case 0: /* FCVT[NPMZ]S */
31
- if (is_load) {
80
+ case 1: /* FCVT[NPMZ]U */
32
- do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
81
switch (type) {
33
- false, 0, false, false);
82
case 0: /* float32 */
34
- } else {
83
case 1: /* float64 */
35
- do_gpr_st(s, tcg_rt, tcg_addr, size,
84
break;
36
- false, 0, false, false);
85
case 3: /* float16 */
37
- }
86
- if (dc_isar_feature(aa64_fp16, s)) {
38
- }
87
- break;
39
- tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
88
+ if (!dc_isar_feature(aa64_fp16, s)) {
40
- if (is_vector) {
89
+ goto do_unallocated;
41
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
90
}
42
if (is_load) {
91
- /* fallthru */
43
do_fp_ld(s, rt2, tcg_addr, size);
92
+ break;
44
} else {
93
default:
45
do_fp_st(s, rt2, tcg_addr, size);
94
- unallocated_encoding(s);
95
- return;
96
+ goto do_unallocated;
46
}
97
}
47
} else {
98
-
48
+ TCGv_i64 tcg_rt = cpu_reg(s, rt);
99
if (!fp_access_check(s)) {
49
TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
100
return;
101
}
102
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
103
+ break;
50
+
104
+
51
if (is_load) {
105
+ default:
52
+ TCGv_i64 tmp = tcg_temp_new_i64();
106
+ switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
107
+ case 0b01100110: /* FMOV half <-> 32-bit int */
108
+ case 0b01100111:
109
+ case 0b11100110: /* FMOV half <-> 64-bit int */
110
+ case 0b11100111:
111
+ if (!dc_isar_feature(aa64_fp16, s)) {
112
+ goto do_unallocated;
113
+ }
114
+ /* fallthru */
115
+ case 0b00000110: /* FMOV 32-bit */
116
+ case 0b00000111:
117
+ case 0b10100110: /* FMOV 64-bit */
118
+ case 0b10100111:
119
+ case 0b11001110: /* FMOV top half of 128-bit */
120
+ case 0b11001111:
121
+ if (!fp_access_check(s)) {
122
+ return;
123
+ }
124
+ itof = opcode & 1;
125
+ handle_fmov(s, rd, rn, type, itof);
126
+ break;
53
+
127
+
54
+ /* Do not modify tcg_rt before recognizing any exception
128
+ default:
55
+ * from the second load.
129
+ do_unallocated:
56
+ */
130
+ unallocated_encoding(s);
57
+ do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
131
+ return;
58
+ false, 0, false, false);
132
+ }
59
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
133
+ break;
60
do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
134
}
61
false, 0, false, false);
135
}
62
+
136
63
+ tcg_gen_mov_i64(tcg_rt, tmp);
64
+ tcg_temp_free_i64(tmp);
65
} else {
66
+ do_gpr_st(s, tcg_rt, tcg_addr, size,
67
+ false, 0, false, false);
68
+ tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
69
do_gpr_st(s, tcg_rt2, tcg_addr, size,
70
false, 0, false, false);
71
}
72
--
137
--
73
2.7.4
138
2.20.1
74
139
75
140
diff view generated by jsdifflib
1
Currently get_phys_addr() has PMSAv7 handling before the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
"is translation disabled?" check, and then PMSAv5 after it.
3
Tidy this up by making the PMSAv5 code handle the "MPU disabled"
4
case itself, so that we have all the PMSA code in one place.
5
This will make adding the PMSAv8 code slightly cleaner, and
6
also means that pre-v7 PMSA cores benefit from the MPU lookup
7
logging that the PMSAv7 codepath had.
8
2
3
Move all of the fp helpers out of helper.c into a new file.
4
This is code movement only. Since helper.c has no copyright
5
header, take the one from cpu.h for the new file.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190215192302.27855-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1501692241-23310-4-git-send-email-peter.maydell@linaro.org
14
---
11
---
15
target/arm/helper.c | 38 ++++++++++++++++++++++----------------
12
target/arm/Makefile.objs | 2 +-
16
1 file changed, 22 insertions(+), 16 deletions(-)
13
target/arm/helper.c | 1062 -------------------------------------
14
target/arm/vfp_helper.c | 1088 ++++++++++++++++++++++++++++++++++++++
15
3 files changed, 1089 insertions(+), 1063 deletions(-)
16
create mode 100644 target/arm/vfp_helper.c
17
17
18
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/Makefile.objs
21
+++ b/target/arm/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
23
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
24
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
25
obj-y += translate.o op_helper.o helper.o cpu.o
26
-obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
27
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o
28
obj-y += gdbstub.o
29
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
30
obj-$(TARGET_AARCH64) += pauth_helper.o
18
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.c
33
--- a/target/arm/helper.c
21
+++ b/target/arm/helper.c
34
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
35
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
23
uint32_t base;
36
return (a & mask) | (b & ~mask);
24
bool is_user = regime_is_user(env, mmu_idx);
37
}
25
38
26
+ if (regime_translation_disabled(env, mmu_idx)) {
39
-/* VFP support. We follow the convention used for VFP instructions:
27
+ /* MPU disabled. */
40
- Single precision routines have a "s" suffix, double precision a
28
+ *phys_ptr = address;
41
- "d" suffix. */
29
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
42
-
43
-/* Convert host exception flags to vfp form. */
44
-static inline int vfp_exceptbits_from_host(int host_bits)
45
-{
46
- int target_bits = 0;
47
-
48
- if (host_bits & float_flag_invalid)
49
- target_bits |= 1;
50
- if (host_bits & float_flag_divbyzero)
51
- target_bits |= 2;
52
- if (host_bits & float_flag_overflow)
53
- target_bits |= 4;
54
- if (host_bits & (float_flag_underflow | float_flag_output_denormal))
55
- target_bits |= 8;
56
- if (host_bits & float_flag_inexact)
57
- target_bits |= 0x10;
58
- if (host_bits & float_flag_input_denormal)
59
- target_bits |= 0x80;
60
- return target_bits;
61
-}
62
-
63
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
64
-{
65
- uint32_t i, fpscr;
66
-
67
- fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
68
- | (env->vfp.vec_len << 16)
69
- | (env->vfp.vec_stride << 20);
70
-
71
- i = get_float_exception_flags(&env->vfp.fp_status);
72
- i |= get_float_exception_flags(&env->vfp.standard_fp_status);
73
- /* FZ16 does not generate an input denormal exception. */
74
- i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
75
- & ~float_flag_input_denormal);
76
- fpscr |= vfp_exceptbits_from_host(i);
77
-
78
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
79
- fpscr |= i ? FPCR_QC : 0;
80
-
81
- return fpscr;
82
-}
83
-
84
-uint32_t vfp_get_fpscr(CPUARMState *env)
85
-{
86
- return HELPER(vfp_get_fpscr)(env);
87
-}
88
-
89
-/* Convert vfp exception flags to target form. */
90
-static inline int vfp_exceptbits_to_host(int target_bits)
91
-{
92
- int host_bits = 0;
93
-
94
- if (target_bits & 1)
95
- host_bits |= float_flag_invalid;
96
- if (target_bits & 2)
97
- host_bits |= float_flag_divbyzero;
98
- if (target_bits & 4)
99
- host_bits |= float_flag_overflow;
100
- if (target_bits & 8)
101
- host_bits |= float_flag_underflow;
102
- if (target_bits & 0x10)
103
- host_bits |= float_flag_inexact;
104
- if (target_bits & 0x80)
105
- host_bits |= float_flag_input_denormal;
106
- return host_bits;
107
-}
108
-
109
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
110
-{
111
- int i;
112
- uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
113
-
114
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
115
- if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
116
- val &= ~FPCR_FZ16;
117
- }
118
-
119
- /*
120
- * We don't implement trapped exception handling, so the
121
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
122
- *
123
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
124
- * (which are stored in fp_status), and the other RES0 bits
125
- * in between, then we clear all of the low 16 bits.
126
- */
127
- env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
128
- env->vfp.vec_len = (val >> 16) & 7;
129
- env->vfp.vec_stride = (val >> 20) & 3;
130
-
131
- /*
132
- * The bit we set within fpscr_q is arbitrary; the register as a
133
- * whole being zero/non-zero is what counts.
134
- */
135
- env->vfp.qc[0] = val & FPCR_QC;
136
- env->vfp.qc[1] = 0;
137
- env->vfp.qc[2] = 0;
138
- env->vfp.qc[3] = 0;
139
-
140
- changed ^= val;
141
- if (changed & (3 << 22)) {
142
- i = (val >> 22) & 3;
143
- switch (i) {
144
- case FPROUNDING_TIEEVEN:
145
- i = float_round_nearest_even;
146
- break;
147
- case FPROUNDING_POSINF:
148
- i = float_round_up;
149
- break;
150
- case FPROUNDING_NEGINF:
151
- i = float_round_down;
152
- break;
153
- case FPROUNDING_ZERO:
154
- i = float_round_to_zero;
155
- break;
156
- }
157
- set_float_rounding_mode(i, &env->vfp.fp_status);
158
- set_float_rounding_mode(i, &env->vfp.fp_status_f16);
159
- }
160
- if (changed & FPCR_FZ16) {
161
- bool ftz_enabled = val & FPCR_FZ16;
162
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
163
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
164
- }
165
- if (changed & FPCR_FZ) {
166
- bool ftz_enabled = val & FPCR_FZ;
167
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
168
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
169
- }
170
- if (changed & FPCR_DN) {
171
- bool dnan_enabled = val & FPCR_DN;
172
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
173
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
174
- }
175
-
176
- /* The exception flags are ORed together when we read fpscr so we
177
- * only need to preserve the current state in one of our
178
- * float_status values.
179
- */
180
- i = vfp_exceptbits_to_host(val);
181
- set_float_exception_flags(i, &env->vfp.fp_status);
182
- set_float_exception_flags(0, &env->vfp.fp_status_f16);
183
- set_float_exception_flags(0, &env->vfp.standard_fp_status);
184
-}
185
-
186
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
187
-{
188
- HELPER(vfp_set_fpscr)(env, val);
189
-}
190
-
191
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
192
-
193
-#define VFP_BINOP(name) \
194
-float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
195
-{ \
196
- float_status *fpst = fpstp; \
197
- return float32_ ## name(a, b, fpst); \
198
-} \
199
-float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
200
-{ \
201
- float_status *fpst = fpstp; \
202
- return float64_ ## name(a, b, fpst); \
203
-}
204
-VFP_BINOP(add)
205
-VFP_BINOP(sub)
206
-VFP_BINOP(mul)
207
-VFP_BINOP(div)
208
-VFP_BINOP(min)
209
-VFP_BINOP(max)
210
-VFP_BINOP(minnum)
211
-VFP_BINOP(maxnum)
212
-#undef VFP_BINOP
213
-
214
-float32 VFP_HELPER(neg, s)(float32 a)
215
-{
216
- return float32_chs(a);
217
-}
218
-
219
-float64 VFP_HELPER(neg, d)(float64 a)
220
-{
221
- return float64_chs(a);
222
-}
223
-
224
-float32 VFP_HELPER(abs, s)(float32 a)
225
-{
226
- return float32_abs(a);
227
-}
228
-
229
-float64 VFP_HELPER(abs, d)(float64 a)
230
-{
231
- return float64_abs(a);
232
-}
233
-
234
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
235
-{
236
- return float32_sqrt(a, &env->vfp.fp_status);
237
-}
238
-
239
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
240
-{
241
- return float64_sqrt(a, &env->vfp.fp_status);
242
-}
243
-
244
-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
245
-{
246
- uint32_t flags;
247
- switch (cmp) {
248
- case float_relation_equal:
249
- flags = 0x6;
250
- break;
251
- case float_relation_less:
252
- flags = 0x8;
253
- break;
254
- case float_relation_greater:
255
- flags = 0x2;
256
- break;
257
- case float_relation_unordered:
258
- flags = 0x3;
259
- break;
260
- default:
261
- g_assert_not_reached();
262
- }
263
- env->vfp.xregs[ARM_VFP_FPSCR] =
264
- deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
265
-}
266
-
267
-/* XXX: check quiet/signaling case */
268
-#define DO_VFP_cmp(p, type) \
269
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
270
-{ \
271
- softfloat_to_vfp_compare(env, \
272
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
273
-} \
274
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
275
-{ \
276
- softfloat_to_vfp_compare(env, \
277
- type ## _compare(a, b, &env->vfp.fp_status)); \
278
-}
279
-DO_VFP_cmp(s, float32)
280
-DO_VFP_cmp(d, float64)
281
-#undef DO_VFP_cmp
282
-
283
-/* Integer to float and float to integer conversions */
284
-
285
-#define CONV_ITOF(name, ftype, fsz, sign) \
286
-ftype HELPER(name)(uint32_t x, void *fpstp) \
287
-{ \
288
- float_status *fpst = fpstp; \
289
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
290
-}
291
-
292
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
293
-sign##int32_t HELPER(name)(ftype x, void *fpstp) \
294
-{ \
295
- float_status *fpst = fpstp; \
296
- if (float##fsz##_is_any_nan(x)) { \
297
- float_raise(float_flag_invalid, fpst); \
298
- return 0; \
299
- } \
300
- return float##fsz##_to_##sign##int32##round(x, fpst); \
301
-}
302
-
303
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
304
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
305
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
306
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
307
-
308
-FLOAT_CONVS(si, h, uint32_t, 16, )
309
-FLOAT_CONVS(si, s, float32, 32, )
310
-FLOAT_CONVS(si, d, float64, 64, )
311
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
312
-FLOAT_CONVS(ui, s, float32, 32, u)
313
-FLOAT_CONVS(ui, d, float64, 64, u)
314
-
315
-#undef CONV_ITOF
316
-#undef CONV_FTOI
317
-#undef FLOAT_CONVS
318
-
319
-/* floating point conversion */
320
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
321
-{
322
- return float32_to_float64(x, &env->vfp.fp_status);
323
-}
324
-
325
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
326
-{
327
- return float64_to_float32(x, &env->vfp.fp_status);
328
-}
329
-
330
-/* VFP3 fixed point conversion. */
331
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
332
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
333
- void *fpstp) \
334
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
335
-
336
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
337
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
338
- void *fpst) \
339
-{ \
340
- if (unlikely(float##fsz##_is_any_nan(x))) { \
341
- float_raise(float_flag_invalid, fpst); \
342
- return 0; \
343
- } \
344
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
345
-}
346
-
347
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
348
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
349
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
350
- float_round_to_zero, _round_to_zero) \
351
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
352
- get_float_rounding_mode(fpst), )
353
-
354
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
355
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
356
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
357
- get_float_rounding_mode(fpst), )
358
-
359
-VFP_CONV_FIX(sh, d, 64, 64, int16)
360
-VFP_CONV_FIX(sl, d, 64, 64, int32)
361
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
362
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
363
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
364
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
365
-VFP_CONV_FIX(sh, s, 32, 32, int16)
366
-VFP_CONV_FIX(sl, s, 32, 32, int32)
367
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
368
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
369
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
370
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
371
-
372
-#undef VFP_CONV_FIX
373
-#undef VFP_CONV_FIX_FLOAT
374
-#undef VFP_CONV_FLOAT_FIX_ROUND
375
-#undef VFP_CONV_FIX_A64
376
-
377
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
378
-{
379
- return int32_to_float16_scalbn(x, -shift, fpst);
380
-}
381
-
382
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
383
-{
384
- return uint32_to_float16_scalbn(x, -shift, fpst);
385
-}
386
-
387
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
388
-{
389
- return int64_to_float16_scalbn(x, -shift, fpst);
390
-}
391
-
392
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
393
-{
394
- return uint64_to_float16_scalbn(x, -shift, fpst);
395
-}
396
-
397
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
398
-{
399
- if (unlikely(float16_is_any_nan(x))) {
400
- float_raise(float_flag_invalid, fpst);
401
- return 0;
402
- }
403
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
404
- shift, fpst);
405
-}
406
-
407
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
408
-{
409
- if (unlikely(float16_is_any_nan(x))) {
410
- float_raise(float_flag_invalid, fpst);
411
- return 0;
412
- }
413
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
414
- shift, fpst);
415
-}
416
-
417
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
418
-{
419
- if (unlikely(float16_is_any_nan(x))) {
420
- float_raise(float_flag_invalid, fpst);
421
- return 0;
422
- }
423
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
424
- shift, fpst);
425
-}
426
-
427
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
428
-{
429
- if (unlikely(float16_is_any_nan(x))) {
430
- float_raise(float_flag_invalid, fpst);
431
- return 0;
432
- }
433
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
434
- shift, fpst);
435
-}
436
-
437
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
438
-{
439
- if (unlikely(float16_is_any_nan(x))) {
440
- float_raise(float_flag_invalid, fpst);
441
- return 0;
442
- }
443
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
444
- shift, fpst);
445
-}
446
-
447
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
448
-{
449
- if (unlikely(float16_is_any_nan(x))) {
450
- float_raise(float_flag_invalid, fpst);
451
- return 0;
452
- }
453
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
454
- shift, fpst);
455
-}
456
-
457
-/* Set the current fp rounding mode and return the old one.
458
- * The argument is a softfloat float_round_ value.
459
- */
460
-uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
461
-{
462
- float_status *fp_status = fpstp;
463
-
464
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
465
- set_float_rounding_mode(rmode, fp_status);
466
-
467
- return prev_rmode;
468
-}
469
-
470
-/* Set the current fp rounding mode in the standard fp status and return
471
- * the old one. This is for NEON instructions that need to change the
472
- * rounding mode but wish to use the standard FPSCR values for everything
473
- * else. Always set the rounding mode back to the correct value after
474
- * modifying it.
475
- * The argument is a softfloat float_round_ value.
476
- */
477
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
478
-{
479
- float_status *fp_status = &env->vfp.standard_fp_status;
480
-
481
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
482
- set_float_rounding_mode(rmode, fp_status);
483
-
484
- return prev_rmode;
485
-}
486
-
487
-/* Half precision conversions. */
488
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
489
-{
490
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
491
- * it would affect flushing input denormals.
492
- */
493
- float_status *fpst = fpstp;
494
- flag save = get_flush_inputs_to_zero(fpst);
495
- set_flush_inputs_to_zero(false, fpst);
496
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
497
- set_flush_inputs_to_zero(save, fpst);
498
- return r;
499
-}
500
-
501
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
502
-{
503
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
504
- * it would affect flushing output denormals.
505
- */
506
- float_status *fpst = fpstp;
507
- flag save = get_flush_to_zero(fpst);
508
- set_flush_to_zero(false, fpst);
509
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
510
- set_flush_to_zero(save, fpst);
511
- return r;
512
-}
513
-
514
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
515
-{
516
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
517
- * it would affect flushing input denormals.
518
- */
519
- float_status *fpst = fpstp;
520
- flag save = get_flush_inputs_to_zero(fpst);
521
- set_flush_inputs_to_zero(false, fpst);
522
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
523
- set_flush_inputs_to_zero(save, fpst);
524
- return r;
525
-}
526
-
527
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
528
-{
529
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
530
- * it would affect flushing output denormals.
531
- */
532
- float_status *fpst = fpstp;
533
- flag save = get_flush_to_zero(fpst);
534
- set_flush_to_zero(false, fpst);
535
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
536
- set_flush_to_zero(save, fpst);
537
- return r;
538
-}
539
-
540
-#define float32_two make_float32(0x40000000)
541
-#define float32_three make_float32(0x40400000)
542
-#define float32_one_point_five make_float32(0x3fc00000)
543
-
544
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
545
-{
546
- float_status *s = &env->vfp.standard_fp_status;
547
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
548
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
549
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
550
- float_raise(float_flag_input_denormal, s);
551
- }
552
- return float32_two;
553
- }
554
- return float32_sub(float32_two, float32_mul(a, b, s), s);
555
-}
556
-
557
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
558
-{
559
- float_status *s = &env->vfp.standard_fp_status;
560
- float32 product;
561
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
562
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
563
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
564
- float_raise(float_flag_input_denormal, s);
565
- }
566
- return float32_one_point_five;
567
- }
568
- product = float32_mul(a, b, s);
569
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
570
-}
571
-
572
-/* NEON helpers. */
573
-
574
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
575
- * int->float conversions at run-time. */
576
-#define float64_256 make_float64(0x4070000000000000LL)
577
-#define float64_512 make_float64(0x4080000000000000LL)
578
-#define float16_maxnorm make_float16(0x7bff)
579
-#define float32_maxnorm make_float32(0x7f7fffff)
580
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
581
-
582
-/* Reciprocal functions
583
- *
584
- * The algorithm that must be used to calculate the estimate
585
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
586
- */
587
-
588
-/* See RecipEstimate()
589
- *
590
- * input is a 9 bit fixed point number
591
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
592
- * result range 256 .. 511 for a number from 1.0 to 511/256.
593
- */
594
-
595
-static int recip_estimate(int input)
596
-{
597
- int a, b, r;
598
- assert(256 <= input && input < 512);
599
- a = (input * 2) + 1;
600
- b = (1 << 19) / a;
601
- r = (b + 1) >> 1;
602
- assert(256 <= r && r < 512);
603
- return r;
604
-}
605
-
606
-/*
607
- * Common wrapper to call recip_estimate
608
- *
609
- * The parameters are exponent and 64 bit fraction (without implicit
610
- * bit) where the binary point is nominally at bit 52. Returns a
611
- * float64 which can then be rounded to the appropriate size by the
612
- * callee.
613
- */
614
-
615
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
616
-{
617
- uint32_t scaled, estimate;
618
- uint64_t result_frac;
619
- int result_exp;
620
-
621
- /* Handle sub-normals */
622
- if (*exp == 0) {
623
- if (extract64(frac, 51, 1) == 0) {
624
- *exp = -1;
625
- frac <<= 2;
626
- } else {
627
- frac <<= 1;
628
- }
629
- }
630
-
631
- /* scaled = UInt('1':fraction<51:44>) */
632
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
633
- estimate = recip_estimate(scaled);
634
-
635
- result_exp = exp_off - *exp;
636
- result_frac = deposit64(0, 44, 8, estimate);
637
- if (result_exp == 0) {
638
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
639
- } else if (result_exp == -1) {
640
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
641
- result_exp = 0;
642
- }
643
-
644
- *exp = result_exp;
645
-
646
- return result_frac;
647
-}
648
-
649
-static bool round_to_inf(float_status *fpst, bool sign_bit)
650
-{
651
- switch (fpst->float_rounding_mode) {
652
- case float_round_nearest_even: /* Round to Nearest */
653
- return true;
654
- case float_round_up: /* Round to +Inf */
655
- return !sign_bit;
656
- case float_round_down: /* Round to -Inf */
657
- return sign_bit;
658
- case float_round_to_zero: /* Round to Zero */
659
- return false;
660
- }
661
-
662
- g_assert_not_reached();
663
-}
664
-
665
-uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
666
-{
667
- float_status *fpst = fpstp;
668
- float16 f16 = float16_squash_input_denormal(input, fpst);
669
- uint32_t f16_val = float16_val(f16);
670
- uint32_t f16_sign = float16_is_neg(f16);
671
- int f16_exp = extract32(f16_val, 10, 5);
672
- uint32_t f16_frac = extract32(f16_val, 0, 10);
673
- uint64_t f64_frac;
674
-
675
- if (float16_is_any_nan(f16)) {
676
- float16 nan = f16;
677
- if (float16_is_signaling_nan(f16, fpst)) {
678
- float_raise(float_flag_invalid, fpst);
679
- nan = float16_silence_nan(f16, fpst);
680
- }
681
- if (fpst->default_nan_mode) {
682
- nan = float16_default_nan(fpst);
683
- }
684
- return nan;
685
- } else if (float16_is_infinity(f16)) {
686
- return float16_set_sign(float16_zero, float16_is_neg(f16));
687
- } else if (float16_is_zero(f16)) {
688
- float_raise(float_flag_divbyzero, fpst);
689
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
690
- } else if (float16_abs(f16) < (1 << 8)) {
691
- /* Abs(value) < 2.0^-16 */
692
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
693
- if (round_to_inf(fpst, f16_sign)) {
694
- return float16_set_sign(float16_infinity, f16_sign);
695
- } else {
696
- return float16_set_sign(float16_maxnorm, f16_sign);
697
- }
698
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
699
- float_raise(float_flag_underflow, fpst);
700
- return float16_set_sign(float16_zero, float16_is_neg(f16));
701
- }
702
-
703
- f64_frac = call_recip_estimate(&f16_exp, 29,
704
- ((uint64_t) f16_frac) << (52 - 10));
705
-
706
- /* result = sign : result_exp<4:0> : fraction<51:42> */
707
- f16_val = deposit32(0, 15, 1, f16_sign);
708
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
709
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
710
- return make_float16(f16_val);
711
-}
712
-
713
-float32 HELPER(recpe_f32)(float32 input, void *fpstp)
714
-{
715
- float_status *fpst = fpstp;
716
- float32 f32 = float32_squash_input_denormal(input, fpst);
717
- uint32_t f32_val = float32_val(f32);
718
- bool f32_sign = float32_is_neg(f32);
719
- int f32_exp = extract32(f32_val, 23, 8);
720
- uint32_t f32_frac = extract32(f32_val, 0, 23);
721
- uint64_t f64_frac;
722
-
723
- if (float32_is_any_nan(f32)) {
724
- float32 nan = f32;
725
- if (float32_is_signaling_nan(f32, fpst)) {
726
- float_raise(float_flag_invalid, fpst);
727
- nan = float32_silence_nan(f32, fpst);
728
- }
729
- if (fpst->default_nan_mode) {
730
- nan = float32_default_nan(fpst);
731
- }
732
- return nan;
733
- } else if (float32_is_infinity(f32)) {
734
- return float32_set_sign(float32_zero, float32_is_neg(f32));
735
- } else if (float32_is_zero(f32)) {
736
- float_raise(float_flag_divbyzero, fpst);
737
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
738
- } else if (float32_abs(f32) < (1ULL << 21)) {
739
- /* Abs(value) < 2.0^-128 */
740
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
741
- if (round_to_inf(fpst, f32_sign)) {
742
- return float32_set_sign(float32_infinity, f32_sign);
743
- } else {
744
- return float32_set_sign(float32_maxnorm, f32_sign);
745
- }
746
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
747
- float_raise(float_flag_underflow, fpst);
748
- return float32_set_sign(float32_zero, float32_is_neg(f32));
749
- }
750
-
751
- f64_frac = call_recip_estimate(&f32_exp, 253,
752
- ((uint64_t) f32_frac) << (52 - 23));
753
-
754
- /* result = sign : result_exp<7:0> : fraction<51:29> */
755
- f32_val = deposit32(0, 31, 1, f32_sign);
756
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
757
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
758
- return make_float32(f32_val);
759
-}
760
-
761
-float64 HELPER(recpe_f64)(float64 input, void *fpstp)
762
-{
763
- float_status *fpst = fpstp;
764
- float64 f64 = float64_squash_input_denormal(input, fpst);
765
- uint64_t f64_val = float64_val(f64);
766
- bool f64_sign = float64_is_neg(f64);
767
- int f64_exp = extract64(f64_val, 52, 11);
768
- uint64_t f64_frac = extract64(f64_val, 0, 52);
769
-
770
- /* Deal with any special cases */
771
- if (float64_is_any_nan(f64)) {
772
- float64 nan = f64;
773
- if (float64_is_signaling_nan(f64, fpst)) {
774
- float_raise(float_flag_invalid, fpst);
775
- nan = float64_silence_nan(f64, fpst);
776
- }
777
- if (fpst->default_nan_mode) {
778
- nan = float64_default_nan(fpst);
779
- }
780
- return nan;
781
- } else if (float64_is_infinity(f64)) {
782
- return float64_set_sign(float64_zero, float64_is_neg(f64));
783
- } else if (float64_is_zero(f64)) {
784
- float_raise(float_flag_divbyzero, fpst);
785
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
786
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
787
- /* Abs(value) < 2.0^-1024 */
788
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
789
- if (round_to_inf(fpst, f64_sign)) {
790
- return float64_set_sign(float64_infinity, f64_sign);
791
- } else {
792
- return float64_set_sign(float64_maxnorm, f64_sign);
793
- }
794
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
795
- float_raise(float_flag_underflow, fpst);
796
- return float64_set_sign(float64_zero, float64_is_neg(f64));
797
- }
798
-
799
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
800
-
801
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
802
- f64_val = deposit64(0, 63, 1, f64_sign);
803
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
804
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
805
- return make_float64(f64_val);
806
-}
807
-
808
-/* The algorithm that must be used to calculate the estimate
809
- * is specified by the ARM ARM.
810
- */
811
-
812
-static int do_recip_sqrt_estimate(int a)
813
-{
814
- int b, estimate;
815
-
816
- assert(128 <= a && a < 512);
817
- if (a < 256) {
818
- a = a * 2 + 1;
819
- } else {
820
- a = (a >> 1) << 1;
821
- a = (a + 1) * 2;
822
- }
823
- b = 512;
824
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
825
- b += 1;
826
- }
827
- estimate = (b + 1) / 2;
828
- assert(256 <= estimate && estimate < 512);
829
-
830
- return estimate;
831
-}
832
-
833
-
834
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
835
-{
836
- int estimate;
837
- uint32_t scaled;
838
-
839
- if (*exp == 0) {
840
- while (extract64(frac, 51, 1) == 0) {
841
- frac = frac << 1;
842
- *exp -= 1;
843
- }
844
- frac = extract64(frac, 0, 51) << 1;
845
- }
846
-
847
- if (*exp & 1) {
848
- /* scaled = UInt('01':fraction<51:45>) */
849
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
850
- } else {
851
- /* scaled = UInt('1':fraction<51:44>) */
852
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
853
- }
854
- estimate = do_recip_sqrt_estimate(scaled);
855
-
856
- *exp = (exp_off - *exp) / 2;
857
- return extract64(estimate, 0, 8) << 44;
858
-}
859
-
860
-uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
861
-{
862
- float_status *s = fpstp;
863
- float16 f16 = float16_squash_input_denormal(input, s);
864
- uint16_t val = float16_val(f16);
865
- bool f16_sign = float16_is_neg(f16);
866
- int f16_exp = extract32(val, 10, 5);
867
- uint16_t f16_frac = extract32(val, 0, 10);
868
- uint64_t f64_frac;
869
-
870
- if (float16_is_any_nan(f16)) {
871
- float16 nan = f16;
872
- if (float16_is_signaling_nan(f16, s)) {
873
- float_raise(float_flag_invalid, s);
874
- nan = float16_silence_nan(f16, s);
875
- }
876
- if (s->default_nan_mode) {
877
- nan = float16_default_nan(s);
878
- }
879
- return nan;
880
- } else if (float16_is_zero(f16)) {
881
- float_raise(float_flag_divbyzero, s);
882
- return float16_set_sign(float16_infinity, f16_sign);
883
- } else if (f16_sign) {
884
- float_raise(float_flag_invalid, s);
885
- return float16_default_nan(s);
886
- } else if (float16_is_infinity(f16)) {
887
- return float16_zero;
888
- }
889
-
890
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
891
- * preserving the parity of the exponent. */
892
-
893
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
894
-
895
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
896
-
897
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
898
- val = deposit32(0, 15, 1, f16_sign);
899
- val = deposit32(val, 10, 5, f16_exp);
900
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
901
- return make_float16(val);
902
-}
903
-
904
-float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
905
-{
906
- float_status *s = fpstp;
907
- float32 f32 = float32_squash_input_denormal(input, s);
908
- uint32_t val = float32_val(f32);
909
- uint32_t f32_sign = float32_is_neg(f32);
910
- int f32_exp = extract32(val, 23, 8);
911
- uint32_t f32_frac = extract32(val, 0, 23);
912
- uint64_t f64_frac;
913
-
914
- if (float32_is_any_nan(f32)) {
915
- float32 nan = f32;
916
- if (float32_is_signaling_nan(f32, s)) {
917
- float_raise(float_flag_invalid, s);
918
- nan = float32_silence_nan(f32, s);
919
- }
920
- if (s->default_nan_mode) {
921
- nan = float32_default_nan(s);
922
- }
923
- return nan;
924
- } else if (float32_is_zero(f32)) {
925
- float_raise(float_flag_divbyzero, s);
926
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
927
- } else if (float32_is_neg(f32)) {
928
- float_raise(float_flag_invalid, s);
929
- return float32_default_nan(s);
930
- } else if (float32_is_infinity(f32)) {
931
- return float32_zero;
932
- }
933
-
934
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
935
- * preserving the parity of the exponent. */
936
-
937
- f64_frac = ((uint64_t) f32_frac) << 29;
938
-
939
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
940
-
941
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
942
- val = deposit32(0, 31, 1, f32_sign);
943
- val = deposit32(val, 23, 8, f32_exp);
944
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
945
- return make_float32(val);
946
-}
947
-
948
-float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
949
-{
950
- float_status *s = fpstp;
951
- float64 f64 = float64_squash_input_denormal(input, s);
952
- uint64_t val = float64_val(f64);
953
- bool f64_sign = float64_is_neg(f64);
954
- int f64_exp = extract64(val, 52, 11);
955
- uint64_t f64_frac = extract64(val, 0, 52);
956
-
957
- if (float64_is_any_nan(f64)) {
958
- float64 nan = f64;
959
- if (float64_is_signaling_nan(f64, s)) {
960
- float_raise(float_flag_invalid, s);
961
- nan = float64_silence_nan(f64, s);
962
- }
963
- if (s->default_nan_mode) {
964
- nan = float64_default_nan(s);
965
- }
966
- return nan;
967
- } else if (float64_is_zero(f64)) {
968
- float_raise(float_flag_divbyzero, s);
969
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
970
- } else if (float64_is_neg(f64)) {
971
- float_raise(float_flag_invalid, s);
972
- return float64_default_nan(s);
973
- } else if (float64_is_infinity(f64)) {
974
- return float64_zero;
975
- }
976
-
977
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
978
-
979
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
980
- val = deposit64(0, 61, 1, f64_sign);
981
- val = deposit64(val, 52, 11, f64_exp);
982
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
983
- return make_float64(val);
984
-}
985
-
986
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
987
-{
988
- /* float_status *s = fpstp; */
989
- int input, estimate;
990
-
991
- if ((a & 0x80000000) == 0) {
992
- return 0xffffffff;
993
- }
994
-
995
- input = extract32(a, 23, 9);
996
- estimate = recip_estimate(input);
997
-
998
- return deposit32(0, (32 - 9), 9, estimate);
999
-}
1000
-
1001
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
1002
-{
1003
- int estimate;
1004
-
1005
- if ((a & 0xc0000000) == 0) {
1006
- return 0xffffffff;
1007
- }
1008
-
1009
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
1010
-
1011
- return deposit32(0, 23, 9, estimate);
1012
-}
1013
-
1014
-/* VFPv4 fused multiply-accumulate */
1015
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
1016
-{
1017
- float_status *fpst = fpstp;
1018
- return float32_muladd(a, b, c, 0, fpst);
1019
-}
1020
-
1021
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
1022
-{
1023
- float_status *fpst = fpstp;
1024
- return float64_muladd(a, b, c, 0, fpst);
1025
-}
1026
-
1027
-/* ARMv8 round to integral */
1028
-float32 HELPER(rints_exact)(float32 x, void *fp_status)
1029
-{
1030
- return float32_round_to_int(x, fp_status);
1031
-}
1032
-
1033
-float64 HELPER(rintd_exact)(float64 x, void *fp_status)
1034
-{
1035
- return float64_round_to_int(x, fp_status);
1036
-}
1037
-
1038
-float32 HELPER(rints)(float32 x, void *fp_status)
1039
-{
1040
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1041
- float32 ret;
1042
-
1043
- ret = float32_round_to_int(x, fp_status);
1044
-
1045
- /* Suppress any inexact exceptions the conversion produced */
1046
- if (!(old_flags & float_flag_inexact)) {
1047
- new_flags = get_float_exception_flags(fp_status);
1048
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1049
- }
1050
-
1051
- return ret;
1052
-}
1053
-
1054
-float64 HELPER(rintd)(float64 x, void *fp_status)
1055
-{
1056
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1057
- float64 ret;
1058
-
1059
- ret = float64_round_to_int(x, fp_status);
1060
-
1061
- new_flags = get_float_exception_flags(fp_status);
1062
-
1063
- /* Suppress any inexact exceptions the conversion produced */
1064
- if (!(old_flags & float_flag_inexact)) {
1065
- new_flags = get_float_exception_flags(fp_status);
1066
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1067
- }
1068
-
1069
- return ret;
1070
-}
1071
-
1072
-/* Convert ARM rounding mode to softfloat */
1073
-int arm_rmode_to_sf(int rmode)
1074
-{
1075
- switch (rmode) {
1076
- case FPROUNDING_TIEAWAY:
1077
- rmode = float_round_ties_away;
1078
- break;
1079
- case FPROUNDING_ODD:
1080
- /* FIXME: add support for TIEAWAY and ODD */
1081
- qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
1082
- rmode);
1083
- /* fall through for now */
1084
- case FPROUNDING_TIEEVEN:
1085
- default:
1086
- rmode = float_round_nearest_even;
1087
- break;
1088
- case FPROUNDING_POSINF:
1089
- rmode = float_round_up;
1090
- break;
1091
- case FPROUNDING_NEGINF:
1092
- rmode = float_round_down;
1093
- break;
1094
- case FPROUNDING_ZERO:
1095
- rmode = float_round_to_zero;
1096
- break;
1097
- }
1098
- return rmode;
1099
-}
1100
-
1101
/* CRC helpers.
1102
* The upper bytes of val (above the number specified by 'bytes') must have
1103
* been zeroed out by the caller.
1104
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
1105
new file mode 100644
1106
index XXXXXXX..XXXXXXX
1107
--- /dev/null
1108
+++ b/target/arm/vfp_helper.c
1109
@@ -XXX,XX +XXX,XX @@
1110
+/*
1111
+ * ARM VFP floating-point operations
1112
+ *
1113
+ * Copyright (c) 2003 Fabrice Bellard
1114
+ *
1115
+ * This library is free software; you can redistribute it and/or
1116
+ * modify it under the terms of the GNU Lesser General Public
1117
+ * License as published by the Free Software Foundation; either
1118
+ * version 2.1 of the License, or (at your option) any later version.
1119
+ *
1120
+ * This library is distributed in the hope that it will be useful,
1121
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1122
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1123
+ * Lesser General Public License for more details.
1124
+ *
1125
+ * You should have received a copy of the GNU Lesser General Public
1126
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1127
+ */
1128
+
1129
+#include "qemu/osdep.h"
1130
+#include "qemu/log.h"
1131
+#include "cpu.h"
1132
+#include "exec/helper-proto.h"
1133
+#include "fpu/softfloat.h"
1134
+#include "internals.h"
1135
+
1136
+
1137
+/* VFP support. We follow the convention used for VFP instructions:
1138
+ Single precision routines have a "s" suffix, double precision a
1139
+ "d" suffix. */
1140
+
1141
+/* Convert host exception flags to vfp form. */
1142
+static inline int vfp_exceptbits_from_host(int host_bits)
1143
+{
1144
+ int target_bits = 0;
1145
+
1146
+ if (host_bits & float_flag_invalid)
1147
+ target_bits |= 1;
1148
+ if (host_bits & float_flag_divbyzero)
1149
+ target_bits |= 2;
1150
+ if (host_bits & float_flag_overflow)
1151
+ target_bits |= 4;
1152
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal))
1153
+ target_bits |= 8;
1154
+ if (host_bits & float_flag_inexact)
1155
+ target_bits |= 0x10;
1156
+ if (host_bits & float_flag_input_denormal)
1157
+ target_bits |= 0x80;
1158
+ return target_bits;
1159
+}
1160
+
1161
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
1162
+{
1163
+ uint32_t i, fpscr;
1164
+
1165
+ fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
1166
+ | (env->vfp.vec_len << 16)
1167
+ | (env->vfp.vec_stride << 20);
1168
+
1169
+ i = get_float_exception_flags(&env->vfp.fp_status);
1170
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
1171
+ /* FZ16 does not generate an input denormal exception. */
1172
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
1173
+ & ~float_flag_input_denormal);
1174
+ fpscr |= vfp_exceptbits_from_host(i);
1175
+
1176
+ i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
1177
+ fpscr |= i ? FPCR_QC : 0;
1178
+
1179
+ return fpscr;
1180
+}
1181
+
1182
+uint32_t vfp_get_fpscr(CPUARMState *env)
1183
+{
1184
+ return HELPER(vfp_get_fpscr)(env);
1185
+}
1186
+
1187
+/* Convert vfp exception flags to target form. */
1188
+static inline int vfp_exceptbits_to_host(int target_bits)
1189
+{
1190
+ int host_bits = 0;
1191
+
1192
+ if (target_bits & 1)
1193
+ host_bits |= float_flag_invalid;
1194
+ if (target_bits & 2)
1195
+ host_bits |= float_flag_divbyzero;
1196
+ if (target_bits & 4)
1197
+ host_bits |= float_flag_overflow;
1198
+ if (target_bits & 8)
1199
+ host_bits |= float_flag_underflow;
1200
+ if (target_bits & 0x10)
1201
+ host_bits |= float_flag_inexact;
1202
+ if (target_bits & 0x80)
1203
+ host_bits |= float_flag_input_denormal;
1204
+ return host_bits;
1205
+}
1206
+
1207
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
1208
+{
1209
+ int i;
1210
+ uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
1211
+
1212
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
1213
+ if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
1214
+ val &= ~FPCR_FZ16;
1215
+ }
1216
+
1217
+ /*
1218
+ * We don't implement trapped exception handling, so the
1219
+ * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
1220
+ *
1221
+ * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
1222
+ * (which are stored in fp_status), and the other RES0 bits
1223
+ * in between, then we clear all of the low 16 bits.
1224
+ */
1225
+ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
1226
+ env->vfp.vec_len = (val >> 16) & 7;
1227
+ env->vfp.vec_stride = (val >> 20) & 3;
1228
+
1229
+ /*
1230
+ * The bit we set within fpscr_q is arbitrary; the register as a
1231
+ * whole being zero/non-zero is what counts.
1232
+ */
1233
+ env->vfp.qc[0] = val & FPCR_QC;
1234
+ env->vfp.qc[1] = 0;
1235
+ env->vfp.qc[2] = 0;
1236
+ env->vfp.qc[3] = 0;
1237
+
1238
+ changed ^= val;
1239
+ if (changed & (3 << 22)) {
1240
+ i = (val >> 22) & 3;
1241
+ switch (i) {
1242
+ case FPROUNDING_TIEEVEN:
1243
+ i = float_round_nearest_even;
1244
+ break;
1245
+ case FPROUNDING_POSINF:
1246
+ i = float_round_up;
1247
+ break;
1248
+ case FPROUNDING_NEGINF:
1249
+ i = float_round_down;
1250
+ break;
1251
+ case FPROUNDING_ZERO:
1252
+ i = float_round_to_zero;
1253
+ break;
1254
+ }
1255
+ set_float_rounding_mode(i, &env->vfp.fp_status);
1256
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
1257
+ }
1258
+ if (changed & FPCR_FZ16) {
1259
+ bool ftz_enabled = val & FPCR_FZ16;
1260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1261
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1262
+ }
1263
+ if (changed & FPCR_FZ) {
1264
+ bool ftz_enabled = val & FPCR_FZ;
1265
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
1266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
1267
+ }
1268
+ if (changed & FPCR_DN) {
1269
+ bool dnan_enabled = val & FPCR_DN;
1270
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
1271
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
1272
+ }
1273
+
1274
+ /* The exception flags are ORed together when we read fpscr so we
1275
+ * only need to preserve the current state in one of our
1276
+ * float_status values.
1277
+ */
1278
+ i = vfp_exceptbits_to_host(val);
1279
+ set_float_exception_flags(i, &env->vfp.fp_status);
1280
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
1281
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
1282
+}
1283
+
1284
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
1285
+{
1286
+ HELPER(vfp_set_fpscr)(env, val);
1287
+}
1288
+
1289
+#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
1290
+
1291
+#define VFP_BINOP(name) \
1292
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
1293
+{ \
1294
+ float_status *fpst = fpstp; \
1295
+ return float32_ ## name(a, b, fpst); \
1296
+} \
1297
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
1298
+{ \
1299
+ float_status *fpst = fpstp; \
1300
+ return float64_ ## name(a, b, fpst); \
1301
+}
1302
+VFP_BINOP(add)
1303
+VFP_BINOP(sub)
1304
+VFP_BINOP(mul)
1305
+VFP_BINOP(div)
1306
+VFP_BINOP(min)
1307
+VFP_BINOP(max)
1308
+VFP_BINOP(minnum)
1309
+VFP_BINOP(maxnum)
1310
+#undef VFP_BINOP
1311
+
1312
+float32 VFP_HELPER(neg, s)(float32 a)
1313
+{
1314
+ return float32_chs(a);
1315
+}
1316
+
1317
+float64 VFP_HELPER(neg, d)(float64 a)
1318
+{
1319
+ return float64_chs(a);
1320
+}
1321
+
1322
+float32 VFP_HELPER(abs, s)(float32 a)
1323
+{
1324
+ return float32_abs(a);
1325
+}
1326
+
1327
+float64 VFP_HELPER(abs, d)(float64 a)
1328
+{
1329
+ return float64_abs(a);
1330
+}
1331
+
1332
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
1333
+{
1334
+ return float32_sqrt(a, &env->vfp.fp_status);
1335
+}
1336
+
1337
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
1338
+{
1339
+ return float64_sqrt(a, &env->vfp.fp_status);
1340
+}
1341
+
1342
+static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
1343
+{
1344
+ uint32_t flags;
1345
+ switch (cmp) {
1346
+ case float_relation_equal:
1347
+ flags = 0x6;
1348
+ break;
1349
+ case float_relation_less:
1350
+ flags = 0x8;
1351
+ break;
1352
+ case float_relation_greater:
1353
+ flags = 0x2;
1354
+ break;
1355
+ case float_relation_unordered:
1356
+ flags = 0x3;
1357
+ break;
1358
+ default:
1359
+ g_assert_not_reached();
1360
+ }
1361
+ env->vfp.xregs[ARM_VFP_FPSCR] =
1362
+ deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
1363
+}
1364
+
1365
+/* XXX: check quiet/signaling case */
1366
+#define DO_VFP_cmp(p, type) \
1367
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
1368
+{ \
1369
+ softfloat_to_vfp_compare(env, \
1370
+ type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
1371
+} \
1372
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
1373
+{ \
1374
+ softfloat_to_vfp_compare(env, \
1375
+ type ## _compare(a, b, &env->vfp.fp_status)); \
1376
+}
1377
+DO_VFP_cmp(s, float32)
1378
+DO_VFP_cmp(d, float64)
1379
+#undef DO_VFP_cmp
1380
+
1381
+/* Integer to float and float to integer conversions */
1382
+
1383
+#define CONV_ITOF(name, ftype, fsz, sign) \
1384
+ftype HELPER(name)(uint32_t x, void *fpstp) \
1385
+{ \
1386
+ float_status *fpst = fpstp; \
1387
+ return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
1388
+}
1389
+
1390
+#define CONV_FTOI(name, ftype, fsz, sign, round) \
1391
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
1392
+{ \
1393
+ float_status *fpst = fpstp; \
1394
+ if (float##fsz##_is_any_nan(x)) { \
1395
+ float_raise(float_flag_invalid, fpst); \
1396
+ return 0; \
1397
+ } \
1398
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
1399
+}
1400
+
1401
+#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
1402
+ CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
1403
+ CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
1404
+ CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
1405
+
1406
+FLOAT_CONVS(si, h, uint32_t, 16, )
1407
+FLOAT_CONVS(si, s, float32, 32, )
1408
+FLOAT_CONVS(si, d, float64, 64, )
1409
+FLOAT_CONVS(ui, h, uint32_t, 16, u)
1410
+FLOAT_CONVS(ui, s, float32, 32, u)
1411
+FLOAT_CONVS(ui, d, float64, 64, u)
1412
+
1413
+#undef CONV_ITOF
1414
+#undef CONV_FTOI
1415
+#undef FLOAT_CONVS
1416
+
1417
+/* floating point conversion */
1418
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
1419
+{
1420
+ return float32_to_float64(x, &env->vfp.fp_status);
1421
+}
1422
+
1423
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
1424
+{
1425
+ return float64_to_float32(x, &env->vfp.fp_status);
1426
+}
1427
+
1428
+/* VFP3 fixed point conversion. */
1429
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1430
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
1431
+ void *fpstp) \
1432
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
1433
+
1434
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
1435
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
1436
+ void *fpst) \
1437
+{ \
1438
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
1439
+ float_raise(float_flag_invalid, fpst); \
1440
+ return 0; \
1441
+ } \
1442
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
1443
+}
1444
+
1445
+#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
1446
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1447
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1448
+ float_round_to_zero, _round_to_zero) \
1449
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1450
+ get_float_rounding_mode(fpst), )
1451
+
1452
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
1453
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1454
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1455
+ get_float_rounding_mode(fpst), )
1456
+
1457
+VFP_CONV_FIX(sh, d, 64, 64, int16)
1458
+VFP_CONV_FIX(sl, d, 64, 64, int32)
1459
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
1460
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
1461
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
1462
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
1463
+VFP_CONV_FIX(sh, s, 32, 32, int16)
1464
+VFP_CONV_FIX(sl, s, 32, 32, int32)
1465
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
1466
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
1467
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
1468
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
1469
+
1470
+#undef VFP_CONV_FIX
1471
+#undef VFP_CONV_FIX_FLOAT
1472
+#undef VFP_CONV_FLOAT_FIX_ROUND
1473
+#undef VFP_CONV_FIX_A64
1474
+
1475
+uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
1476
+{
1477
+ return int32_to_float16_scalbn(x, -shift, fpst);
1478
+}
1479
+
1480
+uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
1481
+{
1482
+ return uint32_to_float16_scalbn(x, -shift, fpst);
1483
+}
1484
+
1485
+uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
1486
+{
1487
+ return int64_to_float16_scalbn(x, -shift, fpst);
1488
+}
1489
+
1490
+uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
1491
+{
1492
+ return uint64_to_float16_scalbn(x, -shift, fpst);
1493
+}
1494
+
1495
+uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
1496
+{
1497
+ if (unlikely(float16_is_any_nan(x))) {
1498
+ float_raise(float_flag_invalid, fpst);
1499
+ return 0;
1500
+ }
1501
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
1502
+ shift, fpst);
1503
+}
1504
+
1505
+uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
1506
+{
1507
+ if (unlikely(float16_is_any_nan(x))) {
1508
+ float_raise(float_flag_invalid, fpst);
1509
+ return 0;
1510
+ }
1511
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
1512
+ shift, fpst);
1513
+}
1514
+
1515
+uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
1516
+{
1517
+ if (unlikely(float16_is_any_nan(x))) {
1518
+ float_raise(float_flag_invalid, fpst);
1519
+ return 0;
1520
+ }
1521
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
1522
+ shift, fpst);
1523
+}
1524
+
1525
+uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
1526
+{
1527
+ if (unlikely(float16_is_any_nan(x))) {
1528
+ float_raise(float_flag_invalid, fpst);
1529
+ return 0;
1530
+ }
1531
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
1532
+ shift, fpst);
1533
+}
1534
+
1535
+uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
1536
+{
1537
+ if (unlikely(float16_is_any_nan(x))) {
1538
+ float_raise(float_flag_invalid, fpst);
1539
+ return 0;
1540
+ }
1541
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
1542
+ shift, fpst);
1543
+}
1544
+
1545
+uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
1546
+{
1547
+ if (unlikely(float16_is_any_nan(x))) {
1548
+ float_raise(float_flag_invalid, fpst);
1549
+ return 0;
1550
+ }
1551
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
1552
+ shift, fpst);
1553
+}
1554
+
1555
+/* Set the current fp rounding mode and return the old one.
1556
+ * The argument is a softfloat float_round_ value.
1557
+ */
1558
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
1559
+{
1560
+ float_status *fp_status = fpstp;
1561
+
1562
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1563
+ set_float_rounding_mode(rmode, fp_status);
1564
+
1565
+ return prev_rmode;
1566
+}
1567
+
1568
+/* Set the current fp rounding mode in the standard fp status and return
1569
+ * the old one. This is for NEON instructions that need to change the
1570
+ * rounding mode but wish to use the standard FPSCR values for everything
1571
+ * else. Always set the rounding mode back to the correct value after
1572
+ * modifying it.
1573
+ * The argument is a softfloat float_round_ value.
1574
+ */
1575
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
1576
+{
1577
+ float_status *fp_status = &env->vfp.standard_fp_status;
1578
+
1579
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1580
+ set_float_rounding_mode(rmode, fp_status);
1581
+
1582
+ return prev_rmode;
1583
+}
1584
+
1585
+/* Half precision conversions. */
1586
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1587
+{
1588
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1589
+ * it would affect flushing input denormals.
1590
+ */
1591
+ float_status *fpst = fpstp;
1592
+ flag save = get_flush_inputs_to_zero(fpst);
1593
+ set_flush_inputs_to_zero(false, fpst);
1594
+ float32 r = float16_to_float32(a, !ahp_mode, fpst);
1595
+ set_flush_inputs_to_zero(save, fpst);
1596
+ return r;
1597
+}
1598
+
1599
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
1600
+{
1601
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1602
+ * it would affect flushing output denormals.
1603
+ */
1604
+ float_status *fpst = fpstp;
1605
+ flag save = get_flush_to_zero(fpst);
1606
+ set_flush_to_zero(false, fpst);
1607
+ float16 r = float32_to_float16(a, !ahp_mode, fpst);
1608
+ set_flush_to_zero(save, fpst);
1609
+ return r;
1610
+}
1611
+
1612
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1613
+{
1614
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1615
+ * it would affect flushing input denormals.
1616
+ */
1617
+ float_status *fpst = fpstp;
1618
+ flag save = get_flush_inputs_to_zero(fpst);
1619
+ set_flush_inputs_to_zero(false, fpst);
1620
+ float64 r = float16_to_float64(a, !ahp_mode, fpst);
1621
+ set_flush_inputs_to_zero(save, fpst);
1622
+ return r;
1623
+}
1624
+
1625
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
1626
+{
1627
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1628
+ * it would affect flushing output denormals.
1629
+ */
1630
+ float_status *fpst = fpstp;
1631
+ flag save = get_flush_to_zero(fpst);
1632
+ set_flush_to_zero(false, fpst);
1633
+ float16 r = float64_to_float16(a, !ahp_mode, fpst);
1634
+ set_flush_to_zero(save, fpst);
1635
+ return r;
1636
+}
1637
+
1638
+#define float32_two make_float32(0x40000000)
1639
+#define float32_three make_float32(0x40400000)
1640
+#define float32_one_point_five make_float32(0x3fc00000)
1641
+
1642
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
1643
+{
1644
+ float_status *s = &env->vfp.standard_fp_status;
1645
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1646
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1647
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1648
+ float_raise(float_flag_input_denormal, s);
1649
+ }
1650
+ return float32_two;
1651
+ }
1652
+ return float32_sub(float32_two, float32_mul(a, b, s), s);
1653
+}
1654
+
1655
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
1656
+{
1657
+ float_status *s = &env->vfp.standard_fp_status;
1658
+ float32 product;
1659
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1660
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1661
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1662
+ float_raise(float_flag_input_denormal, s);
1663
+ }
1664
+ return float32_one_point_five;
1665
+ }
1666
+ product = float32_mul(a, b, s);
1667
+ return float32_div(float32_sub(float32_three, product, s), float32_two, s);
1668
+}
1669
+
1670
+/* NEON helpers. */
1671
+
1672
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
1673
+ * int->float conversions at run-time. */
1674
+#define float64_256 make_float64(0x4070000000000000LL)
1675
+#define float64_512 make_float64(0x4080000000000000LL)
1676
+#define float16_maxnorm make_float16(0x7bff)
1677
+#define float32_maxnorm make_float32(0x7f7fffff)
1678
+#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
1679
+
1680
+/* Reciprocal functions
1681
+ *
1682
+ * The algorithm that must be used to calculate the estimate
1683
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
1684
+ */
1685
+
1686
+/* See RecipEstimate()
1687
+ *
1688
+ * input is a 9 bit fixed point number
1689
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
1690
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
1691
+ */
1692
+
1693
+static int recip_estimate(int input)
1694
+{
1695
+ int a, b, r;
1696
+ assert(256 <= input && input < 512);
1697
+ a = (input * 2) + 1;
1698
+ b = (1 << 19) / a;
1699
+ r = (b + 1) >> 1;
1700
+ assert(256 <= r && r < 512);
1701
+ return r;
1702
+}
1703
+
1704
+/*
1705
+ * Common wrapper to call recip_estimate
1706
+ *
1707
+ * The parameters are exponent and 64 bit fraction (without implicit
1708
+ * bit) where the binary point is nominally at bit 52. Returns a
1709
+ * float64 which can then be rounded to the appropriate size by the
1710
+ * callee.
1711
+ */
1712
+
1713
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
1714
+{
1715
+ uint32_t scaled, estimate;
1716
+ uint64_t result_frac;
1717
+ int result_exp;
1718
+
1719
+ /* Handle sub-normals */
1720
+ if (*exp == 0) {
1721
+ if (extract64(frac, 51, 1) == 0) {
1722
+ *exp = -1;
1723
+ frac <<= 2;
1724
+ } else {
1725
+ frac <<= 1;
1726
+ }
1727
+ }
1728
+
1729
+ /* scaled = UInt('1':fraction<51:44>) */
1730
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1731
+ estimate = recip_estimate(scaled);
1732
+
1733
+ result_exp = exp_off - *exp;
1734
+ result_frac = deposit64(0, 44, 8, estimate);
1735
+ if (result_exp == 0) {
1736
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
1737
+ } else if (result_exp == -1) {
1738
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
1739
+ result_exp = 0;
1740
+ }
1741
+
1742
+ *exp = result_exp;
1743
+
1744
+ return result_frac;
1745
+}
1746
+
1747
+static bool round_to_inf(float_status *fpst, bool sign_bit)
1748
+{
1749
+ switch (fpst->float_rounding_mode) {
1750
+ case float_round_nearest_even: /* Round to Nearest */
1751
+ return true;
1752
+ case float_round_up: /* Round to +Inf */
1753
+ return !sign_bit;
1754
+ case float_round_down: /* Round to -Inf */
1755
+ return sign_bit;
1756
+ case float_round_to_zero: /* Round to Zero */
30
+ return false;
1757
+ return false;
31
+ }
1758
+ }
32
+
1759
+
33
*phys_ptr = address;
1760
+ g_assert_not_reached();
34
for (n = 7; n >= 0; n--) {
1761
+}
35
base = env->cp15.c6_region[n];
1762
+
36
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
1763
+uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
37
}
1764
+{
38
}
1765
+ float_status *fpst = fpstp;
39
1766
+ float16 f16 = float16_squash_input_denormal(input, fpst);
40
- /* pmsav7 has special handling for when MPU is disabled so call it before
1767
+ uint32_t f16_val = float16_val(f16);
41
- * the common MMU/MPU disabled check below.
1768
+ uint32_t f16_sign = float16_is_neg(f16);
42
- */
1769
+ int f16_exp = extract32(f16_val, 10, 5);
43
- if (arm_feature(env, ARM_FEATURE_PMSA) &&
1770
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
44
- arm_feature(env, ARM_FEATURE_V7)) {
1771
+ uint64_t f64_frac;
45
+ if (arm_feature(env, ARM_FEATURE_PMSA)) {
1772
+
46
bool ret;
1773
+ if (float16_is_any_nan(f16)) {
47
*page_size = TARGET_PAGE_SIZE;
1774
+ float16 nan = f16;
48
- ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
1775
+ if (float16_is_signaling_nan(f16, fpst)) {
49
- phys_ptr, prot, fsr);
1776
+ float_raise(float_flag_invalid, fpst);
50
- qemu_log_mask(CPU_LOG_MMU, "PMSAv7 MPU lookup for %s at 0x%08" PRIx32
1777
+ nan = float16_silence_nan(f16, fpst);
51
+
1778
+ }
52
+ if (arm_feature(env, ARM_FEATURE_V7)) {
1779
+ if (fpst->default_nan_mode) {
53
+ /* PMSAv7 */
1780
+ nan = float16_default_nan(fpst);
54
+ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
1781
+ }
55
+ phys_ptr, prot, fsr);
1782
+ return nan;
1783
+ } else if (float16_is_infinity(f16)) {
1784
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1785
+ } else if (float16_is_zero(f16)) {
1786
+ float_raise(float_flag_divbyzero, fpst);
1787
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
1788
+ } else if (float16_abs(f16) < (1 << 8)) {
1789
+ /* Abs(value) < 2.0^-16 */
1790
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1791
+ if (round_to_inf(fpst, f16_sign)) {
1792
+ return float16_set_sign(float16_infinity, f16_sign);
56
+ } else {
1793
+ } else {
57
+ /* Pre-v7 MPU */
1794
+ return float16_set_sign(float16_maxnorm, f16_sign);
58
+ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
59
+ phys_ptr, prot, fsr);
60
+ }
1795
+ }
61
+ qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32
1796
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
62
" mmu_idx %u -> %s (prot %c%c%c)\n",
1797
+ float_raise(float_flag_underflow, fpst);
63
access_type == MMU_DATA_LOAD ? "reading" :
1798
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
64
(access_type == MMU_DATA_STORE ? "writing" : "execute"),
1799
+ }
65
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
1800
+
66
return ret;
1801
+ f64_frac = call_recip_estimate(&f16_exp, 29,
67
}
1802
+ ((uint64_t) f16_frac) << (52 - 10));
68
1803
+
69
+ /* Definitely a real MMU, not an MPU */
1804
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
70
+
1805
+ f16_val = deposit32(0, 15, 1, f16_sign);
71
if (regime_translation_disabled(env, mmu_idx)) {
1806
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
72
- /* MMU/MPU disabled. */
1807
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
73
+ /* MMU disabled. */
1808
+ return make_float16(f16_val);
74
*phys_ptr = address;
1809
+}
75
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1810
+
76
*page_size = TARGET_PAGE_SIZE;
1811
+float32 HELPER(recpe_f32)(float32 input, void *fpstp)
77
return 0;
1812
+{
78
}
1813
+ float_status *fpst = fpstp;
79
1814
+ float32 f32 = float32_squash_input_denormal(input, fpst);
80
- if (arm_feature(env, ARM_FEATURE_PMSA)) {
1815
+ uint32_t f32_val = float32_val(f32);
81
- /* Pre-v7 MPU */
1816
+ bool f32_sign = float32_is_neg(f32);
82
- *page_size = TARGET_PAGE_SIZE;
1817
+ int f32_exp = extract32(f32_val, 23, 8);
83
- return get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
1818
+ uint32_t f32_frac = extract32(f32_val, 0, 23);
84
- phys_ptr, prot, fsr);
1819
+ uint64_t f64_frac;
85
- }
1820
+
86
-
1821
+ if (float32_is_any_nan(f32)) {
87
if (regime_using_lpae_format(env, mmu_idx)) {
1822
+ float32 nan = f32;
88
return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
1823
+ if (float32_is_signaling_nan(f32, fpst)) {
89
attrs, prot, page_size, fsr, fi);
1824
+ float_raise(float_flag_invalid, fpst);
1825
+ nan = float32_silence_nan(f32, fpst);
1826
+ }
1827
+ if (fpst->default_nan_mode) {
1828
+ nan = float32_default_nan(fpst);
1829
+ }
1830
+ return nan;
1831
+ } else if (float32_is_infinity(f32)) {
1832
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1833
+ } else if (float32_is_zero(f32)) {
1834
+ float_raise(float_flag_divbyzero, fpst);
1835
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
1836
+ } else if (float32_abs(f32) < (1ULL << 21)) {
1837
+ /* Abs(value) < 2.0^-128 */
1838
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1839
+ if (round_to_inf(fpst, f32_sign)) {
1840
+ return float32_set_sign(float32_infinity, f32_sign);
1841
+ } else {
1842
+ return float32_set_sign(float32_maxnorm, f32_sign);
1843
+ }
1844
+ } else if (f32_exp >= 253 && fpst->flush_to_zero) {
1845
+ float_raise(float_flag_underflow, fpst);
1846
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1847
+ }
1848
+
1849
+ f64_frac = call_recip_estimate(&f32_exp, 253,
1850
+ ((uint64_t) f32_frac) << (52 - 23));
1851
+
1852
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
1853
+ f32_val = deposit32(0, 31, 1, f32_sign);
1854
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
1855
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
1856
+ return make_float32(f32_val);
1857
+}
1858
+
1859
+float64 HELPER(recpe_f64)(float64 input, void *fpstp)
1860
+{
1861
+ float_status *fpst = fpstp;
1862
+ float64 f64 = float64_squash_input_denormal(input, fpst);
1863
+ uint64_t f64_val = float64_val(f64);
1864
+ bool f64_sign = float64_is_neg(f64);
1865
+ int f64_exp = extract64(f64_val, 52, 11);
1866
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
1867
+
1868
+ /* Deal with any special cases */
1869
+ if (float64_is_any_nan(f64)) {
1870
+ float64 nan = f64;
1871
+ if (float64_is_signaling_nan(f64, fpst)) {
1872
+ float_raise(float_flag_invalid, fpst);
1873
+ nan = float64_silence_nan(f64, fpst);
1874
+ }
1875
+ if (fpst->default_nan_mode) {
1876
+ nan = float64_default_nan(fpst);
1877
+ }
1878
+ return nan;
1879
+ } else if (float64_is_infinity(f64)) {
1880
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1881
+ } else if (float64_is_zero(f64)) {
1882
+ float_raise(float_flag_divbyzero, fpst);
1883
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
1884
+ } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1885
+ /* Abs(value) < 2.0^-1024 */
1886
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1887
+ if (round_to_inf(fpst, f64_sign)) {
1888
+ return float64_set_sign(float64_infinity, f64_sign);
1889
+ } else {
1890
+ return float64_set_sign(float64_maxnorm, f64_sign);
1891
+ }
1892
+ } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1893
+ float_raise(float_flag_underflow, fpst);
1894
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1895
+ }
1896
+
1897
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
1898
+
1899
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
1900
+ f64_val = deposit64(0, 63, 1, f64_sign);
1901
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
1902
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
1903
+ return make_float64(f64_val);
1904
+}
1905
+
1906
+/* The algorithm that must be used to calculate the estimate
1907
+ * is specified by the ARM ARM.
1908
+ */
1909
+
1910
+static int do_recip_sqrt_estimate(int a)
1911
+{
1912
+ int b, estimate;
1913
+
1914
+ assert(128 <= a && a < 512);
1915
+ if (a < 256) {
1916
+ a = a * 2 + 1;
1917
+ } else {
1918
+ a = (a >> 1) << 1;
1919
+ a = (a + 1) * 2;
1920
+ }
1921
+ b = 512;
1922
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
1923
+ b += 1;
1924
+ }
1925
+ estimate = (b + 1) / 2;
1926
+ assert(256 <= estimate && estimate < 512);
1927
+
1928
+ return estimate;
1929
+}
1930
+
1931
+
1932
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
1933
+{
1934
+ int estimate;
1935
+ uint32_t scaled;
1936
+
1937
+ if (*exp == 0) {
1938
+ while (extract64(frac, 51, 1) == 0) {
1939
+ frac = frac << 1;
1940
+ *exp -= 1;
1941
+ }
1942
+ frac = extract64(frac, 0, 51) << 1;
1943
+ }
1944
+
1945
+ if (*exp & 1) {
1946
+ /* scaled = UInt('01':fraction<51:45>) */
1947
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1948
+ } else {
1949
+ /* scaled = UInt('1':fraction<51:44>) */
1950
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1951
+ }
1952
+ estimate = do_recip_sqrt_estimate(scaled);
1953
+
1954
+ *exp = (exp_off - *exp) / 2;
1955
+ return extract64(estimate, 0, 8) << 44;
1956
+}
1957
+
1958
+uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
1959
+{
1960
+ float_status *s = fpstp;
1961
+ float16 f16 = float16_squash_input_denormal(input, s);
1962
+ uint16_t val = float16_val(f16);
1963
+ bool f16_sign = float16_is_neg(f16);
1964
+ int f16_exp = extract32(val, 10, 5);
1965
+ uint16_t f16_frac = extract32(val, 0, 10);
1966
+ uint64_t f64_frac;
1967
+
1968
+ if (float16_is_any_nan(f16)) {
1969
+ float16 nan = f16;
1970
+ if (float16_is_signaling_nan(f16, s)) {
1971
+ float_raise(float_flag_invalid, s);
1972
+ nan = float16_silence_nan(f16, s);
1973
+ }
1974
+ if (s->default_nan_mode) {
1975
+ nan = float16_default_nan(s);
1976
+ }
1977
+ return nan;
1978
+ } else if (float16_is_zero(f16)) {
1979
+ float_raise(float_flag_divbyzero, s);
1980
+ return float16_set_sign(float16_infinity, f16_sign);
1981
+ } else if (f16_sign) {
1982
+ float_raise(float_flag_invalid, s);
1983
+ return float16_default_nan(s);
1984
+ } else if (float16_is_infinity(f16)) {
1985
+ return float16_zero;
1986
+ }
1987
+
1988
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1989
+ * preserving the parity of the exponent. */
1990
+
1991
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1992
+
1993
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
1994
+
1995
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1996
+ val = deposit32(0, 15, 1, f16_sign);
1997
+ val = deposit32(val, 10, 5, f16_exp);
1998
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1999
+ return make_float16(val);
2000
+}
2001
+
2002
+float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
2003
+{
2004
+ float_status *s = fpstp;
2005
+ float32 f32 = float32_squash_input_denormal(input, s);
2006
+ uint32_t val = float32_val(f32);
2007
+ uint32_t f32_sign = float32_is_neg(f32);
2008
+ int f32_exp = extract32(val, 23, 8);
2009
+ uint32_t f32_frac = extract32(val, 0, 23);
2010
+ uint64_t f64_frac;
2011
+
2012
+ if (float32_is_any_nan(f32)) {
2013
+ float32 nan = f32;
2014
+ if (float32_is_signaling_nan(f32, s)) {
2015
+ float_raise(float_flag_invalid, s);
2016
+ nan = float32_silence_nan(f32, s);
2017
+ }
2018
+ if (s->default_nan_mode) {
2019
+ nan = float32_default_nan(s);
2020
+ }
2021
+ return nan;
2022
+ } else if (float32_is_zero(f32)) {
2023
+ float_raise(float_flag_divbyzero, s);
2024
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
2025
+ } else if (float32_is_neg(f32)) {
2026
+ float_raise(float_flag_invalid, s);
2027
+ return float32_default_nan(s);
2028
+ } else if (float32_is_infinity(f32)) {
2029
+ return float32_zero;
2030
+ }
2031
+
2032
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
2033
+ * preserving the parity of the exponent. */
2034
+
2035
+ f64_frac = ((uint64_t) f32_frac) << 29;
2036
+
2037
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
2038
+
2039
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
2040
+ val = deposit32(0, 31, 1, f32_sign);
2041
+ val = deposit32(val, 23, 8, f32_exp);
2042
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
2043
+ return make_float32(val);
2044
+}
2045
+
2046
+float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
2047
+{
2048
+ float_status *s = fpstp;
2049
+ float64 f64 = float64_squash_input_denormal(input, s);
2050
+ uint64_t val = float64_val(f64);
2051
+ bool f64_sign = float64_is_neg(f64);
2052
+ int f64_exp = extract64(val, 52, 11);
2053
+ uint64_t f64_frac = extract64(val, 0, 52);
2054
+
2055
+ if (float64_is_any_nan(f64)) {
2056
+ float64 nan = f64;
2057
+ if (float64_is_signaling_nan(f64, s)) {
2058
+ float_raise(float_flag_invalid, s);
2059
+ nan = float64_silence_nan(f64, s);
2060
+ }
2061
+ if (s->default_nan_mode) {
2062
+ nan = float64_default_nan(s);
2063
+ }
2064
+ return nan;
2065
+ } else if (float64_is_zero(f64)) {
2066
+ float_raise(float_flag_divbyzero, s);
2067
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
2068
+ } else if (float64_is_neg(f64)) {
2069
+ float_raise(float_flag_invalid, s);
2070
+ return float64_default_nan(s);
2071
+ } else if (float64_is_infinity(f64)) {
2072
+ return float64_zero;
2073
+ }
2074
+
2075
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
2076
+
2077
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
2078
+ val = deposit64(0, 61, 1, f64_sign);
2079
+ val = deposit64(val, 52, 11, f64_exp);
2080
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
2081
+ return make_float64(val);
2082
+}
2083
+
2084
+uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
2085
+{
2086
+ /* float_status *s = fpstp; */
2087
+ int input, estimate;
2088
+
2089
+ if ((a & 0x80000000) == 0) {
2090
+ return 0xffffffff;
2091
+ }
2092
+
2093
+ input = extract32(a, 23, 9);
2094
+ estimate = recip_estimate(input);
2095
+
2096
+ return deposit32(0, (32 - 9), 9, estimate);
2097
+}
2098
+
2099
+uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
2100
+{
2101
+ int estimate;
2102
+
2103
+ if ((a & 0xc0000000) == 0) {
2104
+ return 0xffffffff;
2105
+ }
2106
+
2107
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
2108
+
2109
+ return deposit32(0, 23, 9, estimate);
2110
+}
2111
+
2112
+/* VFPv4 fused multiply-accumulate */
2113
+float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
2114
+{
2115
+ float_status *fpst = fpstp;
2116
+ return float32_muladd(a, b, c, 0, fpst);
2117
+}
2118
+
2119
+float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
2120
+{
2121
+ float_status *fpst = fpstp;
2122
+ return float64_muladd(a, b, c, 0, fpst);
2123
+}
2124
+
2125
+/* ARMv8 round to integral */
2126
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
2127
+{
2128
+ return float32_round_to_int(x, fp_status);
2129
+}
2130
+
2131
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
2132
+{
2133
+ return float64_round_to_int(x, fp_status);
2134
+}
2135
+
2136
+float32 HELPER(rints)(float32 x, void *fp_status)
2137
+{
2138
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2139
+ float32 ret;
2140
+
2141
+ ret = float32_round_to_int(x, fp_status);
2142
+
2143
+ /* Suppress any inexact exceptions the conversion produced */
2144
+ if (!(old_flags & float_flag_inexact)) {
2145
+ new_flags = get_float_exception_flags(fp_status);
2146
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2147
+ }
2148
+
2149
+ return ret;
2150
+}
2151
+
2152
+float64 HELPER(rintd)(float64 x, void *fp_status)
2153
+{
2154
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2155
+ float64 ret;
2156
+
2157
+ ret = float64_round_to_int(x, fp_status);
2158
+
2159
+ new_flags = get_float_exception_flags(fp_status);
2160
+
2161
+ /* Suppress any inexact exceptions the conversion produced */
2162
+ if (!(old_flags & float_flag_inexact)) {
2163
+ new_flags = get_float_exception_flags(fp_status);
2164
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2165
+ }
2166
+
2167
+ return ret;
2168
+}
2169
+
2170
+/* Convert ARM rounding mode to softfloat */
2171
+int arm_rmode_to_sf(int rmode)
2172
+{
2173
+ switch (rmode) {
2174
+ case FPROUNDING_TIEAWAY:
2175
+ rmode = float_round_ties_away;
2176
+ break;
2177
+ case FPROUNDING_ODD:
2178
+ /* FIXME: add support for TIEAWAY and ODD */
2179
+ qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
2180
+ rmode);
2181
+ /* fall through for now */
2182
+ case FPROUNDING_TIEEVEN:
2183
+ default:
2184
+ rmode = float_round_nearest_even;
2185
+ break;
2186
+ case FPROUNDING_POSINF:
2187
+ rmode = float_round_up;
2188
+ break;
2189
+ case FPROUNDING_NEGINF:
2190
+ rmode = float_round_down;
2191
+ break;
2192
+ case FPROUNDING_ZERO:
2193
+ rmode = float_round_to_zero;
2194
+ break;
2195
+ }
2196
+ return rmode;
2197
+}
90
--
2198
--
91
2.7.4
2199
2.20.1
92
2200
93
2201
diff view generated by jsdifflib
1
Tighten up the T32 decoder in the places where new v8M instructions
1
From: Richard Henderson <richard.henderson@linaro.org>
2
will be:
2
3
* TT/TTT/TTA/TTAT are in what was nominally LDREX/STREX r15, ...
3
There are lots of special cases within these insns. Split the
4
which is UNPREDICTABLE:
4
major argument decode/loading/saving into no_output (compares),
5
make the UNPREDICTABLE behaviour be to UNDEF
5
rd_is_dp, and rm_is_dp.
6
* BXNS/BLXNS are distinguished from BX/BLX via the low 3 bits,
6
7
which in previous architectural versions are SBZ:
7
We still need to special case argument load for compare (rd as
8
enforce the SBZ via UNDEF rather than ignoring it, and move
8
input, rm as zero) and vcvt fixed (rd as input+output), but lots
9
the "ARCH(5)" UNDEF case up so we don't leak a TCG temporary
9
of special cases do disappear.
10
* SG is in the encoding which would be LDRD/STRD with rn = r15;
10
11
this is UNPREDICTABLE and we currently UNDEF:
11
Now that we have a full switch at the beginning, hoist the ISA
12
move this check further up the code so that we don't leak
12
checks from the code generation.
13
TCG temporaries in the UNDEF case and have a better place
13
14
to put the SG decode.
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
15
Message-id: 20190215192302.27855-4-richard.henderson@linaro.org
16
This means that if a v8M binary is accidentally run on v7M
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
or if a test case hits something that we haven't implemented
18
yet the behaviour will be obvious (UNDEF) rather than obscure
19
(plough on treating it as a different instruction).
20
21
In the process, add some comments about the instruction patterns
22
at these points in the decode. Our Thumb and ARM decoders are
23
very difficult to understand currently, but gradually adding
24
comments like this should help to clarify what exactly has
25
been decoded when.
26
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Message-id: 1501692241-23310-5-git-send-email-peter.maydell@linaro.org
31
---
18
---
32
target/arm/translate.c | 48 +++++++++++++++++++++++++++++++++++++++---------
19
target/arm/translate.c | 227 ++++++++++++++++++++---------------------
33
1 file changed, 39 insertions(+), 9 deletions(-)
20
1 file changed, 111 insertions(+), 116 deletions(-)
34
21
35
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/target/arm/translate.c b/target/arm/translate.c
36
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate.c
24
--- a/target/arm/translate.c
38
+++ b/target/arm/translate.c
25
+++ b/target/arm/translate.c
39
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
26
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
40
abort();
27
}
41
case 4:
28
} else {
42
if (insn & (1 << 22)) {
29
/* data processing */
43
- /* Other load/store, table branch. */
30
+ bool rd_is_dp = dp;
44
+ /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
31
+ bool rm_is_dp = dp;
45
+ * - load/store doubleword, load/store exclusive, ldacq/strel,
32
+ bool no_output = false;
46
+ * table branch.
33
+
47
+ */
34
/* The opcode is in bits 23, 21, 20 and 6. */
48
if (insn & 0x01200000) {
35
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
49
- /* Load/store doubleword. */
36
- if (dp) {
50
+ /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
37
- if (op == 15) {
51
+ * - load/store dual (post-indexed)
38
- /* rn is opcode */
52
+ * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
39
- rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
53
+ * - load/store dual (literal and immediate)
40
- } else {
54
+ * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
41
- /* rn is register number */
55
+ * - load/store dual (pre-indexed)
42
- VFP_DREG_N(rn, insn);
56
+ */
43
- }
57
if (rn == 15) {
44
+ rn = VFP_SREG_N(insn);
58
+ if (insn & (1 << 21)) {
45
59
+ /* UNPREDICTABLE */
46
- if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
60
+ goto illegal_op;
47
- ((rn & 0x1e) == 0x6))) {
48
- /* Integer or single/half precision destination. */
49
- rd = VFP_SREG_D(insn);
50
- } else {
51
- VFP_DREG_D(rd, insn);
52
- }
53
- if (op == 15 &&
54
- (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
55
- ((rn & 0x1e) == 0x4))) {
56
- /* VCVT from int or half precision is always from S reg
57
- * regardless of dp bit. VCVT with immediate frac_bits
58
- * has same format as SREG_M.
59
+ if (op == 15) {
60
+ /* rn is opcode, encoded as per VFP_SREG_N. */
61
+ switch (rn) {
62
+ case 0x00: /* vmov */
63
+ case 0x01: /* vabs */
64
+ case 0x02: /* vneg */
65
+ case 0x03: /* vsqrt */
66
+ break;
67
+
68
+ case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
69
+ case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
70
+ /*
71
+ * VCVTB, VCVTT: only present with the halfprec extension
72
+ * UNPREDICTABLE if bit 8 is set prior to ARMv8
73
+ * (we choose to UNDEF)
74
*/
75
- rm = VFP_SREG_M(insn);
76
- } else {
77
- VFP_DREG_M(rm, insn);
78
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
79
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
80
+ return 1;
61
+ }
81
+ }
62
addr = tcg_temp_new_i32();
82
+ rm_is_dp = false;
63
tcg_gen_movi_i32(addr, s->pc & ~3);
83
+ break;
64
} else {
84
+ case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
65
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
85
+ case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
86
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
87
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
88
+ return 1;
89
+ }
90
+ rd_is_dp = false;
91
+ break;
92
+
93
+ case 0x08: case 0x0a: /* vcmp, vcmpz */
94
+ case 0x09: case 0x0b: /* vcmpe, vcmpez */
95
+ no_output = true;
96
+ break;
97
+
98
+ case 0x0c: /* vrintr */
99
+ case 0x0d: /* vrintz */
100
+ case 0x0e: /* vrintx */
101
+ break;
102
+
103
+ case 0x0f: /* vcvt double<->single */
104
+ rd_is_dp = !dp;
105
+ break;
106
+
107
+ case 0x10: /* vcvt.fxx.u32 */
108
+ case 0x11: /* vcvt.fxx.s32 */
109
+ rm_is_dp = false;
110
+ break;
111
+ case 0x18: /* vcvtr.u32.fxx */
112
+ case 0x19: /* vcvtz.u32.fxx */
113
+ case 0x1a: /* vcvtr.s32.fxx */
114
+ case 0x1b: /* vcvtz.s32.fxx */
115
+ rd_is_dp = false;
116
+ break;
117
+
118
+ case 0x14: /* vcvt fp <-> fixed */
119
+ case 0x15:
120
+ case 0x16:
121
+ case 0x17:
122
+ case 0x1c:
123
+ case 0x1d:
124
+ case 0x1e:
125
+ case 0x1f:
126
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
127
+ return 1;
128
+ }
129
+ /* Immediate frac_bits has same format as SREG_M. */
130
+ rm_is_dp = false;
131
+ break;
132
+
133
+ default:
134
+ return 1;
66
}
135
}
67
if (insn & (1 << 21)) {
136
+ } else if (dp) {
68
/* Base writeback. */
137
+ /* rn is register number */
69
- if (rn == 15)
138
+ VFP_DREG_N(rn, insn);
70
- goto illegal_op;
139
+ }
71
tcg_gen_addi_i32(addr, addr, offset - 4);
140
+
72
store_reg(s, rn, addr);
141
+ if (rd_is_dp) {
73
} else {
142
+ VFP_DREG_D(rd, insn);
74
tcg_temp_free_i32(addr);
143
+ } else {
144
+ rd = VFP_SREG_D(insn);
145
+ }
146
+ if (rm_is_dp) {
147
+ VFP_DREG_M(rm, insn);
148
} else {
149
- rn = VFP_SREG_N(insn);
150
- if (op == 15 && rn == 15) {
151
- /* Double precision destination. */
152
- VFP_DREG_D(rd, insn);
153
- } else {
154
- rd = VFP_SREG_D(insn);
155
- }
156
- /* NB that we implicitly rely on the encoding for the frac_bits
157
- * in VCVT of fixed to float being the same as that of an SREG_M
158
- */
159
rm = VFP_SREG_M(insn);
160
}
161
162
veclen = s->vec_len;
163
- if (op == 15 && rn > 3)
164
+ if (op == 15 && rn > 3) {
165
veclen = 0;
166
+ }
167
168
/* Shut up compiler warnings. */
169
delta_m = 0;
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
171
/* Load the initial operands. */
172
if (op == 15) {
173
switch (rn) {
174
- case 16:
175
- case 17:
176
- /* Integer source */
177
- gen_mov_F0_vreg(0, rm);
178
- break;
179
- case 8:
180
- case 9:
181
- /* Compare */
182
+ case 0x08: case 0x09: /* Compare */
183
gen_mov_F0_vreg(dp, rd);
184
gen_mov_F1_vreg(dp, rm);
185
break;
186
- case 10:
187
- case 11:
188
- /* Compare with zero */
189
+ case 0x0a: case 0x0b: /* Compare with zero */
190
gen_mov_F0_vreg(dp, rd);
191
gen_vfp_F1_ld0(dp);
192
break;
193
- case 20:
194
- case 21:
195
- case 22:
196
- case 23:
197
- case 28:
198
- case 29:
199
- case 30:
200
- case 31:
201
+ case 0x14: /* vcvt fp <-> fixed */
202
+ case 0x15:
203
+ case 0x16:
204
+ case 0x17:
205
+ case 0x1c:
206
+ case 0x1d:
207
+ case 0x1e:
208
+ case 0x1f:
209
/* Source and destination the same. */
210
gen_mov_F0_vreg(dp, rd);
211
break;
212
- case 4:
213
- case 5:
214
- case 6:
215
- case 7:
216
- /* VCVTB, VCVTT: only present with the halfprec extension
217
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
218
- * (we choose to UNDEF)
219
- */
220
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
221
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
222
- return 1;
223
- }
224
- if (!extract32(rn, 1, 1)) {
225
- /* Half precision source. */
226
- gen_mov_F0_vreg(0, rm);
227
- break;
228
- }
229
- /* Otherwise fall through */
230
default:
231
/* One source operand. */
232
- gen_mov_F0_vreg(dp, rm);
233
+ gen_mov_F0_vreg(rm_is_dp, rm);
234
break;
75
}
235
}
76
} else if ((insn & (1 << 23)) == 0) {
236
} else {
77
- /* Load/store exclusive word. */
237
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
78
+ /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
238
break;
79
+ * - load/store exclusive word
239
}
80
+ */
240
case 15: /* single<->double conversion */
81
+ if (rs == 15) {
241
- if (dp)
82
+ goto illegal_op;
242
+ if (dp) {
243
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
244
- else
245
+ } else {
246
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
247
+ }
248
break;
249
case 16: /* fuito */
250
gen_vfp_uito(dp, 0);
251
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
252
gen_vfp_sito(dp, 0);
253
break;
254
case 20: /* fshto */
255
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
256
- return 1;
257
- }
258
gen_vfp_shto(dp, 16 - rm, 0);
259
break;
260
case 21: /* fslto */
261
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
262
- return 1;
263
- }
264
gen_vfp_slto(dp, 32 - rm, 0);
265
break;
266
case 22: /* fuhto */
267
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
268
- return 1;
269
- }
270
gen_vfp_uhto(dp, 16 - rm, 0);
271
break;
272
case 23: /* fulto */
273
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
274
- return 1;
275
- }
276
gen_vfp_ulto(dp, 32 - rm, 0);
277
break;
278
case 24: /* ftoui */
279
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
280
gen_vfp_tosiz(dp, 0);
281
break;
282
case 28: /* ftosh */
283
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
284
- return 1;
285
- }
286
gen_vfp_tosh(dp, 16 - rm, 0);
287
break;
288
case 29: /* ftosl */
289
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
290
- return 1;
291
- }
292
gen_vfp_tosl(dp, 32 - rm, 0);
293
break;
294
case 30: /* ftouh */
295
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
296
- return 1;
297
- }
298
gen_vfp_touh(dp, 16 - rm, 0);
299
break;
300
case 31: /* ftoul */
301
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
302
- return 1;
303
- }
304
gen_vfp_toul(dp, 32 - rm, 0);
305
break;
306
default: /* undefined */
307
- return 1;
308
+ g_assert_not_reached();
309
}
310
break;
311
default: /* undefined */
312
return 1;
313
}
314
315
- /* Write back the result. */
316
- if (op == 15 && (rn >= 8 && rn <= 11)) {
317
- /* Comparison, do nothing. */
318
- } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
319
- (rn & 0x1e) == 0x6)) {
320
- /* VCVT double to int: always integer result.
321
- * VCVT double to half precision is always a single
322
- * precision result.
323
- */
324
- gen_mov_vreg_F0(0, rd);
325
- } else if (op == 15 && rn == 15) {
326
- /* conversion */
327
- gen_mov_vreg_F0(!dp, rd);
328
- } else {
329
- gen_mov_vreg_F0(dp, rd);
330
+ /* Write back the result, if any. */
331
+ if (!no_output) {
332
+ gen_mov_vreg_F0(rd_is_dp, rd);
333
}
334
335
/* break out of the loop if we have finished */
336
- if (veclen == 0)
337
+ if (veclen == 0) {
338
break;
83
+ }
339
+ }
84
addr = tcg_temp_local_new_i32();
340
85
load_reg_var(s, addr, rn);
341
if (op == 15 && delta_m == 0) {
86
tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
342
/* single source one-many */
87
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
88
break;
89
}
90
if (insn & (1 << 10)) {
91
- /* data processing extended or blx */
92
+ /* 0b0100_01xx_xxxx_xxxx
93
+ * - data processing extended, branch and exchange
94
+ */
95
rd = (insn & 7) | ((insn >> 4) & 8);
96
rm = (insn >> 3) & 0xf;
97
op = (insn >> 8) & 3;
98
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
99
tmp = load_reg(s, rm);
100
store_reg(s, rd, tmp);
101
break;
102
- case 3:/* branch [and link] exchange thumb register */
103
- tmp = load_reg(s, rm);
104
- if (insn & (1 << 7)) {
105
+ case 3:
106
+ {
107
+ /* 0b0100_0111_xxxx_xxxx
108
+ * - branch [and link] exchange thumb register
109
+ */
110
+ bool link = insn & (1 << 7);
111
+
112
+ if (insn & 7) {
113
+ goto undef;
114
+ }
115
+ if (link) {
116
ARCH(5);
117
+ }
118
+ tmp = load_reg(s, rm);
119
+ if (link) {
120
val = (uint32_t)s->pc | 1;
121
tmp2 = tcg_temp_new_i32();
122
tcg_gen_movi_i32(tmp2, val);
123
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
124
}
125
break;
126
}
127
+ }
128
break;
129
}
130
131
--
343
--
132
2.7.4
344
2.20.1
133
345
134
346
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Mimicking gicv3-maintenance-interrupt, add the PMU's interrupt to
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
CPU state.
4
Message-id: 20190215192302.27855-5-richard.henderson@linaro.org
5
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1500471597-2517-2-git-send-email-drjones@redhat.com
6
[PMM: fixed a couple of comment typos]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
target/arm/cpu.h | 2 ++
9
target/arm/cpu.h | 10 +++++
12
hw/arm/virt.c | 3 +++
10
target/arm/helper.h | 3 ++
13
target/arm/cpu.c | 2 ++
11
target/arm/cpu.c | 1 +
14
3 files changed, 7 insertions(+)
12
target/arm/cpu64.c | 2 +
13
target/arm/translate-a64.c | 26 +++++++++++
14
target/arm/translate.c | 10 +++++
15
target/arm/vfp_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
16
7 files changed, 140 insertions(+)
15
17
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
20
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
21
qemu_irq gt_timer_outputs[NUM_GTIMERS];
23
return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
22
/* GPIO output for GICv3 maintenance interrupt signal */
24
}
23
qemu_irq gicv3_maintenance_interrupt;
25
24
+ /* GPIO output for the PMU interrupt */
26
+static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
25
+ qemu_irq pmu_interrupt;
27
+{
26
28
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
27
/* MemoryRegion to use for secure physical accesses */
29
+}
28
MemoryRegion *secure_memory;
30
+
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
31
static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
30
index XXXXXXX..XXXXXXX 100644
32
{
31
--- a/hw/arm/virt.c
33
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
32
+++ b/hw/arm/virt.c
34
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
33
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
35
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
34
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
36
}
35
qdev_get_gpio_in(gicdev, ppibase
37
36
+ ARCH_GICV3_MAINT_IRQ));
38
+static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
37
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
39
+{
38
+ qdev_get_gpio_in(gicdev, ppibase
40
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
39
+ + VIRTUAL_PMU_IRQ));
41
+}
40
42
+
41
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
43
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
42
sysbus_connect_irq(gicbusdev, i + smp_cpus,
44
{
45
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
46
diff --git a/target/arm/helper.h b/target/arm/helper.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/helper.h
49
+++ b/target/arm/helper.h
50
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
51
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
52
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
53
54
+DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
55
+DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
56
+
57
/* neon_helper.c */
58
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
59
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
43
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
44
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/cpu.c
62
--- a/target/arm/cpu.c
46
+++ b/target/arm/cpu.c
63
+++ b/target/arm/cpu.c
47
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
64
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
48
65
cpu->isar.id_isar5 = t;
49
qdev_init_gpio_out_named(DEVICE(cpu), &cpu->gicv3_maintenance_interrupt,
66
50
"gicv3-maintenance-interrupt", 1);
67
t = cpu->isar.id_isar6;
51
+ qdev_init_gpio_out_named(DEVICE(cpu), &cpu->pmu_interrupt,
68
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
52
+ "pmu-interrupt", 1);
69
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
53
#endif
70
cpu->isar.id_isar6 = t;
54
71
55
/* DTB consumers generally don't in fact care what the 'compatible'
72
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/cpu64.c
75
+++ b/target/arm/cpu64.c
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
77
cpu->isar.id_aa64isar0 = t;
78
79
t = cpu->isar.id_aa64isar1;
80
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
81
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
82
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
83
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
84
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
85
cpu->isar.id_isar5 = u;
86
87
u = cpu->isar.id_isar6;
88
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
89
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
90
cpu->isar.id_isar6 = u;
91
92
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-a64.c
95
+++ b/target/arm/translate-a64.c
96
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
97
}
98
}
99
100
+static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
101
+{
102
+ TCGv_i64 t = read_fp_dreg(s, rn);
103
+ TCGv_ptr fpstatus = get_fpstatus_ptr(false);
104
+
105
+ gen_helper_fjcvtzs(t, t, fpstatus);
106
+
107
+ tcg_temp_free_ptr(fpstatus);
108
+
109
+ tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
110
+ tcg_gen_extrh_i64_i32(cpu_ZF, t);
111
+ tcg_gen_movi_i32(cpu_CF, 0);
112
+ tcg_gen_movi_i32(cpu_NF, 0);
113
+ tcg_gen_movi_i32(cpu_VF, 0);
114
+
115
+ tcg_temp_free_i64(t);
116
+}
117
+
118
/* Floating point <-> integer conversions
119
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
120
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
121
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
122
handle_fmov(s, rd, rn, type, itof);
123
break;
124
125
+ case 0b00111110: /* FJCVTZS */
126
+ if (!dc_isar_feature(aa64_jscvt, s)) {
127
+ goto do_unallocated;
128
+ } else if (fp_access_check(s)) {
129
+ handle_fjcvtzs(s, rd, rn);
130
+ }
131
+ break;
132
+
133
default:
134
do_unallocated:
135
unallocated_encoding(s);
136
diff --git a/target/arm/translate.c b/target/arm/translate.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/target/arm/translate.c
139
+++ b/target/arm/translate.c
140
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
141
rm_is_dp = false;
142
break;
143
144
+ case 0x13: /* vjcvt */
145
+ if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
146
+ return 1;
147
+ }
148
+ rd_is_dp = false;
149
+ break;
150
+
151
default:
152
return 1;
153
}
154
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
155
case 17: /* fsito */
156
gen_vfp_sito(dp, 0);
157
break;
158
+ case 19: /* vjcvt */
159
+ gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
160
+ break;
161
case 20: /* fshto */
162
gen_vfp_shto(dp, 16 - rm, 0);
163
break;
164
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/vfp_helper.c
167
+++ b/target/arm/vfp_helper.c
168
@@ -XXX,XX +XXX,XX @@ int arm_rmode_to_sf(int rmode)
169
}
170
return rmode;
171
}
172
+
173
+/*
174
+ * Implement float64 to int32_t conversion without saturation;
175
+ * the result is supplied modulo 2^32.
176
+ */
177
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
178
+{
179
+ float_status *status = vstatus;
180
+ uint32_t exp, sign;
181
+ uint64_t frac;
182
+ uint32_t inexact = 1; /* !Z */
183
+
184
+ sign = extract64(value, 63, 1);
185
+ exp = extract64(value, 52, 11);
186
+ frac = extract64(value, 0, 52);
187
+
188
+ if (exp == 0) {
189
+ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
190
+ inexact = sign;
191
+ if (frac != 0) {
192
+ if (status->flush_inputs_to_zero) {
193
+ float_raise(float_flag_input_denormal, status);
194
+ } else {
195
+ float_raise(float_flag_inexact, status);
196
+ inexact = 1;
197
+ }
198
+ }
199
+ frac = 0;
200
+ } else if (exp == 0x7ff) {
201
+ /* This operation raises Invalid for both NaN and overflow (Inf). */
202
+ float_raise(float_flag_invalid, status);
203
+ frac = 0;
204
+ } else {
205
+ int true_exp = exp - 1023;
206
+ int shift = true_exp - 52;
207
+
208
+ /* Restore implicit bit. */
209
+ frac |= 1ull << 52;
210
+
211
+ /* Shift the fraction into place. */
212
+ if (shift >= 0) {
213
+ /* The number is so large we must shift the fraction left. */
214
+ if (shift >= 64) {
215
+ /* The fraction is shifted out entirely. */
216
+ frac = 0;
217
+ } else {
218
+ frac <<= shift;
219
+ }
220
+ } else if (shift > -64) {
221
+ /* Normal case -- shift right and notice if bits shift out. */
222
+ inexact = (frac << (64 + shift)) != 0;
223
+ frac >>= -shift;
224
+ } else {
225
+ /* The fraction is shifted out entirely. */
226
+ frac = 0;
227
+ }
228
+
229
+ /* Notice overflow or inexact exceptions. */
230
+ if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
231
+ /* Overflow, for which this operation raises invalid. */
232
+ float_raise(float_flag_invalid, status);
233
+ inexact = 1;
234
+ } else if (inexact) {
235
+ float_raise(float_flag_inexact, status);
236
+ }
237
+
238
+ /* Honor the sign. */
239
+ if (sign) {
240
+ frac = -frac;
241
+ }
242
+ }
243
+
244
+ /* Pack the result and the env->ZF representation of Z together. */
245
+ return deposit64(frac, 32, 32, inexact);
246
+}
247
+
248
+uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
249
+{
250
+ uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status);
251
+ uint32_t result = pair;
252
+ uint32_t z = (pair >> 32) == 0;
253
+
254
+ /* Store Z, clear NCV, in FPSCR.NZCV. */
255
+ env->vfp.xregs[ARM_VFP_FPSCR]
256
+ = (env->vfp.xregs[ARM_VFP_FPSCR] & ~CPSR_NZCV) | (z * CPSR_Z);
257
+
258
+ return result;
259
+}
56
--
260
--
57
2.7.4
261
2.20.1
58
262
59
263
diff view generated by jsdifflib
1
For external aborts, we will want to be able to specify the EA
1
The Peripheral Protection Controller's handling of unused ports
2
(external abort type) bit in the syndrome field. Allow callers of
2
is that if there is nothing connected to the port's downstream
3
deliver_fault() to do that by adding a field to ARMMMUFaultInfo which
3
then it does not create the sysbus MMIO region for the upstream
4
we use when constructing the syndrome values.
4
end of the port. This results in odd behaviour when there is
5
an unused port in the middle of the range: since sysbus MMIO
6
regions are implicitly consecutively allocated, any used ports
7
above the unused ones end up with sysbus MMIO region numbers
8
that don't match the port number.
9
10
Avoid this numbering mismatch by creating dummy MMIO regions
11
for the unused ports. This doesn't change anything for our
12
existing boards, which don't have any gaps in the middle of
13
the port ranges they use; but it will be needed for the Musca
14
board.
5
15
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
---
18
---
10
target/arm/internals.h | 2 ++
19
include/hw/misc/tz-ppc.h | 8 +++++++-
11
target/arm/op_helper.c | 10 +++++-----
20
hw/misc/tz-ppc.c | 32 ++++++++++++++++++++++++++++++++
12
2 files changed, 7 insertions(+), 5 deletions(-)
21
2 files changed, 39 insertions(+), 1 deletion(-)
13
22
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
25
--- a/include/hw/misc/tz-ppc.h
17
+++ b/target/arm/internals.h
26
+++ b/include/hw/misc/tz-ppc.h
18
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu);
27
@@ -XXX,XX +XXX,XX @@
19
* @s2addr: Address that caused a fault at stage 2
28
*
20
* @stage2: True if we faulted at stage 2
29
* QEMU interface:
21
* @s1ptw: True if we faulted at stage 2 while doing a stage 1 page-table walk
30
* + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
22
+ * @ea: True if we should set the EA (external abort type) bit in syndrome
31
- * of each of the 16 ports of the PPC
23
*/
32
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
24
typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
33
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
25
struct ARMMMUFaultInfo {
34
+ * range then no sysbus MMIO region is created for its upstream. When an
26
target_ulong s2addr;
35
+ * unused port lies in the middle of the range with other used ports at
27
bool stage2;
36
+ * higher port numbers, a dummy MMIO region is created to ensure that
28
bool s1ptw;
37
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
29
+ bool ea;
38
+ * not be mapped, and will assert if any access is made to them.
39
* + Property "port[0..15]": MemoryRegion defining the downstream device(s)
40
* for each of the 16 ports of the PPC
41
* + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
42
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/tz-ppc.c
45
+++ b/hw/misc/tz-ppc.c
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_ppc_ops = {
47
.endianness = DEVICE_LITTLE_ENDIAN,
30
};
48
};
31
49
32
/* Do a page table walk and add page to TLB if possible */
50
+static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
33
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
51
+ unsigned size, bool is_write,
34
index XXXXXXX..XXXXXXX 100644
52
+ MemTxAttrs attrs)
35
--- a/target/arm/op_helper.c
53
+{
36
+++ b/target/arm/op_helper.c
54
+ /*
37
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
55
+ * Board code should never map the upstream end of an unused port,
38
56
+ * so we should never try to make a memory access to it.
39
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
57
+ */
40
unsigned int target_el,
58
+ g_assert_not_reached();
41
- bool same_el,
59
+}
42
+ bool same_el, bool ea,
60
+
43
bool s1ptw, bool is_write,
61
+static const MemoryRegionOps tz_ppc_dummy_ops = {
44
int fsc)
62
+ .valid.accepts = tz_ppc_dummy_accepts,
63
+};
64
+
65
static void tz_ppc_reset(DeviceState *dev)
45
{
66
{
46
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
67
TZPPC *s = TZ_PPC(dev);
68
@@ -XXX,XX +XXX,XX @@ static void tz_ppc_realize(DeviceState *dev, Error **errp)
69
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
70
TZPPC *s = TZ_PPC(dev);
71
int i;
72
+ int max_port = 0;
73
74
/* We can't create the upstream end of the port until realize,
75
* as we don't know the size of the MR used as the downstream until then.
47
*/
76
*/
48
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
77
for (i = 0; i < TZ_NUM_PORTS; i++) {
49
syn = syn_data_abort_no_iss(same_el,
78
+ if (s->port[i].downstream) {
50
- 0, 0, s1ptw, is_write, fsc);
79
+ max_port = i;
51
+ ea, 0, s1ptw, is_write, fsc);
80
+ }
52
} else {
81
+ }
53
/* Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template
82
+
54
* syndrome created at translation time.
83
+ for (i = 0; i <= max_port; i++) {
55
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
84
TZPPCPort *port = &s->port[i];
56
*/
85
char *name;
57
syn = syn_data_abort_with_iss(same_el,
86
uint64_t size;
58
0, 0, 0, 0, 0,
87
59
- 0, 0, s1ptw, is_write, fsc,
88
if (!port->downstream) {
60
+ ea, 0, s1ptw, is_write, fsc,
89
+ /*
61
false);
90
+ * Create dummy sysbus MMIO region so the sysbus region
62
/* Merge the runtime syndrome with the template syndrome. */
91
+ * numbering doesn't get out of sync with the port numbers.
63
syn |= template_syn;
92
+ * The size is entirely arbitrary.
64
@@ -XXX,XX +XXX,XX @@ static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
93
+ */
65
}
94
+ name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
66
95
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
67
if (access_type == MMU_INST_FETCH) {
96
+ port, name, 0x10000);
68
- syn = syn_insn_abort(same_el, 0, fi->s1ptw, fsc);
97
+ sysbus_init_mmio(sbd, &port->upstream);
69
+ syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
98
+ g_free(name);
70
exc = EXCP_PREFETCH_ABORT;
99
continue;
71
} else {
100
}
72
syn = merge_syn_data_abort(env->exception.syndrome, target_el,
101
73
- same_el, fi->s1ptw,
74
+ same_el, fi->ea, fi->s1ptw,
75
access_type == MMU_DATA_STORE,
76
fsc);
77
if (access_type == MMU_DATA_STORE
78
--
102
--
79
2.7.4
103
2.20.1
80
104
81
105
diff view generated by jsdifflib
1
The armv7m_nvic.h header file was accidentally placed in
1
Create a new include file for the pl031's device struct,
2
include/hw/arm; move it to include/hw/intc to match where
2
type macros, etc, so that it can be instantiated using
3
its corresponding .c file lives.
3
the "embedded struct" coding style.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-15-git-send-email-peter.maydell@linaro.org
10
---
8
---
11
include/hw/arm/armv7m.h | 2 +-
9
include/hw/timer/pl031.h | 44 ++++++++++++++++++++++++++++++++++++++++
12
include/hw/{arm => intc}/armv7m_nvic.h | 0
10
hw/timer/pl031.c | 25 +----------------------
13
hw/intc/armv7m_nvic.c | 2 +-
11
MAINTAINERS | 1 +
14
3 files changed, 2 insertions(+), 2 deletions(-)
12
3 files changed, 46 insertions(+), 24 deletions(-)
15
rename include/hw/{arm => intc}/armv7m_nvic.h (100%)
13
create mode 100644 include/hw/timer/pl031.h
16
14
17
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
15
diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/include/hw/timer/pl031.h
20
@@ -XXX,XX +XXX,XX @@
21
+/*
22
+ * ARM AMBA PrimeCell PL031 RTC
23
+ *
24
+ * Copyright (c) 2007 CodeSourcery
25
+ *
26
+ * This file is free software; you can redistribute it and/or modify
27
+ * it under the terms of the GNU General Public License version 2 as
28
+ * published by the Free Software Foundation.
29
+ *
30
+ * Contributions after 2012-01-13 are licensed under the terms of the
31
+ * GNU GPL, version 2 or (at your option) any later version.
32
+ */
33
+
34
+#ifndef HW_TIMER_PL031
35
+#define HW_TIMER_PL031
36
+
37
+#include "hw/sysbus.h"
38
+
39
+#define TYPE_PL031 "pl031"
40
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
41
+
42
+typedef struct PL031State {
43
+ SysBusDevice parent_obj;
44
+
45
+ MemoryRegion iomem;
46
+ QEMUTimer *timer;
47
+ qemu_irq irq;
48
+
49
+ /*
50
+ * Needed to preserve the tick_count across migration, even if the
51
+ * absolute value of the rtc_clock is different on the source and
52
+ * destination.
53
+ */
54
+ uint32_t tick_offset_vmstate;
55
+ uint32_t tick_offset;
56
+
57
+ uint32_t mr;
58
+ uint32_t lr;
59
+ uint32_t cr;
60
+ uint32_t im;
61
+ uint32_t is;
62
+} PL031State;
63
+
64
+#endif
65
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
18
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armv7m.h
67
--- a/hw/timer/pl031.c
20
+++ b/include/hw/arm/armv7m.h
68
+++ b/hw/timer/pl031.c
21
@@ -XXX,XX +XXX,XX @@
69
@@ -XXX,XX +XXX,XX @@
22
#define HW_ARM_ARMV7M_H
70
*/
23
71
24
#include "hw/sysbus.h"
72
#include "qemu/osdep.h"
25
-#include "hw/arm/armv7m_nvic.h"
73
+#include "hw/timer/pl031.h"
26
+#include "hw/intc/armv7m_nvic.h"
27
28
#define TYPE_BITBAND "ARM,bitband-memory"
29
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
30
diff --git a/include/hw/arm/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
31
similarity index 100%
32
rename from include/hw/arm/armv7m_nvic.h
33
rename to include/hw/intc/armv7m_nvic.h
34
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/armv7m_nvic.c
37
+++ b/hw/intc/armv7m_nvic.c
38
@@ -XXX,XX +XXX,XX @@
39
#include "hw/sysbus.h"
74
#include "hw/sysbus.h"
40
#include "qemu/timer.h"
75
#include "qemu/timer.h"
41
#include "hw/arm/arm.h"
76
#include "sysemu/sysemu.h"
42
-#include "hw/arm/armv7m_nvic.h"
77
@@ -XXX,XX +XXX,XX @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
43
+#include "hw/intc/armv7m_nvic.h"
78
#define RTC_MIS 0x18 /* Masked interrupt status register */
44
#include "target/arm/cpu.h"
79
#define RTC_ICR 0x1c /* Interrupt clear register */
45
#include "exec/exec-all.h"
80
46
#include "qemu/log.h"
81
-#define TYPE_PL031 "pl031"
82
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
83
-
84
-typedef struct PL031State {
85
- SysBusDevice parent_obj;
86
-
87
- MemoryRegion iomem;
88
- QEMUTimer *timer;
89
- qemu_irq irq;
90
-
91
- /* Needed to preserve the tick_count across migration, even if the
92
- * absolute value of the rtc_clock is different on the source and
93
- * destination.
94
- */
95
- uint32_t tick_offset_vmstate;
96
- uint32_t tick_offset;
97
-
98
- uint32_t mr;
99
- uint32_t lr;
100
- uint32_t cr;
101
- uint32_t im;
102
- uint32_t is;
103
-} PL031State;
104
-
105
static const unsigned char pl031_id[] = {
106
0x31, 0x10, 0x14, 0x00, /* Device ID */
107
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
108
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
111
+++ b/MAINTAINERS
112
@@ -XXX,XX +XXX,XX @@ F: hw/sd/pl181.c
113
F: hw/ssi/pl022.c
114
F: include/hw/ssi/pl022.h
115
F: hw/timer/pl031.c
116
+F: include/hw/timer/pl031.h
117
F: include/hw/arm/primecell.h
118
F: hw/timer/cmsdk-apb-timer.c
119
F: include/hw/timer/cmsdk-apb-timer.h
47
--
120
--
48
2.7.4
121
2.20.1
49
122
50
123
diff view generated by jsdifflib
1
Set the MachineClass flag ignore_memory_transaction_failures
1
Convert the debug printing in the PL031 device to use trace events,
2
for almost all ARM boards. This means they retain the legacy
2
and augment it to cover the interesting parts of device operation.
3
behaviour that accesses to unimplemented addresses will RAZ/WI
4
rather than aborting, when a subsequent commit adds support
5
for external aborts.
6
7
The exceptions are:
8
* virt -- we know that guests won't try to prod devices
9
that we don't describe in the device tree or ACPI tables
10
* mps2 -- this board was written to use unimplemented-device
11
for all the ranges with devices we don't yet handle
12
13
New boards should not set the flag, but instead be written
14
like the mps2.
15
3
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
For the Xilinx boards:
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
---
7
---
20
hw/arm/aspeed.c | 3 +++
8
hw/timer/pl031.c | 55 +++++++++++++++++++++++--------------------
21
hw/arm/collie.c | 1 +
9
hw/timer/trace-events | 6 +++++
22
hw/arm/cubieboard.c | 1 +
10
2 files changed, 36 insertions(+), 25 deletions(-)
23
hw/arm/digic_boards.c | 1 +
24
hw/arm/exynos4_boards.c | 2 ++
25
hw/arm/gumstix.c | 2 ++
26
hw/arm/highbank.c | 2 ++
27
hw/arm/imx25_pdk.c | 1 +
28
hw/arm/integratorcp.c | 1 +
29
hw/arm/kzm.c | 1 +
30
hw/arm/mainstone.c | 1 +
31
hw/arm/musicpal.c | 1 +
32
hw/arm/netduino2.c | 1 +
33
hw/arm/nseries.c | 2 ++
34
hw/arm/omap_sx1.c | 2 ++
35
hw/arm/palm.c | 1 +
36
hw/arm/raspi.c | 1 +
37
hw/arm/realview.c | 4 ++++
38
hw/arm/sabrelite.c | 1 +
39
hw/arm/spitz.c | 4 ++++
40
hw/arm/stellaris.c | 2 ++
41
hw/arm/tosa.c | 1 +
42
hw/arm/versatilepb.c | 2 ++
43
hw/arm/vexpress.c | 1 +
44
hw/arm/xilinx_zynq.c | 1 +
45
hw/arm/xlnx-ep108.c | 2 ++
46
hw/arm/z2.c | 1 +
47
27 files changed, 43 insertions(+)
48
11
49
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
12
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
50
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/aspeed.c
14
--- a/hw/timer/pl031.c
52
+++ b/hw/arm/aspeed.c
15
+++ b/hw/timer/pl031.c
53
@@ -XXX,XX +XXX,XX @@ static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
16
@@ -XXX,XX +XXX,XX @@
54
mc->no_floppy = 1;
17
#include "sysemu/sysemu.h"
55
mc->no_cdrom = 1;
18
#include "qemu/cutils.h"
56
mc->no_parallel = 1;
19
#include "qemu/log.h"
57
+ mc->ignore_memory_transaction_failures = true;
20
-
21
-//#define DEBUG_PL031
22
-
23
-#ifdef DEBUG_PL031
24
-#define DPRINTF(fmt, ...) \
25
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
26
-#else
27
-#define DPRINTF(fmt, ...) do {} while(0)
28
-#endif
29
+#include "trace.h"
30
31
#define RTC_DR 0x00 /* Data read register */
32
#define RTC_MR 0x04 /* Match register */
33
@@ -XXX,XX +XXX,XX @@ static const unsigned char pl031_id[] = {
34
35
static void pl031_update(PL031State *s)
36
{
37
- qemu_set_irq(s->irq, s->is & s->im);
38
+ uint32_t flags = s->is & s->im;
39
+
40
+ trace_pl031_irq_state(flags);
41
+ qemu_set_irq(s->irq, flags);
58
}
42
}
59
43
60
static const TypeInfo palmetto_bmc_type = {
44
static void pl031_interrupt(void * opaque)
61
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_class_init(ObjectClass *oc, void *data)
45
@@ -XXX,XX +XXX,XX @@ static void pl031_interrupt(void * opaque)
62
mc->no_floppy = 1;
46
PL031State *s = (PL031State *)opaque;
63
mc->no_cdrom = 1;
47
64
mc->no_parallel = 1;
48
s->is = 1;
65
+ mc->ignore_memory_transaction_failures = true;
49
- DPRINTF("Alarm raised\n");
50
+ trace_pl031_alarm_raised();
51
pl031_update(s);
66
}
52
}
67
53
68
static const TypeInfo ast2500_evb_type = {
54
@@ -XXX,XX +XXX,XX @@ static void pl031_set_alarm(PL031State *s)
69
@@ -XXX,XX +XXX,XX @@ static void romulus_bmc_class_init(ObjectClass *oc, void *data)
55
/* The timer wraps around. This subtraction also wraps in the same way,
70
mc->no_floppy = 1;
56
and gives correct results when alarm < now_ticks. */
71
mc->no_cdrom = 1;
57
ticks = s->mr - pl031_get_count(s);
72
mc->no_parallel = 1;
58
- DPRINTF("Alarm set in %ud ticks\n", ticks);
73
+ mc->ignore_memory_transaction_failures = true;
59
+ trace_pl031_set_alarm(ticks);
60
if (ticks == 0) {
61
timer_del(s->timer);
62
pl031_interrupt(s);
63
@@ -XXX,XX +XXX,XX @@ static uint64_t pl031_read(void *opaque, hwaddr offset,
64
unsigned size)
65
{
66
PL031State *s = (PL031State *)opaque;
67
-
68
- if (offset >= 0xfe0 && offset < 0x1000)
69
- return pl031_id[(offset - 0xfe0) >> 2];
70
+ uint64_t r;
71
72
switch (offset) {
73
case RTC_DR:
74
- return pl031_get_count(s);
75
+ r = pl031_get_count(s);
76
+ break;
77
case RTC_MR:
78
- return s->mr;
79
+ r = s->mr;
80
+ break;
81
case RTC_IMSC:
82
- return s->im;
83
+ r = s->im;
84
+ break;
85
case RTC_RIS:
86
- return s->is;
87
+ r = s->is;
88
+ break;
89
case RTC_LR:
90
- return s->lr;
91
+ r = s->lr;
92
+ break;
93
case RTC_CR:
94
/* RTC is permanently enabled. */
95
- return 1;
96
+ r = 1;
97
+ break;
98
case RTC_MIS:
99
- return s->is & s->im;
100
+ r = s->is & s->im;
101
+ break;
102
+ case 0xfe0 ... 0xfff:
103
+ r = pl031_id[(offset - 0xfe0) >> 2];
104
+ break;
105
case RTC_ICR:
106
qemu_log_mask(LOG_GUEST_ERROR,
107
"pl031: read of write-only register at offset 0x%x\n",
108
(int)offset);
109
+ r = 0;
110
break;
111
default:
112
qemu_log_mask(LOG_GUEST_ERROR,
113
"pl031_read: Bad offset 0x%x\n", (int)offset);
114
+ r = 0;
115
break;
116
}
117
118
- return 0;
119
+ trace_pl031_read(offset, r);
120
+ return r;
74
}
121
}
75
122
76
static const TypeInfo romulus_bmc_type = {
123
static void pl031_write(void * opaque, hwaddr offset,
77
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
124
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
125
{
126
PL031State *s = (PL031State *)opaque;
127
128
+ trace_pl031_write(offset, value);
129
130
switch (offset) {
131
case RTC_LR:
132
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
133
break;
134
case RTC_IMSC:
135
s->im = value & 1;
136
- DPRINTF("Interrupt mask %d\n", s->im);
137
pl031_update(s);
138
break;
139
case RTC_ICR:
140
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
141
cleared when bit 0 of the written value is set. However the
142
arm926e documentation (DDI0287B) states that the interrupt is
143
cleared when any value is written. */
144
- DPRINTF("Interrupt cleared");
145
s->is = 0;
146
pl031_update(s);
147
break;
148
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
78
index XXXXXXX..XXXXXXX 100644
149
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/collie.c
150
--- a/hw/timer/trace-events
80
+++ b/hw/arm/collie.c
151
+++ b/hw/timer/trace-events
81
@@ -XXX,XX +XXX,XX @@ static void collie_machine_init(MachineClass *mc)
152
@@ -XXX,XX +XXX,XX @@ xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec
82
{
153
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
83
mc->desc = "Sharp SL-5500 (Collie) PDA (SA-1110)";
154
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
84
mc->init = collie_init;
155
85
+ mc->ignore_memory_transaction_failures = true;
156
+# hw/timer/pl031.c
86
}
157
+pl031_irq_state(int level) "irq state %d"
87
158
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
88
DEFINE_MACHINE("collie", collie_machine_init)
159
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
89
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
160
+pl031_alarm_raised(void) "alarm raised"
90
index XXXXXXX..XXXXXXX 100644
161
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
91
--- a/hw/arm/cubieboard.c
92
+++ b/hw/arm/cubieboard.c
93
@@ -XXX,XX +XXX,XX @@ static void cubieboard_machine_init(MachineClass *mc)
94
mc->init = cubieboard_init;
95
mc->block_default_type = IF_IDE;
96
mc->units_per_default_bus = 1;
97
+ mc->ignore_memory_transaction_failures = true;
98
}
99
100
DEFINE_MACHINE("cubieboard", cubieboard_machine_init)
101
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/arm/digic_boards.c
104
+++ b/hw/arm/digic_boards.c
105
@@ -XXX,XX +XXX,XX @@ static void canon_a1100_machine_init(MachineClass *mc)
106
{
107
mc->desc = "Canon PowerShot A1100 IS";
108
mc->init = &canon_a1100_init;
109
+ mc->ignore_memory_transaction_failures = true;
110
}
111
112
DEFINE_MACHINE("canon-a1100", canon_a1100_machine_init)
113
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/hw/arm/exynos4_boards.c
116
+++ b/hw/arm/exynos4_boards.c
117
@@ -XXX,XX +XXX,XX @@ static void nuri_class_init(ObjectClass *oc, void *data)
118
mc->desc = "Samsung NURI board (Exynos4210)";
119
mc->init = nuri_init;
120
mc->max_cpus = EXYNOS4210_NCPUS;
121
+ mc->ignore_memory_transaction_failures = true;
122
}
123
124
static const TypeInfo nuri_type = {
125
@@ -XXX,XX +XXX,XX @@ static void smdkc210_class_init(ObjectClass *oc, void *data)
126
mc->desc = "Samsung SMDKC210 board (Exynos4210)";
127
mc->init = smdkc210_init;
128
mc->max_cpus = EXYNOS4210_NCPUS;
129
+ mc->ignore_memory_transaction_failures = true;
130
}
131
132
static const TypeInfo smdkc210_type = {
133
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/arm/gumstix.c
136
+++ b/hw/arm/gumstix.c
137
@@ -XXX,XX +XXX,XX @@ static void connex_class_init(ObjectClass *oc, void *data)
138
139
mc->desc = "Gumstix Connex (PXA255)";
140
mc->init = connex_init;
141
+ mc->ignore_memory_transaction_failures = true;
142
}
143
144
static const TypeInfo connex_type = {
145
@@ -XXX,XX +XXX,XX @@ static void verdex_class_init(ObjectClass *oc, void *data)
146
147
mc->desc = "Gumstix Verdex (PXA270)";
148
mc->init = verdex_init;
149
+ mc->ignore_memory_transaction_failures = true;
150
}
151
152
static const TypeInfo verdex_type = {
153
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/arm/highbank.c
156
+++ b/hw/arm/highbank.c
157
@@ -XXX,XX +XXX,XX @@ static void highbank_class_init(ObjectClass *oc, void *data)
158
mc->block_default_type = IF_IDE;
159
mc->units_per_default_bus = 1;
160
mc->max_cpus = 4;
161
+ mc->ignore_memory_transaction_failures = true;
162
}
163
164
static const TypeInfo highbank_type = {
165
@@ -XXX,XX +XXX,XX @@ static void midway_class_init(ObjectClass *oc, void *data)
166
mc->block_default_type = IF_IDE;
167
mc->units_per_default_bus = 1;
168
mc->max_cpus = 4;
169
+ mc->ignore_memory_transaction_failures = true;
170
}
171
172
static const TypeInfo midway_type = {
173
diff --git a/hw/arm/imx25_pdk.c b/hw/arm/imx25_pdk.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/hw/arm/imx25_pdk.c
176
+++ b/hw/arm/imx25_pdk.c
177
@@ -XXX,XX +XXX,XX @@ static void imx25_pdk_machine_init(MachineClass *mc)
178
{
179
mc->desc = "ARM i.MX25 PDK board (ARM926)";
180
mc->init = imx25_pdk_init;
181
+ mc->ignore_memory_transaction_failures = true;
182
}
183
184
DEFINE_MACHINE("imx25-pdk", imx25_pdk_machine_init)
185
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/integratorcp.c
188
+++ b/hw/arm/integratorcp.c
189
@@ -XXX,XX +XXX,XX @@ static void integratorcp_machine_init(MachineClass *mc)
190
{
191
mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
192
mc->init = integratorcp_init;
193
+ mc->ignore_memory_transaction_failures = true;
194
}
195
196
DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
197
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/arm/kzm.c
200
+++ b/hw/arm/kzm.c
201
@@ -XXX,XX +XXX,XX @@ static void kzm_machine_init(MachineClass *mc)
202
{
203
mc->desc = "ARM KZM Emulation Baseboard (ARM1136)";
204
mc->init = kzm_init;
205
+ mc->ignore_memory_transaction_failures = true;
206
}
207
208
DEFINE_MACHINE("kzm", kzm_machine_init)
209
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/hw/arm/mainstone.c
212
+++ b/hw/arm/mainstone.c
213
@@ -XXX,XX +XXX,XX @@ static void mainstone2_machine_init(MachineClass *mc)
214
{
215
mc->desc = "Mainstone II (PXA27x)";
216
mc->init = mainstone_init;
217
+ mc->ignore_memory_transaction_failures = true;
218
}
219
220
DEFINE_MACHINE("mainstone", mainstone2_machine_init)
221
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/hw/arm/musicpal.c
224
+++ b/hw/arm/musicpal.c
225
@@ -XXX,XX +XXX,XX @@ static void musicpal_machine_init(MachineClass *mc)
226
{
227
mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
228
mc->init = musicpal_init;
229
+ mc->ignore_memory_transaction_failures = true;
230
}
231
232
DEFINE_MACHINE("musicpal", musicpal_machine_init)
233
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/hw/arm/netduino2.c
236
+++ b/hw/arm/netduino2.c
237
@@ -XXX,XX +XXX,XX @@ static void netduino2_machine_init(MachineClass *mc)
238
{
239
mc->desc = "Netduino 2 Machine";
240
mc->init = netduino2_init;
241
+ mc->ignore_memory_transaction_failures = true;
242
}
243
244
DEFINE_MACHINE("netduino2", netduino2_machine_init)
245
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/hw/arm/nseries.c
248
+++ b/hw/arm/nseries.c
249
@@ -XXX,XX +XXX,XX @@ static void n800_class_init(ObjectClass *oc, void *data)
250
mc->desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)";
251
mc->init = n800_init;
252
mc->default_boot_order = "";
253
+ mc->ignore_memory_transaction_failures = true;
254
}
255
256
static const TypeInfo n800_type = {
257
@@ -XXX,XX +XXX,XX @@ static void n810_class_init(ObjectClass *oc, void *data)
258
mc->desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)";
259
mc->init = n810_init;
260
mc->default_boot_order = "";
261
+ mc->ignore_memory_transaction_failures = true;
262
}
263
264
static const TypeInfo n810_type = {
265
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/hw/arm/omap_sx1.c
268
+++ b/hw/arm/omap_sx1.c
269
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v2_class_init(ObjectClass *oc, void *data)
270
271
mc->desc = "Siemens SX1 (OMAP310) V2";
272
mc->init = sx1_init_v2;
273
+ mc->ignore_memory_transaction_failures = true;
274
}
275
276
static const TypeInfo sx1_machine_v2_type = {
277
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
278
279
mc->desc = "Siemens SX1 (OMAP310) V1";
280
mc->init = sx1_init_v1;
281
+ mc->ignore_memory_transaction_failures = true;
282
}
283
284
static const TypeInfo sx1_machine_v1_type = {
285
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
286
index XXXXXXX..XXXXXXX 100644
287
--- a/hw/arm/palm.c
288
+++ b/hw/arm/palm.c
289
@@ -XXX,XX +XXX,XX @@ static void palmte_machine_init(MachineClass *mc)
290
{
291
mc->desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)";
292
mc->init = palmte_init;
293
+ mc->ignore_memory_transaction_failures = true;
294
}
295
296
DEFINE_MACHINE("cheetah", palmte_machine_init)
297
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/arm/raspi.c
300
+++ b/hw/arm/raspi.c
301
@@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc)
302
mc->no_cdrom = 1;
303
mc->max_cpus = BCM2836_NCPUS;
304
mc->default_ram_size = 1024 * 1024 * 1024;
305
+ mc->ignore_memory_transaction_failures = true;
306
};
307
DEFINE_MACHINE("raspi2", raspi2_machine_init)
308
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/hw/arm/realview.c
311
+++ b/hw/arm/realview.c
312
@@ -XXX,XX +XXX,XX @@ static void realview_eb_class_init(ObjectClass *oc, void *data)
313
mc->desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)";
314
mc->init = realview_eb_init;
315
mc->block_default_type = IF_SCSI;
316
+ mc->ignore_memory_transaction_failures = true;
317
}
318
319
static const TypeInfo realview_eb_type = {
320
@@ -XXX,XX +XXX,XX @@ static void realview_eb_mpcore_class_init(ObjectClass *oc, void *data)
321
mc->init = realview_eb_mpcore_init;
322
mc->block_default_type = IF_SCSI;
323
mc->max_cpus = 4;
324
+ mc->ignore_memory_transaction_failures = true;
325
}
326
327
static const TypeInfo realview_eb_mpcore_type = {
328
@@ -XXX,XX +XXX,XX @@ static void realview_pb_a8_class_init(ObjectClass *oc, void *data)
329
330
mc->desc = "ARM RealView Platform Baseboard for Cortex-A8";
331
mc->init = realview_pb_a8_init;
332
+ mc->ignore_memory_transaction_failures = true;
333
}
334
335
static const TypeInfo realview_pb_a8_type = {
336
@@ -XXX,XX +XXX,XX @@ static void realview_pbx_a9_class_init(ObjectClass *oc, void *data)
337
mc->desc = "ARM RealView Platform Baseboard Explore for Cortex-A9";
338
mc->init = realview_pbx_a9_init;
339
mc->max_cpus = 4;
340
+ mc->ignore_memory_transaction_failures = true;
341
}
342
343
static const TypeInfo realview_pbx_a9_type = {
344
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
345
index XXXXXXX..XXXXXXX 100644
346
--- a/hw/arm/sabrelite.c
347
+++ b/hw/arm/sabrelite.c
348
@@ -XXX,XX +XXX,XX @@ static void sabrelite_machine_init(MachineClass *mc)
349
mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
350
mc->init = sabrelite_init;
351
mc->max_cpus = FSL_IMX6_NUM_CPUS;
352
+ mc->ignore_memory_transaction_failures = true;
353
}
354
355
DEFINE_MACHINE("sabrelite", sabrelite_machine_init)
356
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/hw/arm/spitz.c
359
+++ b/hw/arm/spitz.c
360
@@ -XXX,XX +XXX,XX @@ static void akitapda_class_init(ObjectClass *oc, void *data)
361
362
mc->desc = "Sharp SL-C1000 (Akita) PDA (PXA270)";
363
mc->init = akita_init;
364
+ mc->ignore_memory_transaction_failures = true;
365
}
366
367
static const TypeInfo akitapda_type = {
368
@@ -XXX,XX +XXX,XX @@ static void spitzpda_class_init(ObjectClass *oc, void *data)
369
mc->desc = "Sharp SL-C3000 (Spitz) PDA (PXA270)";
370
mc->init = spitz_init;
371
mc->block_default_type = IF_IDE;
372
+ mc->ignore_memory_transaction_failures = true;
373
}
374
375
static const TypeInfo spitzpda_type = {
376
@@ -XXX,XX +XXX,XX @@ static void borzoipda_class_init(ObjectClass *oc, void *data)
377
mc->desc = "Sharp SL-C3100 (Borzoi) PDA (PXA270)";
378
mc->init = borzoi_init;
379
mc->block_default_type = IF_IDE;
380
+ mc->ignore_memory_transaction_failures = true;
381
}
382
383
static const TypeInfo borzoipda_type = {
384
@@ -XXX,XX +XXX,XX @@ static void terrierpda_class_init(ObjectClass *oc, void *data)
385
mc->desc = "Sharp SL-C3200 (Terrier) PDA (PXA270)";
386
mc->init = terrier_init;
387
mc->block_default_type = IF_IDE;
388
+ mc->ignore_memory_transaction_failures = true;
389
}
390
391
static const TypeInfo terrierpda_type = {
392
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
393
index XXXXXXX..XXXXXXX 100644
394
--- a/hw/arm/stellaris.c
395
+++ b/hw/arm/stellaris.c
396
@@ -XXX,XX +XXX,XX @@ static void lm3s811evb_class_init(ObjectClass *oc, void *data)
397
398
mc->desc = "Stellaris LM3S811EVB";
399
mc->init = lm3s811evb_init;
400
+ mc->ignore_memory_transaction_failures = true;
401
}
402
403
static const TypeInfo lm3s811evb_type = {
404
@@ -XXX,XX +XXX,XX @@ static void lm3s6965evb_class_init(ObjectClass *oc, void *data)
405
406
mc->desc = "Stellaris LM3S6965EVB";
407
mc->init = lm3s6965evb_init;
408
+ mc->ignore_memory_transaction_failures = true;
409
}
410
411
static const TypeInfo lm3s6965evb_type = {
412
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
413
index XXXXXXX..XXXXXXX 100644
414
--- a/hw/arm/tosa.c
415
+++ b/hw/arm/tosa.c
416
@@ -XXX,XX +XXX,XX @@ static void tosapda_machine_init(MachineClass *mc)
417
mc->desc = "Sharp SL-6000 (Tosa) PDA (PXA255)";
418
mc->init = tosa_init;
419
mc->block_default_type = IF_IDE;
420
+ mc->ignore_memory_transaction_failures = true;
421
}
422
423
DEFINE_MACHINE("tosa", tosapda_machine_init)
424
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
425
index XXXXXXX..XXXXXXX 100644
426
--- a/hw/arm/versatilepb.c
427
+++ b/hw/arm/versatilepb.c
428
@@ -XXX,XX +XXX,XX @@ static void versatilepb_class_init(ObjectClass *oc, void *data)
429
mc->desc = "ARM Versatile/PB (ARM926EJ-S)";
430
mc->init = vpb_init;
431
mc->block_default_type = IF_SCSI;
432
+ mc->ignore_memory_transaction_failures = true;
433
}
434
435
static const TypeInfo versatilepb_type = {
436
@@ -XXX,XX +XXX,XX @@ static void versatileab_class_init(ObjectClass *oc, void *data)
437
mc->desc = "ARM Versatile/AB (ARM926EJ-S)";
438
mc->init = vab_init;
439
mc->block_default_type = IF_SCSI;
440
+ mc->ignore_memory_transaction_failures = true;
441
}
442
443
static const TypeInfo versatileab_type = {
444
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/hw/arm/vexpress.c
447
+++ b/hw/arm/vexpress.c
448
@@ -XXX,XX +XXX,XX @@ static void vexpress_class_init(ObjectClass *oc, void *data)
449
mc->desc = "ARM Versatile Express";
450
mc->init = vexpress_common_init;
451
mc->max_cpus = 4;
452
+ mc->ignore_memory_transaction_failures = true;
453
}
454
455
static void vexpress_a9_class_init(ObjectClass *oc, void *data)
456
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
457
index XXXXXXX..XXXXXXX 100644
458
--- a/hw/arm/xilinx_zynq.c
459
+++ b/hw/arm/xilinx_zynq.c
460
@@ -XXX,XX +XXX,XX @@ static void zynq_machine_init(MachineClass *mc)
461
mc->init = zynq_init;
462
mc->max_cpus = 1;
463
mc->no_sdcard = 1;
464
+ mc->ignore_memory_transaction_failures = true;
465
}
466
467
DEFINE_MACHINE("xilinx-zynq-a9", zynq_machine_init)
468
diff --git a/hw/arm/xlnx-ep108.c b/hw/arm/xlnx-ep108.c
469
index XXXXXXX..XXXXXXX 100644
470
--- a/hw/arm/xlnx-ep108.c
471
+++ b/hw/arm/xlnx-ep108.c
472
@@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_machine_init(MachineClass *mc)
473
mc->init = xlnx_ep108_init;
474
mc->block_default_type = IF_IDE;
475
mc->units_per_default_bus = 1;
476
+ mc->ignore_memory_transaction_failures = true;
477
}
478
479
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
480
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_init(MachineClass *mc)
481
mc->init = xlnx_ep108_init;
482
mc->block_default_type = IF_IDE;
483
mc->units_per_default_bus = 1;
484
+ mc->ignore_memory_transaction_failures = true;
485
}
486
487
DEFINE_MACHINE("xlnx-zcu102", xlnx_zcu102_machine_init)
488
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
489
index XXXXXXX..XXXXXXX 100644
490
--- a/hw/arm/z2.c
491
+++ b/hw/arm/z2.c
492
@@ -XXX,XX +XXX,XX @@ static void z2_machine_init(MachineClass *mc)
493
{
494
mc->desc = "Zipit Z2 (PXA27x)";
495
mc->init = z2_init;
496
+ mc->ignore_memory_transaction_failures = true;
497
}
498
499
DEFINE_MACHINE("z2", z2_machine_init)
500
--
162
--
501
2.7.4
163
2.20.1
502
164
503
165
diff view generated by jsdifflib
1
Implement the new do_transaction_failed hook for ARM, which should
1
Create a new include file for the pl011's device struct,
2
cause the CPU to take a prefetch abort or data abort.
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
---
8
---
8
target/arm/internals.h | 10 ++++++++++
9
include/hw/char/pl011.h | 34 ++++++++++++++++++++++++++++++++++
9
target/arm/cpu.c | 1 +
10
hw/char/pl011.c | 31 ++-----------------------------
10
target/arm/op_helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
11
2 files changed, 36 insertions(+), 29 deletions(-)
11
3 files changed, 54 insertions(+)
12
12
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
15
--- a/include/hw/char/pl011.h
16
+++ b/target/arm/internals.h
16
+++ b/include/hw/char/pl011.h
17
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
17
@@ -XXX,XX +XXX,XX @@
18
MMUAccessType access_type,
18
#ifndef HW_PL011_H
19
int mmu_idx, uintptr_t retaddr);
19
#define HW_PL011_H
20
20
21
+/* arm_cpu_do_transaction_failed: handle a memory system error response
21
+#include "hw/sysbus.h"
22
+ * (eg "no device/memory present at address") by raising an external abort
22
+#include "chardev/char-fe.h"
23
+ * exception
24
+ */
25
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
26
+ vaddr addr, unsigned size,
27
+ MMUAccessType access_type,
28
+ int mmu_idx, MemTxAttrs attrs,
29
+ MemTxResult response, uintptr_t retaddr);
30
+
23
+
31
/* Call the EL change hook if one has been registered */
24
+#define TYPE_PL011 "pl011"
32
static inline void arm_call_el_change_hook(ARMCPU *cpu)
25
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
33
{
26
+
34
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
+/* This shares the same struct (and cast macro) as the base pl011 device */
28
+#define TYPE_PL011_LUMINARY "pl011_luminary"
29
+
30
+typedef struct PL011State {
31
+ SysBusDevice parent_obj;
32
+
33
+ MemoryRegion iomem;
34
+ uint32_t readbuff;
35
+ uint32_t flags;
36
+ uint32_t lcr;
37
+ uint32_t rsr;
38
+ uint32_t cr;
39
+ uint32_t dmacr;
40
+ uint32_t int_enabled;
41
+ uint32_t int_level;
42
+ uint32_t read_fifo[16];
43
+ uint32_t ilpr;
44
+ uint32_t ibrd;
45
+ uint32_t fbrd;
46
+ uint32_t ifl;
47
+ int read_pos;
48
+ int read_count;
49
+ int read_trigger;
50
+ CharBackend chr;
51
+ qemu_irq irq;
52
+ const unsigned char *id;
53
+} PL011State;
54
+
55
static inline DeviceState *pl011_create(hwaddr addr,
56
qemu_irq irq,
57
Chardev *chr)
58
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
35
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/cpu.c
60
--- a/hw/char/pl011.c
37
+++ b/target/arm/cpu.c
61
+++ b/hw/char/pl011.c
38
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
62
@@ -XXX,XX +XXX,XX @@
39
#else
63
*/
40
cc->do_interrupt = arm_cpu_do_interrupt;
64
41
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
65
#include "qemu/osdep.h"
42
+ cc->do_transaction_failed = arm_cpu_do_transaction_failed;
66
+#include "hw/char/pl011.h"
43
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
67
#include "hw/sysbus.h"
44
cc->asidx_from_attrs = arm_asidx_from_attrs;
68
#include "chardev/char-fe.h"
45
cc->vmsd = &vmstate_arm_cpu;
69
#include "qemu/log.h"
46
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
70
#include "trace.h"
47
index XXXXXXX..XXXXXXX 100644
71
48
--- a/target/arm/op_helper.c
72
-#define TYPE_PL011 "pl011"
49
+++ b/target/arm/op_helper.c
73
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
50
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
74
-
51
deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
75
-typedef struct PL011State {
76
- SysBusDevice parent_obj;
77
-
78
- MemoryRegion iomem;
79
- uint32_t readbuff;
80
- uint32_t flags;
81
- uint32_t lcr;
82
- uint32_t rsr;
83
- uint32_t cr;
84
- uint32_t dmacr;
85
- uint32_t int_enabled;
86
- uint32_t int_level;
87
- uint32_t read_fifo[16];
88
- uint32_t ilpr;
89
- uint32_t ibrd;
90
- uint32_t fbrd;
91
- uint32_t ifl;
92
- int read_pos;
93
- int read_count;
94
- int read_trigger;
95
- CharBackend chr;
96
- qemu_irq irq;
97
- const unsigned char *id;
98
-} PL011State;
99
-
100
#define PL011_INT_TX 0x20
101
#define PL011_INT_RX 0x10
102
103
@@ -XXX,XX +XXX,XX @@ static void pl011_luminary_init(Object *obj)
52
}
104
}
53
105
54
+/* arm_cpu_do_transaction_failed: handle a memory system error response
106
static const TypeInfo pl011_luminary_info = {
55
+ * (eg "no device/memory present at address") by raising an external abort
107
- .name = "pl011_luminary",
56
+ * exception
108
+ .name = TYPE_PL011_LUMINARY,
57
+ */
109
.parent = TYPE_PL011,
58
+void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
110
.instance_init = pl011_luminary_init,
59
+ vaddr addr, unsigned size,
111
};
60
+ MMUAccessType access_type,
61
+ int mmu_idx, MemTxAttrs attrs,
62
+ MemTxResult response, uintptr_t retaddr)
63
+{
64
+ ARMCPU *cpu = ARM_CPU(cs);
65
+ CPUARMState *env = &cpu->env;
66
+ uint32_t fsr, fsc;
67
+ ARMMMUFaultInfo fi = {};
68
+ ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
69
+
70
+ if (retaddr) {
71
+ /* now we have a real cpu fault */
72
+ cpu_restore_state(cs, retaddr);
73
+ }
74
+
75
+ /* The EA bit in syndromes and fault status registers is an
76
+ * IMPDEF classification of external aborts. ARM implementations
77
+ * usually use this to indicate AXI bus Decode error (0) or
78
+ * Slave error (1); in QEMU we follow that.
79
+ */
80
+ fi.ea = (response != MEMTX_DECODE_ERROR);
81
+
82
+ /* The fault status register format depends on whether we're using
83
+ * the LPAE long descriptor format, or the short descriptor format.
84
+ */
85
+ if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
86
+ /* long descriptor form, STATUS 0b010000: synchronous ext abort */
87
+ fsr = (fi.ea << 12) | (1 << 9) | 0x10;
88
+ } else {
89
+ /* short descriptor form, FSR 0b01000 : synchronous ext abort */
90
+ fsr = (fi.ea << 12) | 0x8;
91
+ }
92
+ fsc = 0x10;
93
+
94
+ deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
95
+}
96
+
97
#endif /* !defined(CONFIG_USER_ONLY) */
98
99
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
100
--
112
--
101
2.7.4
113
2.20.1
102
114
103
115
diff view generated by jsdifflib
1
Move the MemTxResult type to memattrs.h. We're going to want to
1
The PL011 UART has six interrupt lines:
2
use it in cpu/qom.h, which doesn't want to include all of
2
* RX (receive data)
3
memory.h. In practice MemTxResult and MemTxAttrs are pretty
3
* TX (transmit data)
4
closely linked since both are used for the new-style
4
* RT (receive timeout)
5
read_with_attrs and write_with_attrs callbacks, so memattrs.h
5
* MS (modem status)
6
is a reasonable home for this rather than creating a whole
6
* E (errors)
7
new header file for it.
7
* combined (logical OR of all the above)
8
9
So far we have only emulated the combined interrupt line;
10
add support for the others, so that boards that wire them
11
up to different interrupt controller inputs can do so.
8
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
13
---
15
---
14
include/exec/memattrs.h | 10 ++++++++++
16
include/hw/char/pl011.h | 2 +-
15
include/exec/memory.h | 10 ----------
17
hw/char/pl011.c | 46 +++++++++++++++++++++++++++++++++++++++--
16
2 files changed, 10 insertions(+), 10 deletions(-)
18
2 files changed, 45 insertions(+), 3 deletions(-)
17
19
18
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
20
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/memattrs.h
22
--- a/include/hw/char/pl011.h
21
+++ b/include/exec/memattrs.h
23
+++ b/include/hw/char/pl011.h
22
@@ -XXX,XX +XXX,XX @@ typedef struct MemTxAttrs {
24
@@ -XXX,XX +XXX,XX @@ typedef struct PL011State {
25
int read_count;
26
int read_trigger;
27
CharBackend chr;
28
- qemu_irq irq;
29
+ qemu_irq irq[6];
30
const unsigned char *id;
31
} PL011State;
32
33
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/char/pl011.c
36
+++ b/hw/char/pl011.c
37
@@ -XXX,XX +XXX,XX @@
38
* This code is licensed under the GPL.
23
*/
39
*/
24
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
40
25
41
+/*
26
+/* New-style MMIO accessors can indicate that the transaction failed.
42
+ * QEMU interface:
27
+ * A zero (MEMTX_OK) response means success; anything else is a failure
43
+ * + sysbus MMIO region 0: device registers
28
+ * of some kind. The memory subsystem will bitwise-OR together results
44
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
29
+ * if it is synthesizing an operation from multiple smaller accesses.
45
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
46
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
47
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
48
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
49
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
30
+ */
50
+ */
31
+#define MEMTX_OK 0
32
+#define MEMTX_ERROR (1U << 0) /* device returned an error */
33
+#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
34
+typedef uint32_t MemTxResult;
35
+
51
+
36
#endif
52
#include "qemu/osdep.h"
37
diff --git a/include/exec/memory.h b/include/exec/memory.h
53
#include "hw/char/pl011.h"
38
index XXXXXXX..XXXXXXX 100644
54
#include "hw/sysbus.h"
39
--- a/include/exec/memory.h
55
@@ -XXX,XX +XXX,XX @@
40
+++ b/include/exec/memory.h
56
#define PL011_FLAG_TXFF 0x20
41
@@ -XXX,XX +XXX,XX @@ static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
57
#define PL011_FLAG_RXFE 0x10
42
n->end = end;
58
59
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
60
+#define INT_OE (1 << 10)
61
+#define INT_BE (1 << 9)
62
+#define INT_PE (1 << 8)
63
+#define INT_FE (1 << 7)
64
+#define INT_RT (1 << 6)
65
+#define INT_TX (1 << 5)
66
+#define INT_RX (1 << 4)
67
+#define INT_DSR (1 << 3)
68
+#define INT_DCD (1 << 2)
69
+#define INT_CTS (1 << 1)
70
+#define INT_RI (1 << 0)
71
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
72
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
73
+
74
static const unsigned char pl011_id_arm[8] =
75
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
76
static const unsigned char pl011_id_luminary[8] =
77
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
78
79
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
80
+static const uint32_t irqmask[] = {
81
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
82
+ INT_RX,
83
+ INT_TX,
84
+ INT_RT,
85
+ INT_MS,
86
+ INT_E,
87
+};
88
+
89
static void pl011_update(PL011State *s)
90
{
91
uint32_t flags;
92
+ int i;
93
94
flags = s->int_level & s->int_enabled;
95
trace_pl011_irq_state(flags != 0);
96
- qemu_set_irq(s->irq, flags != 0);
97
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
98
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
99
+ }
43
}
100
}
44
101
45
-/* New-style MMIO accessors can indicate that the transaction failed.
102
static uint64_t pl011_read(void *opaque, hwaddr offset,
46
- * A zero (MEMTX_OK) response means success; anything else is a failure
103
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
47
- * of some kind. The memory subsystem will bitwise-OR together results
104
{
48
- * if it is synthesizing an operation from multiple smaller accesses.
105
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
49
- */
106
PL011State *s = PL011(obj);
50
-#define MEMTX_OK 0
107
+ int i;
51
-#define MEMTX_ERROR (1U << 0) /* device returned an error */
108
52
-#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
109
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
53
-typedef uint32_t MemTxResult;
110
sysbus_init_mmio(sbd, &s->iomem);
54
-
111
- sysbus_init_irq(sbd, &s->irq);
55
/*
112
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
56
* Memory region callbacks
113
+ sysbus_init_irq(sbd, &s->irq[i]);
57
*/
114
+ }
115
116
s->read_trigger = 1;
117
s->ifl = 0x12;
58
--
118
--
59
2.7.4
119
2.20.1
60
120
61
121
diff view generated by jsdifflib
1
The M profile XPSR is almost the same format as the A profile CPSR,
1
The pl011 logs when the guest makes a bad access. It prints
2
but not quite. Define some XPSR_* macros and use them where we
2
the address offset in hex but confusingly omits the '0x'
3
definitely dealing with an XPSR rather than reusing the CPSR ones.
3
prefix; add it.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1501692241-23310-9-git-send-email-peter.maydell@linaro.org
9
---
8
---
10
target/arm/cpu.h | 38 ++++++++++++++++++++++++++++----------
9
hw/char/pl011.c | 4 ++--
11
target/arm/helper.c | 15 ++++++++-------
10
1 file changed, 2 insertions(+), 2 deletions(-)
12
2 files changed, 36 insertions(+), 17 deletions(-)
13
11
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
14
--- a/hw/char/pl011.c
17
+++ b/target/arm/cpu.h
15
+++ b/hw/char/pl011.c
18
@@ -XXX,XX +XXX,XX @@ void pmccntr_sync(CPUARMState *env);
16
@@ -XXX,XX +XXX,XX @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
19
/* Mask of bits which may be set by exception return copying them from SPSR */
17
break;
20
#define CPSR_ERET_MASK (~CPSR_RESERVED)
18
default:
21
19
qemu_log_mask(LOG_GUEST_ERROR,
22
+/* Bit definitions for M profile XPSR. Most are the same as CPSR. */
20
- "pl011_read: Bad offset %x\n", (int)offset);
23
+#define XPSR_EXCP 0x1ffU
21
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
24
+#define XPSR_SPREALIGN (1U << 9) /* Only set in exception stack frames */
22
r = 0;
25
+#define XPSR_IT_2_7 CPSR_IT_2_7
23
break;
26
+#define XPSR_GE CPSR_GE
27
+#define XPSR_SFPA (1U << 20) /* Only set in exception stack frames */
28
+#define XPSR_T (1U << 24) /* Not the same as CPSR_T ! */
29
+#define XPSR_IT_0_1 CPSR_IT_0_1
30
+#define XPSR_Q CPSR_Q
31
+#define XPSR_V CPSR_V
32
+#define XPSR_C CPSR_C
33
+#define XPSR_Z CPSR_Z
34
+#define XPSR_N CPSR_N
35
+#define XPSR_NZCV CPSR_NZCV
36
+#define XPSR_IT CPSR_IT
37
+
38
#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
39
#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
40
#define TTBCR_PD0 (1U << 4)
41
@@ -XXX,XX +XXX,XX @@ static inline uint32_t xpsr_read(CPUARMState *env)
42
/* Set the xPSR. Note that some bits of mask must be all-set or all-clear. */
43
static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
44
{
45
- if (mask & CPSR_NZCV) {
46
- env->ZF = (~val) & CPSR_Z;
47
+ if (mask & XPSR_NZCV) {
48
+ env->ZF = (~val) & XPSR_Z;
49
env->NF = val;
50
env->CF = (val >> 29) & 1;
51
env->VF = (val << 3) & 0x80000000;
52
}
24
}
53
- if (mask & CPSR_Q)
25
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
54
- env->QF = ((val & CPSR_Q) != 0);
26
break;
55
- if (mask & (1 << 24))
27
default:
56
- env->thumb = ((val & (1 << 24)) != 0);
28
qemu_log_mask(LOG_GUEST_ERROR,
57
- if (mask & CPSR_IT_0_1) {
29
- "pl011_write: Bad offset %x\n", (int)offset);
58
+ if (mask & XPSR_Q) {
30
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
59
+ env->QF = ((val & XPSR_Q) != 0);
60
+ }
61
+ if (mask & XPSR_T) {
62
+ env->thumb = ((val & XPSR_T) != 0);
63
+ }
64
+ if (mask & XPSR_IT_0_1) {
65
env->condexec_bits &= ~3;
66
env->condexec_bits |= (val >> 25) & 3;
67
}
68
- if (mask & CPSR_IT_2_7) {
69
+ if (mask & XPSR_IT_2_7) {
70
env->condexec_bits &= 3;
71
env->condexec_bits |= (val >> 8) & 0xfc;
72
}
73
- if (mask & 0x1ff) {
74
- env->v7m.exception = val & 0x1ff;
75
+ if (mask & XPSR_EXCP) {
76
+ env->v7m.exception = val & XPSR_EXCP;
77
}
31
}
78
}
32
}
79
33
80
diff --git a/target/arm/helper.c b/target/arm/helper.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/helper.c
83
+++ b/target/arm/helper.c
84
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
85
/* Align stack pointer if the guest wants that */
86
if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) {
87
env->regs[13] -= 4;
88
- xpsr |= 0x200;
89
+ xpsr |= XPSR_SPREALIGN;
90
}
91
/* Switch to the handler mode. */
92
v7m_push(env, xpsr);
93
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
94
env->regs[15] &= ~1U;
95
}
96
xpsr = v7m_pop(env);
97
- xpsr_write(env, xpsr, 0xfffffdff);
98
+ xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
99
/* Undo stack alignment. */
100
- if (xpsr & 0x200)
101
+ if (xpsr & XPSR_SPREALIGN) {
102
env->regs[13] |= 4;
103
+ }
104
105
/* The restored xPSR exception field will be zero if we're
106
* resuming in Thread mode. If that doesn't match what the
107
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
108
case 0 ... 7: /* xPSR sub-fields */
109
mask = 0;
110
if ((reg & 1) && el) {
111
- mask |= 0x000001ff; /* IPSR (unpriv. reads as zero) */
112
+ mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
113
}
114
if (!(reg & 4)) {
115
- mask |= 0xf8000000; /* APSR */
116
+ mask |= XPSR_NZCV | XPSR_Q; /* APSR */
117
}
118
/* EPSR reads as zero */
119
return xpsr_read(env) & mask;
120
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
121
uint32_t apsrmask = 0;
122
123
if (mask & 8) {
124
- apsrmask |= 0xf8000000; /* APSR NZCVQ */
125
+ apsrmask |= XPSR_NZCV | XPSR_Q;
126
}
127
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
128
- apsrmask |= 0x000f0000; /* APSR GE[3:0] */
129
+ apsrmask |= XPSR_GE;
130
}
131
xpsr_write(env, val, apsrmask);
132
}
133
--
34
--
134
2.7.4
35
2.20.1
135
36
136
37
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
In commit 4b635cf7a95e501211 we added a QOM property to the ARMSSE
2
object, but forgot to add it to the documentation comment in the
3
header. Correct the omission.
2
4
3
QEMU currently shows some unexpected behavior when the user trys to
5
Fixes: 4b635cf7a95e501211 ("hw/arm/armsse: Make SRAM bank size configurable")
4
do a "device_add digic" on an unrelated ARM machine like integratorcp
5
in "-nographic" mode (the device_add command does not immediately
6
return to the monitor prompt), and trying to "device_del" the device
7
later results in a "qemu/qdev-monitor.c:872:qdev_unplug: assertion
8
failed: (hotplug_ctrl)" error condition.
9
Looking at the realize function of the device, it uses serial_hds
10
directly and this means that the device can not be added a second
11
time, so let's simply mark it with "user_creatable = false" now.
12
13
Signed-off-by: Thomas Huth <thuth@redhat.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
8
---
17
hw/arm/digic.c | 2 ++
9
include/hw/arm/armsse.h | 2 ++
18
1 file changed, 2 insertions(+)
10
1 file changed, 2 insertions(+)
19
11
20
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/digic.c
14
--- a/include/hw/arm/armsse.h
23
+++ b/hw/arm/digic.c
15
+++ b/include/hw/arm/armsse.h
24
@@ -XXX,XX +XXX,XX @@ static void digic_class_init(ObjectClass *oc, void *data)
16
@@ -XXX,XX +XXX,XX @@
25
DeviceClass *dc = DEVICE_CLASS(oc);
17
* being the same for both, to avoid having to have separate Property
26
18
* lists for different variants. This restriction can be relaxed later
27
dc->realize = digic_realize;
19
* if necessary.)
28
+ /* Reason: Uses serial_hds in the realize function --> not usable twice */
20
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
29
+ dc->user_creatable = false;
21
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
30
}
22
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
31
23
* which are wired to its NVIC lines 32 .. n+32
32
static const TypeInfo digic_type_info = {
24
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
33
--
25
--
34
2.7.4
26
2.20.1
35
27
36
28
diff view generated by jsdifflib
1
The ARMv7M architecture specifies that most of the addresses in the
1
The Musca boards have DAPLink firmware that sets the initial
2
PPB region (which includes the NVIC, systick and system registers)
2
secure VTOR value (the location of the vector table) differently
3
are not accessible to unprivileged accesses, which should
3
depending on the boot mode (from flash, from RAM, etc). Export
4
BusFault with a few exceptions:
4
the init-svtor as a QOM property of the ARMSSE object so that
5
* the STIR is configurably user-accessible
5
the board can change it.
6
* the ITM (which we don't implement at all) is always
7
user-accessible
8
9
Implement this by switching the register access functions
10
to the _with_attrs scheme that lets us distinguish user
11
mode accesses.
12
13
This allows us to pull the handling of the CCR.USERSETMPEND
14
flag up to the level where we can make it generate a BusFault
15
as it should for non-permitted accesses.
16
17
Note that until the core ARM CPU code implements turning
18
MEMTX_ERROR into a BusFault the registers will continue to
19
act as RAZ/WI to user accesses.
20
6
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 1501692241-23310-16-git-send-email-peter.maydell@linaro.org
25
---
10
---
26
hw/intc/armv7m_nvic.c | 58 ++++++++++++++++++++++++++++++++++++---------------
11
include/hw/arm/armsse.h | 3 +++
27
1 file changed, 41 insertions(+), 17 deletions(-)
12
hw/arm/armsse.c | 8 ++++----
13
2 files changed, 7 insertions(+), 4 deletions(-)
28
14
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
30
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/armv7m_nvic.c
17
--- a/include/hw/arm/armsse.h
32
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/include/hw/arm/armsse.h
33
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
19
@@ -XXX,XX +XXX,XX @@
34
}
20
* if necessary.)
35
case 0xf00: /* Software Triggered Interrupt Register */
21
* + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
36
{
22
* address of each SRAM bank (and thus the total amount of internal SRAM)
37
- /* user mode can only write to STIR if CCR.USERSETMPEND permits it */
23
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
38
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
24
+ * (where it expects to load the PC and SP from the vector table on reset)
39
- if (excnum < s->num_irq &&
25
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
40
- (arm_current_el(&cpu->env) ||
26
* which are wired to its NVIC lines 32 .. n+32
41
- (cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) {
27
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
42
+ if (excnum < s->num_irq) {
28
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
43
armv7m_nvic_set_pending(s, excnum);
29
uint32_t exp_numirq;
44
}
30
uint32_t mainclk_frq;
45
break;
31
uint32_t sram_addr_width;
46
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
32
+ uint32_t init_svtor;
47
}
33
} ARMSSE;
48
}
34
49
35
typedef struct ARMSSEInfo ARMSSEInfo;
50
-static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
36
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
51
- unsigned size)
37
index XXXXXXX..XXXXXXX 100644
52
+static bool nvic_user_access_ok(NVICState *s, hwaddr offset)
38
--- a/hw/arm/armsse.c
53
+{
39
+++ b/hw/arm/armsse.c
54
+ /* Return true if unprivileged access to this register is permitted. */
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
55
+ switch (offset) {
41
* the INITSVTOR* registers before powering up the CPUs in any case,
56
+ case 0xf00: /* STIR: accessible only if CCR.USERSETMPEND permits */
42
* so the hardware's default value doesn't matter. QEMU doesn't emulate
57
+ return s->cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK;
43
* the control processor, so instead we behave in the way that the
58
+ default:
44
- * firmware does. All boards currently known about have firmware that
59
+ /* All other user accesses cause a BusFault unconditionally */
45
- * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
60
+ return false;
46
- * IoTKit default. We can make this more configurable if necessary.
61
+ }
47
+ * firmware does. The initial value is configurable by the board code
62
+}
48
+ * to match whatever its firmware does.
63
+
49
*/
64
+static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
50
- qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
65
+ uint64_t *data, unsigned size,
51
+ qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
66
+ MemTxAttrs attrs)
52
/*
67
{
53
* Start all CPUs except CPU0 powered down. In real hardware it is
68
NVICState *s = (NVICState *)opaque;
54
* a configurable property of the SSE-200 which CPUs start powered up
69
uint32_t offset = addr;
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
70
unsigned i, startvec, end;
56
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
71
uint32_t val;
57
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
72
58
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
73
+ if (attrs.user && !nvic_user_access_ok(s, addr)) {
59
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
74
+ /* Generate BusFault for unprivileged accesses */
60
DEFINE_PROP_END_OF_LIST()
75
+ return MEMTX_ERROR;
76
+ }
77
+
78
switch (offset) {
79
/* reads of set and clear both return the status */
80
case 0x100 ... 0x13f: /* NVIC Set enable */
81
@@ -XXX,XX +XXX,XX @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
82
}
83
84
trace_nvic_sysreg_read(addr, val, size);
85
- return val;
86
+ *data = val;
87
+ return MEMTX_OK;
88
}
89
90
-static void nvic_sysreg_write(void *opaque, hwaddr addr,
91
- uint64_t value, unsigned size)
92
+static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
93
+ uint64_t value, unsigned size,
94
+ MemTxAttrs attrs)
95
{
96
NVICState *s = (NVICState *)opaque;
97
uint32_t offset = addr;
98
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
99
100
trace_nvic_sysreg_write(addr, value, size);
101
102
+ if (attrs.user && !nvic_user_access_ok(s, addr)) {
103
+ /* Generate BusFault for unprivileged accesses */
104
+ return MEMTX_ERROR;
105
+ }
106
+
107
switch (offset) {
108
case 0x100 ... 0x13f: /* NVIC Set enable */
109
offset += 0x80;
110
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
111
}
112
}
113
nvic_irq_update(s);
114
- return;
115
+ return MEMTX_OK;
116
case 0x200 ... 0x23f: /* NVIC Set pend */
117
/* the special logic in armv7m_nvic_set_pending()
118
* is not needed since IRQs are never escalated
119
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
120
}
121
}
122
nvic_irq_update(s);
123
- return;
124
+ return MEMTX_OK;
125
case 0x300 ... 0x33f: /* NVIC Active */
126
- return; /* R/O */
127
+ return MEMTX_OK; /* R/O */
128
case 0x400 ... 0x5ef: /* NVIC Priority */
129
startvec = 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
130
131
@@ -XXX,XX +XXX,XX @@ static void nvic_sysreg_write(void *opaque, hwaddr addr,
132
set_prio(s, startvec + i, (value >> (i * 8)) & 0xff);
133
}
134
nvic_irq_update(s);
135
- return;
136
+ return MEMTX_OK;
137
case 0xd18 ... 0xd23: /* System Handler Priority. */
138
for (i = 0; i < size; i++) {
139
unsigned hdlidx = (offset - 0xd14) + i;
140
set_prio(s, hdlidx, (value >> (i * 8)) & 0xff);
141
}
142
nvic_irq_update(s);
143
- return;
144
+ return MEMTX_OK;
145
}
146
if (size == 4) {
147
nvic_writel(s, offset, value);
148
- return;
149
+ return MEMTX_OK;
150
}
151
qemu_log_mask(LOG_GUEST_ERROR,
152
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
153
+ /* This is UNPREDICTABLE; treat as RAZ/WI */
154
+ return MEMTX_OK;
155
}
156
157
static const MemoryRegionOps nvic_sysreg_ops = {
158
- .read = nvic_sysreg_read,
159
- .write = nvic_sysreg_write,
160
+ .read_with_attrs = nvic_sysreg_read,
161
+ .write_with_attrs = nvic_sysreg_write,
162
.endianness = DEVICE_NATIVE_ENDIAN,
163
};
61
};
164
62
165
--
63
--
166
2.7.4
64
2.20.1
167
65
168
66
diff view generated by jsdifflib
1
Currently we have a rather half-baked setup for allowing CPUs to
1
The Musca-A and Musca-B1 development boards are based on the
2
generate exceptions on accesses to invalid memory: the CPU has a
2
SSE-200 subsystem for embedded. Implement an initial skeleton
3
cpu_unassigned_access() hook which the memory system calls in
3
model of these boards, which are similar but not identical.
4
unassigned_mem_write() and unassigned_mem_read() if the current_cpu
4
5
pointer is non-NULL. This was originally designed before we
5
This commit creates the board model with the SSE and the IRQ
6
implemented the MemTxResult type that allows memory operations to
6
splitters to wire IRQs up to its two CPUs. As yet there
7
report a success or failure code, which is why the hook is called
7
are no devices and no memory: these will be added later.
8
right at the bottom of the memory system. The major problem with
9
this is that it means that the hook can be called even when the
10
access was not actually done by the CPU: for instance if the CPU
11
writes to a DMA engine register which causes the DMA engine to begin
12
a transaction which has been set up by the guest to operate on
13
invalid memory then this will casue the CPU to take an exception
14
incorrectly. Another minor problem is that currently if a device
15
returns a transaction error then this won't turn into a CPU exception
16
at all.
17
18
The right way to do this is to have allow the CPU to respond
19
to memory system transaction failures at the point where the
20
CPU specific code calls into the memory system.
21
22
Define a new QOM CPU method and utility function
23
cpu_transaction_failed() which is called in these cases.
24
The functionality here overlaps with the existing
25
cpu_unassigned_access() because individual target CPUs will
26
need some work to convert them to the new system. When this
27
transition is complete we can remove the old cpu_unassigned_access()
28
code.
29
8
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
33
---
11
---
34
include/qom/cpu.h | 22 ++++++++++++++++++++++
12
hw/arm/Makefile.objs | 1 +
35
1 file changed, 22 insertions(+)
13
hw/arm/musca.c | 197 ++++++++++++++++++++++++++++++++
36
14
MAINTAINERS | 6 +
37
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
15
default-configs/arm-softmmu.mak | 1 +
16
4 files changed, 205 insertions(+)
17
create mode 100644 hw/arm/musca.c
18
19
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
38
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
39
--- a/include/qom/cpu.h
21
--- a/hw/arm/Makefile.objs
40
+++ b/include/qom/cpu.h
22
+++ b/hw/arm/Makefile.objs
41
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock;
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
42
* @has_work: Callback for checking if there is work to do.
24
obj-$(CONFIG_MPS2) += mps2.o
43
* @do_interrupt: Callback for interrupt handling.
25
obj-$(CONFIG_MPS2) += mps2-tz.o
44
* @do_unassigned_access: Callback for unassigned access handling.
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
45
+ * (this is deprecated: new targets should use do_transaction_failed instead)
27
+obj-$(CONFIG_MUSCA) += musca.o
46
* @do_unaligned_access: Callback for unaligned access handling, if
28
obj-$(CONFIG_ARMSSE) += armsse.o
47
* the target defines #ALIGNED_ONLY.
29
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
48
+ * @do_transaction_failed: Callback for handling failed memory transactions
30
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
49
+ * (ie bus faults or external aborts; not MMU faults)
31
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
50
* @virtio_is_big_endian: Callback to return %true if a CPU which supports
32
new file mode 100644
51
* runtime configurable endianness is currently big-endian. Non-configurable
33
index XXXXXXX..XXXXXXX
52
* CPUs can use the default implementation of this method. This method should
34
--- /dev/null
53
@@ -XXX,XX +XXX,XX @@ typedef struct CPUClass {
35
+++ b/hw/arm/musca.c
54
void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
36
@@ -XXX,XX +XXX,XX @@
55
MMUAccessType access_type,
37
+/*
56
int mmu_idx, uintptr_t retaddr);
38
+ * Arm Musca-B1 test chip board emulation
57
+ void (*do_transaction_failed)(CPUState *cpu, hwaddr physaddr, vaddr addr,
39
+ *
58
+ unsigned size, MMUAccessType access_type,
40
+ * Copyright (c) 2019 Linaro Limited
59
+ int mmu_idx, MemTxAttrs attrs,
41
+ * Written by Peter Maydell
60
+ MemTxResult response, uintptr_t retaddr);
42
+ *
61
bool (*virtio_is_big_endian)(CPUState *cpu);
43
+ * This program is free software; you can redistribute it and/or modify
62
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
44
+ * it under the terms of the GNU General Public License version 2 or
63
uint8_t *buf, int len, bool is_write);
45
+ * (at your option) any later version.
64
@@ -XXX,XX +XXX,XX @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
46
+ */
65
47
+
66
cc->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
48
+/*
67
}
49
+ * The Musca boards are a reference implementation of a system using
68
+
50
+ * the SSE-200 subsystem for embedded:
69
+static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
51
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board
70
+ vaddr addr, unsigned size,
52
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board
71
+ MMUAccessType access_type,
53
+ * We model the A and B1 variants of this board, as described in the TRMs:
72
+ int mmu_idx, MemTxAttrs attrs,
54
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html
73
+ MemTxResult response,
55
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html
74
+ uintptr_t retaddr)
56
+ */
75
+{
57
+
76
+ CPUClass *cc = CPU_GET_CLASS(cpu);
58
+#include "qemu/osdep.h"
77
+
59
+#include "qemu/error-report.h"
78
+ if (cc->do_transaction_failed) {
60
+#include "qapi/error.h"
79
+ cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
61
+#include "exec/address-spaces.h"
80
+ mmu_idx, attrs, response, retaddr);
62
+#include "hw/arm/arm.h"
63
+#include "hw/arm/armsse.h"
64
+#include "hw/boards.h"
65
+#include "hw/core/split-irq.h"
66
+
67
+#define MUSCA_NUMIRQ_MAX 96
68
+
69
+typedef enum MuscaType {
70
+ MUSCA_A,
71
+ MUSCA_B1,
72
+} MuscaType;
73
+
74
+typedef struct {
75
+ MachineClass parent;
76
+ MuscaType type;
77
+ uint32_t init_svtor;
78
+ int sram_addr_width;
79
+ int num_irqs;
80
+} MuscaMachineClass;
81
+
82
+typedef struct {
83
+ MachineState parent;
84
+
85
+ ARMSSE sse;
86
+ SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
87
+} MuscaMachineState;
88
+
89
+#define TYPE_MUSCA_MACHINE "musca"
90
+#define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
91
+#define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
92
+
93
+#define MUSCA_MACHINE(obj) \
94
+ OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
95
+#define MUSCA_MACHINE_GET_CLASS(obj) \
96
+ OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
97
+#define MUSCA_MACHINE_CLASS(klass) \
98
+ OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
99
+
100
+/*
101
+ * Main SYSCLK frequency in Hz
102
+ * TODO this should really be different for the two cores, but we
103
+ * don't model that in our SSE-200 model yet.
104
+ */
105
+#define SYSCLK_FRQ 40000000
106
+
107
+static void musca_init(MachineState *machine)
108
+{
109
+ MuscaMachineState *mms = MUSCA_MACHINE(machine);
110
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
111
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
112
+ MemoryRegion *system_memory = get_system_memory();
113
+ DeviceState *ssedev;
114
+ int i;
115
+
116
+ assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
117
+
118
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
119
+ error_report("This board can only be used with CPU %s",
120
+ mc->default_cpu_type);
121
+ exit(1);
81
+ }
122
+ }
82
+}
123
+
83
#endif
124
+ sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse,
84
125
+ sizeof(mms->sse), TYPE_SSE200);
85
#endif /* NEED_CPU_H */
126
+ ssedev = DEVICE(&mms->sse);
127
+ object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory),
128
+ "memory", &error_fatal);
129
+ qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
130
+ qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
131
+ qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
132
+ qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
133
+ object_property_set_bool(OBJECT(&mms->sse), true, "realized",
134
+ &error_fatal);
135
+
136
+ /*
137
+ * We need to create splitters to feed the IRQ inputs
138
+ * for each CPU in the SSE-200 from each device in the board.
139
+ */
140
+ for (i = 0; i < mmc->num_irqs; i++) {
141
+ char *name = g_strdup_printf("musca-irq-splitter%d", i);
142
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
143
+
144
+ object_initialize_child(OBJECT(machine), name,
145
+ splitter, sizeof(*splitter),
146
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
147
+ g_free(name);
148
+
149
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
150
+ &error_fatal);
151
+ object_property_set_bool(OBJECT(splitter), true, "realized",
152
+ &error_fatal);
153
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
154
+ qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i));
155
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
156
+ qdev_get_gpio_in_named(ssedev,
157
+ "EXP_CPU1_IRQ", i));
158
+ }
159
+
160
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
161
+}
162
+
163
+static void musca_class_init(ObjectClass *oc, void *data)
164
+{
165
+ MachineClass *mc = MACHINE_CLASS(oc);
166
+
167
+ mc->default_cpus = 2;
168
+ mc->min_cpus = mc->default_cpus;
169
+ mc->max_cpus = mc->default_cpus;
170
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
171
+ mc->init = musca_init;
172
+}
173
+
174
+static void musca_a_class_init(ObjectClass *oc, void *data)
175
+{
176
+ MachineClass *mc = MACHINE_CLASS(oc);
177
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
178
+
179
+ mc->desc = "ARM Musca-A board (dual Cortex-M33)";
180
+ mmc->type = MUSCA_A;
181
+ mmc->init_svtor = 0x10200000;
182
+ mmc->sram_addr_width = 15;
183
+ mmc->num_irqs = 64;
184
+}
185
+
186
+static void musca_b1_class_init(ObjectClass *oc, void *data)
187
+{
188
+ MachineClass *mc = MACHINE_CLASS(oc);
189
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
190
+
191
+ mc->desc = "ARM Musca-B1 board (dual Cortex-M33)";
192
+ mmc->type = MUSCA_B1;
193
+ /*
194
+ * This matches the DAPlink firmware which boots from QSPI. There
195
+ * is also a firmware blob which boots from the eFlash, which
196
+ * uses init_svtor = 0x1A000000. QEMU doesn't currently support that,
197
+ * though we could in theory expose a machine property on the command
198
+ * line to allow the user to request eFlash boot.
199
+ */
200
+ mmc->init_svtor = 0x10000000;
201
+ mmc->sram_addr_width = 17;
202
+ mmc->num_irqs = 96;
203
+}
204
+
205
+static const TypeInfo musca_info = {
206
+ .name = TYPE_MUSCA_MACHINE,
207
+ .parent = TYPE_MACHINE,
208
+ .abstract = true,
209
+ .instance_size = sizeof(MuscaMachineState),
210
+ .class_size = sizeof(MuscaMachineClass),
211
+ .class_init = musca_class_init,
212
+};
213
+
214
+static const TypeInfo musca_a_info = {
215
+ .name = TYPE_MUSCA_A_MACHINE,
216
+ .parent = TYPE_MUSCA_MACHINE,
217
+ .class_init = musca_a_class_init,
218
+};
219
+
220
+static const TypeInfo musca_b1_info = {
221
+ .name = TYPE_MUSCA_B1_MACHINE,
222
+ .parent = TYPE_MUSCA_MACHINE,
223
+ .class_init = musca_b1_class_init,
224
+};
225
+
226
+static void musca_machine_init(void)
227
+{
228
+ type_register_static(&musca_info);
229
+ type_register_static(&musca_a_info);
230
+ type_register_static(&musca_b1_info);
231
+}
232
+
233
+type_init(musca_machine_init);
234
diff --git a/MAINTAINERS b/MAINTAINERS
235
index XXXXXXX..XXXXXXX 100644
236
--- a/MAINTAINERS
237
+++ b/MAINTAINERS
238
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/iotkit-sysinfo.h
239
F: hw/misc/armsse-cpuid.c
240
F: include/hw/misc/armsse-cpuid.h
241
242
+Musca
243
+M: Peter Maydell <peter.maydell@linaro.org>
244
+L: qemu-arm@nongnu.org
245
+S: Maintained
246
+F: hw/arm/musca.c
247
+
248
Musicpal
249
M: Jan Kiszka <jan.kiszka@web.de>
250
M: Peter Maydell <peter.maydell@linaro.org>
251
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
252
index XXXXXXX..XXXXXXX 100644
253
--- a/default-configs/arm-softmmu.mak
254
+++ b/default-configs/arm-softmmu.mak
255
@@ -XXX,XX +XXX,XX @@ CONFIG_TUSB6010=y
256
CONFIG_IMX=y
257
CONFIG_MAINSTONE=y
258
CONFIG_MPS2=y
259
+CONFIG_MUSCA=y
260
CONFIG_NSERIES=y
261
CONFIG_RASPI=y
262
CONFIG_REALVIEW=y
86
--
263
--
87
2.7.4
264
2.20.1
88
265
89
266
diff view generated by jsdifflib
1
We currently store the M profile CPU register state PRIMASK and
1
Many of the devices on the Musca board live behind TrustZone
2
FAULTMASK in the daif field of the CPU state in its I and F
2
Peripheral Protection Controllers (PPCs); add models of the
3
bits. This is a legacy from the original implementation, which
3
PPCs, using a similar scheme to the MPS2 board models.
4
tried to share the cpu_exec_interrupt code between A profile
4
This commit wires up the PPCs with "unimplemented device"
5
and M profile. We've since separated out the two cases because
5
stubs behind them in the correct places in the address map.
6
they are significantly different, so now there is no common
7
code between M and A profile which looks at env->daif: all the
8
uses are either in A-only or M-only code paths. Sharing the state
9
fields now is just confusing, and will make things awkward
10
when we implement v8M, where the PRIMASK and FAULTMASK
11
registers are banked between security states.
12
13
Switch M profile over to using v7m.faultmask and v7m.primask
14
fields for these registers.
15
6
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 1501692241-23310-10-git-send-email-peter.maydell@linaro.org
19
---
9
---
20
target/arm/cpu.h | 4 +++-
10
hw/arm/musca.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++
21
hw/intc/armv7m_nvic.c | 4 ++--
11
1 file changed, 289 insertions(+)
22
target/arm/cpu.c | 5 -----
23
target/arm/helper.c | 18 +++++-------------
24
target/arm/machine.c | 33 +++++++++++++++++++++++++++++++++
25
5 files changed, 43 insertions(+), 21 deletions(-)
26
12
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
28
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
15
--- a/hw/arm/musca.c
30
+++ b/target/arm/cpu.h
16
+++ b/hw/arm/musca.c
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
17
@@ -XXX,XX +XXX,XX @@
32
uint32_t bfar; /* BusFault Address */
18
#include "hw/arm/armsse.h"
33
unsigned mpu_ctrl; /* MPU_CTRL */
19
#include "hw/boards.h"
34
int exception;
20
#include "hw/core/split-irq.h"
35
+ uint32_t primask;
21
+#include "hw/misc/tz-ppc.h"
36
+ uint32_t faultmask;
22
+#include "hw/misc/unimp.h"
37
} v7m;
23
38
24
#define MUSCA_NUMIRQ_MAX 96
39
/* Information associated with an exception about to be taken:
25
+#define MUSCA_PPC_MAX 3
40
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
26
41
* we're in a HardFault or NMI handler.
27
typedef enum MuscaType {
42
*/
28
MUSCA_A,
43
if ((env->v7m.exception > 0 && env->v7m.exception <= 3)
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
44
- || env->daif & PSTATE_F) {
30
45
+ || env->v7m.faultmask) {
31
ARMSSE sse;
46
return arm_to_core_mmu_idx(ARMMMUIdx_MNegPri);
32
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
47
}
33
+ SplitIRQ sec_resp_splitter;
48
34
+ TZPPC ppc[MUSCA_PPC_MAX];
49
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
35
+ MemoryRegion container;
50
index XXXXXXX..XXXXXXX 100644
36
+ UnimplementedDeviceState eflash[2];
51
--- a/hw/intc/armv7m_nvic.c
37
+ UnimplementedDeviceState qspi;
52
+++ b/hw/intc/armv7m_nvic.c
38
+ UnimplementedDeviceState mpc[5];
53
@@ -XXX,XX +XXX,XX @@ static inline int nvic_exec_prio(NVICState *s)
39
+ UnimplementedDeviceState mhu[2];
54
CPUARMState *env = &s->cpu->env;
40
+ UnimplementedDeviceState pwm[3];
55
int running;
41
+ UnimplementedDeviceState i2s;
56
42
+ UnimplementedDeviceState uart[2];
57
- if (env->daif & PSTATE_F) { /* FAULTMASK */
43
+ UnimplementedDeviceState i2c[2];
58
+ if (env->v7m.faultmask) {
44
+ UnimplementedDeviceState spi;
59
running = -1;
45
+ UnimplementedDeviceState scc;
60
- } else if (env->daif & PSTATE_I) { /* PRIMASK */
46
+ UnimplementedDeviceState timer;
61
+ } else if (env->v7m.primask) {
47
+ UnimplementedDeviceState rtc;
62
running = 0;
48
+ UnimplementedDeviceState pvt;
63
} else if (env->v7m.basepri > 0) {
49
+ UnimplementedDeviceState sdio;
64
running = env->v7m.basepri & nvic_gprio_mask(s);
50
+ UnimplementedDeviceState gpio;
65
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
51
} MuscaMachineState;
66
index XXXXXXX..XXXXXXX 100644
52
67
--- a/target/arm/cpu.c
53
#define TYPE_MUSCA_MACHINE "musca"
68
+++ b/target/arm/cpu.c
54
@@ -XXX,XX +XXX,XX @@ typedef struct {
69
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
55
*/
70
uint32_t initial_pc; /* Loaded from 0x4 */
56
#define SYSCLK_FRQ 40000000
71
uint8_t *rom;
57
72
58
+/*
73
- /* For M profile we store FAULTMASK and PRIMASK in the
59
+ * Most of the devices in the Musca board sit behind Peripheral Protection
74
- * PSTATE F and I bits; these are both clear at reset.
60
+ * Controllers. These data structures define the layout of which devices
75
- */
61
+ * sit behind which PPCs.
76
- env->daif &= ~(PSTATE_I | PSTATE_F);
62
+ * The devfn for each port is a function which creates, configures
77
-
63
+ * and initializes the device, returning the MemoryRegion which
78
/* The reset value of this bit is IMPDEF, but ARM recommends
64
+ * needs to be plugged into the downstream end of the PPC port.
79
* that it resets to 1, so QEMU always does that rather than making
65
+ */
80
* it dependent on CPU model.
66
+typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque,
81
diff --git a/target/arm/helper.c b/target/arm/helper.c
67
+ const char *name, hwaddr size);
82
index XXXXXXX..XXXXXXX 100644
68
+
83
--- a/target/arm/helper.c
69
+typedef struct PPCPortInfo {
84
+++ b/target/arm/helper.c
70
+ const char *name;
85
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
71
+ MakeDevFn *devfn;
86
72
+ void *opaque;
87
if (env->v7m.exception != ARMV7M_EXCP_NMI) {
73
+ hwaddr addr;
88
/* Auto-clear FAULTMASK on return from other than NMI */
74
+ hwaddr size;
89
- env->daif &= ~PSTATE_F;
75
+} PPCPortInfo;
90
+ env->v7m.faultmask = 0;
76
+
77
+typedef struct PPCInfo {
78
+ const char *name;
79
+ PPCPortInfo ports[TZ_NUM_PORTS];
80
+} PPCInfo;
81
+
82
+static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
83
+ void *opaque, const char *name, hwaddr size)
84
+{
85
+ /*
86
+ * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
87
+ * and return a pointer to its MemoryRegion.
88
+ */
89
+ UnimplementedDeviceState *uds = opaque;
90
+
91
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
92
+ sizeof(UnimplementedDeviceState),
93
+ TYPE_UNIMPLEMENTED_DEVICE);
94
+ qdev_prop_set_string(DEVICE(uds), "name", name);
95
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
96
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
97
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
98
+}
99
+
100
+static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
101
+ const char *name, hwaddr size)
102
+{
103
+ /*
104
+ * Create the container MemoryRegion for all the devices that live
105
+ * behind the Musca-A PPC's single port. These devices don't have a PPC
106
+ * port each, but we use the PPCPortInfo struct as a convenient way
107
+ * to describe them. Note that addresses here are relative to the base
108
+ * address of the PPC port region: 0x40100000, and devices appear both
109
+ * at the 0x4... NS region and the 0x5... S region.
110
+ */
111
+ int i;
112
+ MemoryRegion *container = &mms->container;
113
+
114
+ const PPCPortInfo devices[] = {
115
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
116
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
117
+ { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
118
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
119
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
120
+ { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
121
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
122
+ { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
123
+ { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
124
+ { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
125
+ { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
126
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
127
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
128
+ { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
129
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
130
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
131
+ };
132
+
133
+ memory_region_init(container, OBJECT(mms), "musca-device-container", size);
134
+
135
+ for (i = 0; i < ARRAY_SIZE(devices); i++) {
136
+ const PPCPortInfo *pinfo = &devices[i];
137
+ MemoryRegion *mr;
138
+
139
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ memory_region_add_subregion(container, pinfo->addr, mr);
141
+ }
142
+
143
+ return &mms->container;
144
+}
145
+
146
static void musca_init(MachineState *machine)
147
{
148
MuscaMachineState *mms = MUSCA_MACHINE(machine);
149
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
150
MachineClass *mc = MACHINE_GET_CLASS(machine);
151
MemoryRegion *system_memory = get_system_memory();
152
DeviceState *ssedev;
153
+ DeviceState *dev_splitter;
154
+ const PPCInfo *ppcs;
155
+ int num_ppcs;
156
int i;
157
158
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
159
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
160
"EXP_CPU1_IRQ", i));
91
}
161
}
92
162
93
switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) {
163
+ /*
94
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
164
+ * The sec_resp_cfg output from the SSE-200 must be split into multiple
95
return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
165
+ * lines, one for each of the PPCs we create here.
96
env->regs[13] : env->v7m.other_sp;
166
+ */
97
case 16: /* PRIMASK */
167
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
98
- return (env->daif & PSTATE_I) != 0;
168
+ TYPE_SPLIT_IRQ);
99
+ return env->v7m.primask;
169
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
100
case 17: /* BASEPRI */
170
+ OBJECT(&mms->sec_resp_splitter), &error_fatal);
101
case 18: /* BASEPRI_MAX */
171
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
102
return env->v7m.basepri;
172
+ ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal);
103
case 19: /* FAULTMASK */
173
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
104
- return (env->daif & PSTATE_F) != 0;
174
+ "realized", &error_fatal);
105
+ return env->v7m.faultmask;
175
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
106
default:
176
+ qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0,
107
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
177
+ qdev_get_gpio_in(dev_splitter, 0));
108
" register %d\n", reg);
178
+
109
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
179
+ /*
110
}
180
+ * Most of the devices in the board are behind Peripheral Protection
111
break;
181
+ * Controllers. The required order for initializing things is:
112
case 16: /* PRIMASK */
182
+ * + initialize the PPC
113
- if (val & 1) {
183
+ * + initialize, configure and realize downstream devices
114
- env->daif |= PSTATE_I;
184
+ * + connect downstream device MemoryRegions to the PPC
115
- } else {
185
+ * + realize the PPC
116
- env->daif &= ~PSTATE_I;
186
+ * + map the PPC's MemoryRegions to the places in the address map
117
- }
187
+ * where the downstream devices should appear
118
+ env->v7m.primask = val & 1;
188
+ * + wire up the PPC's control lines to the SSE object
119
break;
189
+ *
120
case 17: /* BASEPRI */
190
+ * The PPC mapping differs for the -A and -B1 variants; the -A version
121
env->v7m.basepri = val & 0xff;
191
+ * is much simpler, using only a single port of a single PPC and putting
122
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
192
+ * all the devices behind that.
123
env->v7m.basepri = val;
193
+ */
124
break;
194
+ const PPCInfo a_ppcs[] = { {
125
case 19: /* FAULTMASK */
195
+ .name = "ahb_ppcexp0",
126
- if (val & 1) {
196
+ .ports = {
127
- env->daif |= PSTATE_F;
197
+ { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 },
128
- } else {
198
+ },
129
- env->daif &= ~PSTATE_F;
199
+ },
130
- }
200
+ };
131
+ env->v7m.faultmask = val & 1;
201
+
132
break;
202
+ /*
133
case 20: /* CONTROL */
203
+ * Devices listed with an 0x4.. address appear in both the NS 0x4.. region
134
/* Writing to the SPSEL bit only has an effect if we are in
204
+ * and the 0x5.. S region. Devices listed with an 0x5.. address appear
135
diff --git a/target/arm/machine.c b/target/arm/machine.c
205
+ * only in the S region.
136
index XXXXXXX..XXXXXXX 100644
206
+ */
137
--- a/target/arm/machine.c
207
+ const PPCInfo b1_ppcs[] = { {
138
+++ b/target/arm/machine.c
208
+ .name = "apb_ppcexp0",
139
@@ -XXX,XX +XXX,XX @@ static bool m_needed(void *opaque)
209
+ .ports = {
140
return arm_feature(env, ARM_FEATURE_M);
210
+ { "eflash0", make_unimp_dev, &mms->eflash[0],
211
+ 0x52400000, 0x1000 },
212
+ { "eflash1", make_unimp_dev, &mms->eflash[1],
213
+ 0x52500000, 0x1000 },
214
+ { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
215
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
216
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
217
+ { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
218
+ { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
219
+ { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
220
+ { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
221
+ { }, /* port 9: unused */
222
+ { }, /* port 10: unused */
223
+ { }, /* port 11: unused */
224
+ { }, /* port 12: unused */
225
+ { }, /* port 13: unused */
226
+ { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
227
+ },
228
+ }, {
229
+ .name = "apb_ppcexp1",
230
+ .ports = {
231
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 },
232
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
233
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
234
+ { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
235
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
236
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
237
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
238
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
239
+ { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
240
+ { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
241
+ { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
242
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
243
+ { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
244
+ { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
245
+ },
246
+ }, {
247
+ .name = "ahb_ppcexp0",
248
+ .ports = {
249
+ { }, /* port 0: unused */
250
+ { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 },
251
+ },
252
+ },
253
+ };
254
+
255
+ switch (mmc->type) {
256
+ case MUSCA_A:
257
+ ppcs = a_ppcs;
258
+ num_ppcs = ARRAY_SIZE(a_ppcs);
259
+ break;
260
+ case MUSCA_B1:
261
+ ppcs = b1_ppcs;
262
+ num_ppcs = ARRAY_SIZE(b1_ppcs);
263
+ break;
264
+ default:
265
+ g_assert_not_reached();
266
+ }
267
+ assert(num_ppcs <= MUSCA_PPC_MAX);
268
+
269
+ for (i = 0; i < num_ppcs; i++) {
270
+ const PPCInfo *ppcinfo = &ppcs[i];
271
+ TZPPC *ppc = &mms->ppc[i];
272
+ DeviceState *ppcdev;
273
+ int port;
274
+ char *gpioname;
275
+
276
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
277
+ sizeof(TZPPC), TYPE_TZ_PPC);
278
+ ppcdev = DEVICE(ppc);
279
+
280
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
281
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
282
+ MemoryRegion *mr;
283
+ char *portname;
284
+
285
+ if (!pinfo->devfn) {
286
+ continue;
287
+ }
288
+
289
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
290
+ portname = g_strdup_printf("port[%d]", port);
291
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
292
+ portname, &error_fatal);
293
+ g_free(portname);
294
+ }
295
+
296
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
297
+
298
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
299
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
300
+
301
+ if (!pinfo->devfn) {
302
+ continue;
303
+ }
304
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
305
+
306
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
307
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
308
+ qdev_get_gpio_in_named(ppcdev,
309
+ "cfg_nonsec",
310
+ port));
311
+ g_free(gpioname);
312
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
313
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
314
+ qdev_get_gpio_in_named(ppcdev,
315
+ "cfg_ap", port));
316
+ g_free(gpioname);
317
+ }
318
+
319
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
320
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
321
+ qdev_get_gpio_in_named(ppcdev,
322
+ "irq_enable", 0));
323
+ g_free(gpioname);
324
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
325
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
326
+ qdev_get_gpio_in_named(ppcdev,
327
+ "irq_clear", 0));
328
+ g_free(gpioname);
329
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
330
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
331
+ qdev_get_gpio_in_named(ssedev,
332
+ gpioname, 0));
333
+ g_free(gpioname);
334
+
335
+ qdev_connect_gpio_out(dev_splitter, i,
336
+ qdev_get_gpio_in_named(ppcdev,
337
+ "cfg_sec_resp", 0));
338
+ }
339
+
340
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
141
}
341
}
142
342
143
+static const VMStateDescription vmstate_m_faultmask_primask = {
144
+ .name = "cpu/m/faultmask-primask",
145
+ .version_id = 1,
146
+ .minimum_version_id = 1,
147
+ .fields = (VMStateField[]) {
148
+ VMSTATE_UINT32(env.v7m.faultmask, ARMCPU),
149
+ VMSTATE_UINT32(env.v7m.primask, ARMCPU),
150
+ VMSTATE_END_OF_LIST()
151
+ }
152
+};
153
+
154
static const VMStateDescription vmstate_m = {
155
.name = "cpu/m",
156
.version_id = 4,
157
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
158
VMSTATE_UINT32(env.v7m.mpu_ctrl, ARMCPU),
159
VMSTATE_INT32(env.v7m.exception, ARMCPU),
160
VMSTATE_END_OF_LIST()
161
+ },
162
+ .subsections = (const VMStateDescription*[]) {
163
+ &vmstate_m_faultmask_primask,
164
+ NULL
165
}
166
};
167
168
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
169
CPUARMState *env = &cpu->env;
170
uint32_t val = qemu_get_be32(f);
171
172
+ if (arm_feature(env, ARM_FEATURE_M)) {
173
+ /* If the I or F bits are set then this is a migration from
174
+ * an old QEMU which still stored the M profile FAULTMASK
175
+ * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask
176
+ * accordingly, and then clear the bits so they don't confuse
177
+ * cpsr_write(). For a new QEMU, the bits here will always be
178
+ * clear, and the data is transferred using the
179
+ * vmstate_m_faultmask_primask subsection.
180
+ */
181
+ if (val & CPSR_F) {
182
+ env->v7m.faultmask = 1;
183
+ }
184
+ if (val & CPSR_I) {
185
+ env->v7m.primask = 1;
186
+ }
187
+ val &= ~(CPSR_F | CPSR_I);
188
+ }
189
+
190
env->aarch64 = ((val & PSTATE_nRW) == 0);
191
192
if (is_a64(env)) {
193
--
343
--
194
2.7.4
344
2.20.1
195
345
196
346
diff view generated by jsdifflib
1
From: Andrew Jeffery <andrew@aj.id.au>
1
The Musca board puts its SRAM and flash behind TrustZone
2
2
Memory Protection Controllers (MPCs). Each MPC sits between
3
The reset width register controls how the pulse on the SoC's WDTRST{1,2}
3
the CPU and the RAM/flash, and also has a set of memory mapped
4
pins behaves. A pulse is emitted if the external reset bit is set in
4
control registers. Wire up the MPCs, and the memory behind them.
5
WDT_CTRL. On the AST2500 WDT_RESET_WIDTH can consume magic bit patterns
5
For the moment we implement the flash as simple ROM, which
6
to configure push-pull/open-drain and active-high/active-low
6
cannot be reprogrammed by the guest.
7
behaviours and thus needs some special handling in the write path.
7
8
9
As some of the capabilities depend on the SoC version a silicon-rev
10
property is introduced, which is used to guard version-specific
11
behaviour.
12
13
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
10
---
17
include/hw/watchdog/wdt_aspeed.h | 2 +
11
hw/arm/musca.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++---
18
hw/watchdog/wdt_aspeed.c | 93 +++++++++++++++++++++++++++++++++++-----
12
1 file changed, 147 insertions(+), 8 deletions(-)
19
2 files changed, 84 insertions(+), 11 deletions(-)
13
20
14
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
21
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/watchdog/wdt_aspeed.h
16
--- a/hw/arm/musca.c
24
+++ b/include/hw/watchdog/wdt_aspeed.h
17
+++ b/hw/arm/musca.c
25
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedWDTState {
26
uint32_t regs[ASPEED_WDT_REGS_MAX];
27
28
uint32_t pclk_freq;
29
+ uint32_t silicon_rev;
30
+ uint32_t ext_pulse_width_mask;
31
} AspeedWDTState;
32
33
#endif /* ASPEED_WDT_H */
34
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/watchdog/wdt_aspeed.c
37
+++ b/hw/watchdog/wdt_aspeed.c
38
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
39
*/
19
#include "hw/arm/armsse.h"
40
20
#include "hw/boards.h"
41
#include "qemu/osdep.h"
21
#include "hw/core/split-irq.h"
42
+
22
+#include "hw/misc/tz-mpc.h"
43
+#include "qapi/error.h"
23
#include "hw/misc/tz-ppc.h"
44
#include "qemu/log.h"
24
#include "hw/misc/unimp.h"
45
+#include "qemu/timer.h"
25
46
#include "sysemu/watchdog.h"
26
#define MUSCA_NUMIRQ_MAX 96
47
+#include "hw/misc/aspeed_scu.h"
27
#define MUSCA_PPC_MAX 3
48
#include "hw/sysbus.h"
28
+#define MUSCA_MPC_MAX 5
49
-#include "qemu/timer.h"
29
+
50
#include "hw/watchdog/wdt_aspeed.h"
30
+typedef struct MPCInfo MPCInfo;
51
31
52
-#define WDT_STATUS (0x00 / 4)
32
typedef enum MuscaType {
53
-#define WDT_RELOAD_VALUE (0x04 / 4)
33
MUSCA_A,
54
-#define WDT_RESTART (0x08 / 4)
34
@@ -XXX,XX +XXX,XX @@ typedef struct {
55
-#define WDT_CTRL (0x0C / 4)
35
uint32_t init_svtor;
56
+#define WDT_STATUS (0x00 / 4)
36
int sram_addr_width;
57
+#define WDT_RELOAD_VALUE (0x04 / 4)
37
int num_irqs;
58
+#define WDT_RESTART (0x08 / 4)
38
+ const MPCInfo *mpc_info;
59
+#define WDT_CTRL (0x0C / 4)
39
+ int num_mpcs;
60
#define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
40
} MuscaMachineClass;
61
#define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
41
62
#define WDT_CTRL_1MHZ_CLK BIT(4)
42
typedef struct {
63
@@ -XXX,XX +XXX,XX @@
43
MachineState parent;
64
#define WDT_CTRL_WDT_INTR BIT(2)
44
65
#define WDT_CTRL_RESET_SYSTEM BIT(1)
45
ARMSSE sse;
66
#define WDT_CTRL_ENABLE BIT(0)
46
+ /* RAM and flash */
67
+#define WDT_RESET_WIDTH (0x18 / 4)
47
+ MemoryRegion ram[MUSCA_MPC_MAX];
68
+#define WDT_RESET_WIDTH_ACTIVE_HIGH BIT(31)
48
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
69
+#define WDT_POLARITY_MASK (0xFF << 24)
49
SplitIRQ sec_resp_splitter;
70
+#define WDT_ACTIVE_HIGH_MAGIC (0xA5 << 24)
50
TZPPC ppc[MUSCA_PPC_MAX];
71
+#define WDT_ACTIVE_LOW_MAGIC (0x5A << 24)
51
MemoryRegion container;
72
+#define WDT_RESET_WIDTH_PUSH_PULL BIT(30)
52
UnimplementedDeviceState eflash[2];
73
+#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
53
UnimplementedDeviceState qspi;
74
+#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
54
- UnimplementedDeviceState mpc[5];
75
+#define WDT_OPEN_DRAIN_MAGIC (0x8A << 24)
55
+ TZMPC mpc[MUSCA_MPC_MAX];
76
56
UnimplementedDeviceState mhu[2];
77
-#define WDT_TIMEOUT_STATUS (0x10 / 4)
57
UnimplementedDeviceState pwm[3];
78
-#define WDT_TIMEOUT_CLEAR (0x14 / 4)
58
UnimplementedDeviceState i2s;
79
-#define WDT_RESET_WDITH (0x18 / 4)
59
@@ -XXX,XX +XXX,XX @@ typedef struct {
80
+#define WDT_TIMEOUT_STATUS (0x10 / 4)
60
UnimplementedDeviceState pvt;
81
+#define WDT_TIMEOUT_CLEAR (0x14 / 4)
61
UnimplementedDeviceState sdio;
82
62
UnimplementedDeviceState gpio;
83
-#define WDT_RESTART_MAGIC 0x4755
63
+ UnimplementedDeviceState cryptoisland;
84
+#define WDT_RESTART_MAGIC 0x4755
64
} MuscaMachineState;
85
65
86
static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
66
#define TYPE_MUSCA_MACHINE "musca"
87
{
67
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
88
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
68
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
89
}
69
}
90
70
91
+static bool is_ast2500(const AspeedWDTState *s)
71
+typedef enum MPCInfoType {
72
+ MPC_RAM,
73
+ MPC_ROM,
74
+ MPC_CRYPTOISLAND,
75
+} MPCInfoType;
76
+
77
+struct MPCInfo {
78
+ const char *name;
79
+ hwaddr addr;
80
+ hwaddr size;
81
+ MPCInfoType type;
82
+};
83
+
84
+/* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */
85
+static const MPCInfo a_mpc_info[] = { {
86
+ .name = "qspi",
87
+ .type = MPC_ROM,
88
+ .addr = 0x00200000,
89
+ .size = 0x00800000,
90
+ }, {
91
+ .name = "sram",
92
+ .type = MPC_RAM,
93
+ .addr = 0x00000000,
94
+ .size = 0x00200000,
95
+ }
96
+};
97
+
98
+static const MPCInfo b1_mpc_info[] = { {
99
+ .name = "qspi",
100
+ .type = MPC_ROM,
101
+ .addr = 0x00000000,
102
+ .size = 0x02000000,
103
+ }, {
104
+ .name = "sram",
105
+ .type = MPC_RAM,
106
+ .addr = 0x0a400000,
107
+ .size = 0x00080000,
108
+ }, {
109
+ .name = "eflash0",
110
+ .type = MPC_ROM,
111
+ .addr = 0x0a000000,
112
+ .size = 0x00200000,
113
+ }, {
114
+ .name = "eflash1",
115
+ .type = MPC_ROM,
116
+ .addr = 0x0a200000,
117
+ .size = 0x00200000,
118
+ }, {
119
+ .name = "cryptoisland",
120
+ .type = MPC_CRYPTOISLAND,
121
+ .addr = 0x0a000000,
122
+ .size = 0x00200000,
123
+ }
124
+};
125
+
126
+static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
127
+ const char *name, hwaddr size)
92
+{
128
+{
93
+ switch (s->silicon_rev) {
129
+ /*
94
+ case AST2500_A0_SILICON_REV:
130
+ * Create an MPC and the RAM or flash behind it.
95
+ case AST2500_A1_SILICON_REV:
131
+ * MPC 0: eFlash 0
96
+ return true;
132
+ * MPC 1: eFlash 1
97
+ case AST2400_A0_SILICON_REV:
133
+ * MPC 2: SRAM
98
+ case AST2400_A1_SILICON_REV:
134
+ * MPC 3: QSPI flash
99
+ default:
135
+ * MPC 4: CryptoIsland
136
+ * For now we implement the flash regions as ROM (ie not programmable)
137
+ * (with their control interface memory regions being unimplemented
138
+ * stubs behind the PPCs).
139
+ * The whole CryptoIsland region behind its MPC is an unimplemented stub.
140
+ */
141
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
142
+ TZMPC *mpc = opaque;
143
+ int i = mpc - &mms->mpc[0];
144
+ MemoryRegion *downstream;
145
+ MemoryRegion *upstream;
146
+ UnimplementedDeviceState *uds;
147
+ char *mpcname;
148
+ const MPCInfo *mpcinfo = mmc->mpc_info;
149
+
150
+ mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name);
151
+
152
+ switch (mpcinfo[i].type) {
153
+ case MPC_ROM:
154
+ downstream = &mms->ram[i];
155
+ memory_region_init_rom(downstream, NULL, mpcinfo[i].name,
156
+ mpcinfo[i].size, &error_fatal);
100
+ break;
157
+ break;
101
+ }
158
+ case MPC_RAM:
102
+
159
+ downstream = &mms->ram[i];
103
+ return false;
160
+ memory_region_init_ram(downstream, NULL, mpcinfo[i].name,
104
+}
161
+ mpcinfo[i].size, &error_fatal);
105
+
106
static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
107
{
108
AspeedWDTState *s = ASPEED_WDT(opaque);
109
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
110
return 0;
111
case WDT_CTRL:
112
return s->regs[WDT_CTRL];
113
+ case WDT_RESET_WIDTH:
114
+ return s->regs[WDT_RESET_WIDTH];
115
case WDT_TIMEOUT_STATUS:
116
case WDT_TIMEOUT_CLEAR:
117
- case WDT_RESET_WDITH:
118
qemu_log_mask(LOG_UNIMP,
119
"%s: uninmplemented read at offset 0x%" HWADDR_PRIx "\n",
120
__func__, offset);
121
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
122
timer_del(s->timer);
123
}
124
break;
125
+ case WDT_RESET_WIDTH:
126
+ {
127
+ uint32_t property = data & WDT_POLARITY_MASK;
128
+
129
+ if (property && is_ast2500(s)) {
130
+ if (property == WDT_ACTIVE_HIGH_MAGIC) {
131
+ s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
132
+ } else if (property == WDT_ACTIVE_LOW_MAGIC) {
133
+ s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
134
+ } else if (property == WDT_PUSH_PULL_MAGIC) {
135
+ s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
136
+ } else if (property == WDT_OPEN_DRAIN_MAGIC) {
137
+ s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
138
+ }
139
+ }
140
+ s->regs[WDT_RESET_WIDTH] &= ~s->ext_pulse_width_mask;
141
+ s->regs[WDT_RESET_WIDTH] |= data & s->ext_pulse_width_mask;
142
+ break;
162
+ break;
143
+ }
163
+ case MPC_CRYPTOISLAND:
144
case WDT_TIMEOUT_STATUS:
164
+ /* We don't implement the CryptoIsland yet */
145
case WDT_TIMEOUT_CLEAR:
165
+ uds = &mms->cryptoisland;
146
- case WDT_RESET_WDITH:
166
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
147
qemu_log_mask(LOG_UNIMP,
167
+ sizeof(UnimplementedDeviceState),
148
"%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
168
+ TYPE_UNIMPLEMENTED_DEVICE);
149
__func__, offset);
169
+ qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name);
150
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_reset(DeviceState *dev)
170
+ qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size);
151
s->regs[WDT_RELOAD_VALUE] = 0x03EF1480;
171
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
152
s->regs[WDT_RESTART] = 0;
172
+ downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
153
s->regs[WDT_CTRL] = 0;
154
+ s->regs[WDT_RESET_WIDTH] = 0xFF;
155
156
timer_del(s->timer);
157
}
158
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
159
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
160
AspeedWDTState *s = ASPEED_WDT(dev);
161
162
+ if (!is_supported_silicon_rev(s->silicon_rev)) {
163
+ error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
164
+ s->silicon_rev);
165
+ return;
166
+ }
167
+
168
+ switch (s->silicon_rev) {
169
+ case AST2400_A0_SILICON_REV:
170
+ case AST2400_A1_SILICON_REV:
171
+ s->ext_pulse_width_mask = 0xff;
172
+ break;
173
+ case AST2500_A0_SILICON_REV:
174
+ case AST2500_A1_SILICON_REV:
175
+ s->ext_pulse_width_mask = 0xfffff;
176
+ break;
173
+ break;
177
+ default:
174
+ default:
178
+ g_assert_not_reached();
175
+ g_assert_not_reached();
179
+ }
176
+ }
180
+
177
+
181
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
178
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]),
182
179
+ TYPE_TZ_MPC);
183
/* FIXME: This setting should be derived from the SCU hw strapping
180
+ object_property_set_link(OBJECT(mpc), OBJECT(downstream),
184
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
181
+ "downstream", &error_fatal);
185
sysbus_init_mmio(sbd, &s->iomem);
182
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
183
+ /* Map the upstream end of the MPC into system memory */
184
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
185
+ memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream);
186
+ /* and connect its interrupt to the SSE-200 */
187
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
188
+ qdev_get_gpio_in_named(DEVICE(&mms->sse),
189
+ "mpcexp_status", i));
190
+
191
+ g_free(mpcname);
192
+ /* Return the register interface MR for our caller to map behind the PPC */
193
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
+}
195
+
196
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
197
const char *name, hwaddr size)
198
{
199
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
200
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
201
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
202
{ "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
203
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
204
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
205
+ { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 },
206
+ { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 },
207
};
208
209
memory_region_init(container, OBJECT(mms), "musca-device-container", size);
210
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
211
int i;
212
213
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
214
+ assert(mmc->num_mpcs <= MUSCA_MPC_MAX);
215
216
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
217
error_report("This board can only be used with CPU %s",
218
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
219
{ "eflash1", make_unimp_dev, &mms->eflash[1],
220
0x52500000, 0x1000 },
221
{ "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
222
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
223
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
224
- { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
225
- { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
226
+ { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 },
227
+ { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 },
228
+ { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 },
229
+ { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 },
230
{ "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
231
{ "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
232
{ }, /* port 9: unused */
233
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
234
{ }, /* port 11: unused */
235
{ }, /* port 12: unused */
236
{ }, /* port 13: unused */
237
- { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
238
+ { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 },
239
},
240
}, {
241
.name = "apb_ppcexp1",
242
@@ -XXX,XX +XXX,XX @@ static void musca_a_class_init(ObjectClass *oc, void *data)
243
mmc->init_svtor = 0x10200000;
244
mmc->sram_addr_width = 15;
245
mmc->num_irqs = 64;
246
+ mmc->mpc_info = a_mpc_info;
247
+ mmc->num_mpcs = ARRAY_SIZE(a_mpc_info);
186
}
248
}
187
249
188
+static Property aspeed_wdt_properties[] = {
250
static void musca_b1_class_init(ObjectClass *oc, void *data)
189
+ DEFINE_PROP_UINT32("silicon-rev", AspeedWDTState, silicon_rev, 0),
251
@@ -XXX,XX +XXX,XX @@ static void musca_b1_class_init(ObjectClass *oc, void *data)
190
+ DEFINE_PROP_END_OF_LIST(),
252
mmc->init_svtor = 0x10000000;
191
+};
253
mmc->sram_addr_width = 17;
192
+
254
mmc->num_irqs = 96;
193
static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
255
+ mmc->mpc_info = b1_mpc_info;
194
{
256
+ mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info);
195
DeviceClass *dc = DEVICE_CLASS(klass);
196
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
197
dc->reset = aspeed_wdt_reset;
198
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
199
dc->vmsd = &vmstate_aspeed_wdt;
200
+ dc->props = aspeed_wdt_properties;
201
}
257
}
202
258
203
static const TypeInfo aspeed_wdt_info = {
259
static const TypeInfo musca_info = {
204
--
260
--
205
2.7.4
261
2.20.1
206
262
207
263
diff view generated by jsdifflib
1
We currently have some similar code in tlb_fill() and in
1
Wire up the PL031 RTC for the Musca board.
2
arm_cpu_do_unaligned_access() for delivering a data abort or prefetch
3
abort. We're also going to want to do the same thing to handle
4
external aborts. Factor out the common code into a new function
5
deliver_fault().
6
2
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
---
5
---
11
target/arm/op_helper.c | 110 +++++++++++++++++++++++++------------------------
6
hw/arm/musca.c | 26 +++++++++++++++++++++++---
12
1 file changed, 57 insertions(+), 53 deletions(-)
7
1 file changed, 23 insertions(+), 3 deletions(-)
13
8
14
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
15
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/op_helper.c
11
--- a/hw/arm/musca.c
17
+++ b/target/arm/op_helper.c
12
+++ b/hw/arm/musca.c
18
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
13
@@ -XXX,XX +XXX,XX @@
19
return syn;
14
#include "hw/misc/tz-mpc.h"
20
}
15
#include "hw/misc/tz-ppc.h"
21
16
#include "hw/misc/unimp.h"
22
+static void deliver_fault(ARMCPU *cpu, vaddr addr, MMUAccessType access_type,
17
+#include "hw/timer/pl031.h"
23
+ uint32_t fsr, uint32_t fsc, ARMMMUFaultInfo *fi)
18
19
#define MUSCA_NUMIRQ_MAX 96
20
#define MUSCA_PPC_MAX 3
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
UnimplementedDeviceState spi;
23
UnimplementedDeviceState scc;
24
UnimplementedDeviceState timer;
25
- UnimplementedDeviceState rtc;
26
+ PL031State rtc;
27
UnimplementedDeviceState pvt;
28
UnimplementedDeviceState sdio;
29
UnimplementedDeviceState gpio;
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
*/
32
#define SYSCLK_FRQ 40000000
33
34
+static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
24
+{
35
+{
25
+ CPUARMState *env = &cpu->env;
36
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
26
+ int target_el;
37
+ assert(irqno < MUSCA_NUMIRQ_MAX);
27
+ bool same_el;
28
+ uint32_t syn, exc;
29
+
38
+
30
+ target_el = exception_target_el(env);
39
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
31
+ if (fi->stage2) {
32
+ target_el = 2;
33
+ env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4;
34
+ }
35
+ same_el = (arm_current_el(env) == target_el);
36
+
37
+ if (fsc == 0x3f) {
38
+ /* Caller doesn't have a long-format fault status code. This
39
+ * should only happen if this fault will never actually be reported
40
+ * to an EL that uses a syndrome register. Check that here.
41
+ * 0x3f is a (currently) reserved FSC code, in case the constructed
42
+ * syndrome does leak into the guest somehow.
43
+ */
44
+ assert(target_el != 2 && !arm_el_is_aa64(env, target_el));
45
+ }
46
+
47
+ if (access_type == MMU_INST_FETCH) {
48
+ syn = syn_insn_abort(same_el, 0, fi->s1ptw, fsc);
49
+ exc = EXCP_PREFETCH_ABORT;
50
+ } else {
51
+ syn = merge_syn_data_abort(env->exception.syndrome, target_el,
52
+ same_el, fi->s1ptw,
53
+ access_type == MMU_DATA_STORE,
54
+ fsc);
55
+ if (access_type == MMU_DATA_STORE
56
+ && arm_feature(env, ARM_FEATURE_V6)) {
57
+ fsr |= (1 << 11);
58
+ }
59
+ exc = EXCP_DATA_ABORT;
60
+ }
61
+
62
+ env->exception.vaddress = addr;
63
+ env->exception.fsr = fsr;
64
+ raise_exception(env, exc, syn, target_el);
65
+}
40
+}
66
+
41
+
67
/* try to fill the TLB and return an exception if error. If retaddr is
42
/*
68
* NULL, it means that the function was called in C code (i.e. not
43
* Most of the devices in the Musca board sit behind Peripheral Protection
69
* from generated code or from helper.c)
44
* Controllers. These data structures define the layout of which devices
70
@@ -XXX,XX +XXX,XX @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
45
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
71
ret = arm_tlb_fill(cs, addr, access_type, mmu_idx, &fsr, &fi);
46
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
72
if (unlikely(ret)) {
73
ARMCPU *cpu = ARM_CPU(cs);
74
- CPUARMState *env = &cpu->env;
75
- uint32_t syn, exc, fsc;
76
- unsigned int target_el;
77
- bool same_el;
78
+ uint32_t fsc;
79
80
if (retaddr) {
81
/* now we have a real cpu fault */
82
cpu_restore_state(cs, retaddr);
83
}
84
85
- target_el = exception_target_el(env);
86
- if (fi.stage2) {
87
- target_el = 2;
88
- env->cp15.hpfar_el2 = extract64(fi.s2addr, 12, 47) << 4;
89
- }
90
- same_el = arm_current_el(env) == target_el;
91
-
92
if (fsr & (1 << 9)) {
93
/* LPAE format fault status register : bottom 6 bits are
94
* status code in the same form as needed for syndrome
95
@@ -XXX,XX +XXX,XX @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
96
fsc = extract32(fsr, 0, 6);
97
} else {
98
/* Short format FSR : this fault will never actually be reported
99
- * to an EL that uses a syndrome register. Check that here,
100
- * and use a (currently) reserved FSR code in case the constructed
101
- * syndrome does leak into the guest somehow.
102
+ * to an EL that uses a syndrome register. Use a (currently)
103
+ * reserved FSR code in case the constructed syndrome does leak
104
+ * into the guest somehow. deliver_fault will assert that
105
+ * we don't target an EL using the syndrome.
106
*/
107
- assert(target_el != 2 && !arm_el_is_aa64(env, target_el));
108
fsc = 0x3f;
109
}
110
111
- /* For insn and data aborts we assume there is no instruction syndrome
112
- * information; this is always true for exceptions reported to EL1.
113
- */
114
- if (access_type == MMU_INST_FETCH) {
115
- syn = syn_insn_abort(same_el, 0, fi.s1ptw, fsc);
116
- exc = EXCP_PREFETCH_ABORT;
117
- } else {
118
- syn = merge_syn_data_abort(env->exception.syndrome, target_el,
119
- same_el, fi.s1ptw,
120
- access_type == MMU_DATA_STORE, fsc);
121
- if (access_type == MMU_DATA_STORE
122
- && arm_feature(env, ARM_FEATURE_V6)) {
123
- fsr |= (1 << 11);
124
- }
125
- exc = EXCP_DATA_ABORT;
126
- }
127
-
128
- env->exception.vaddress = addr;
129
- env->exception.fsr = fsr;
130
- raise_exception(env, exc, syn, target_el);
131
+ deliver_fault(cpu, addr, access_type, fsr, fsc, &fi);
132
}
133
}
47
}
134
48
135
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
49
+static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
50
+ const char *name, hwaddr size)
51
+{
52
+ PL031State *rtc = opaque;
53
+
54
+ sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031);
55
+ object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal);
56
+ sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39));
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
58
+}
59
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
61
const char *name, hwaddr size)
136
{
62
{
137
ARMCPU *cpu = ARM_CPU(cs);
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
138
CPUARMState *env = &cpu->env;
64
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
139
- int target_el;
65
{ "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
140
- bool same_el;
66
{ "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
141
- uint32_t syn;
67
- { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
142
+ uint32_t fsr, fsc;
68
+ { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 },
143
+ ARMMMUFaultInfo fi = {};
69
{ "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
144
ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
70
{ "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
145
71
{ "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
146
if (retaddr) {
72
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
147
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
73
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
148
cpu_restore_state(cs, retaddr);
74
{ "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
149
}
75
{ "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
150
76
- { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
151
- target_el = exception_target_el(env);
77
+ { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 },
152
- same_el = (arm_current_el(env) == target_el);
78
{ "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
153
-
79
{ "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
154
- env->exception.vaddress = vaddr;
80
},
155
-
156
/* the DFSR for an alignment fault depends on whether we're using
157
* the LPAE long descriptor format, or the short descriptor format
158
*/
159
if (arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
160
- env->exception.fsr = (1 << 9) | 0x21;
161
+ fsr = (1 << 9) | 0x21;
162
} else {
163
- env->exception.fsr = 0x1;
164
- }
165
-
166
- if (access_type == MMU_DATA_STORE && arm_feature(env, ARM_FEATURE_V6)) {
167
- env->exception.fsr |= (1 << 11);
168
+ fsr = 0x1;
169
}
170
+ fsc = 0x21;
171
172
- syn = merge_syn_data_abort(env->exception.syndrome, target_el,
173
- same_el, 0, access_type == MMU_DATA_STORE,
174
- 0x21);
175
- raise_exception(env, EXCP_DATA_ABORT, syn, target_el);
176
+ deliver_fault(cpu, vaddr, access_type, fsr, fsc, &fi);
177
}
178
179
#endif /* !defined(CONFIG_USER_ONLY) */
180
--
81
--
181
2.7.4
82
2.20.1
182
83
183
84
diff view generated by jsdifflib
1
Add a utility function for testing whether the CPU is in Handler
1
Wire up the two PL011 UARTs in the Musca board.
2
mode; this is just a check whether v7m.exception is non-zero, but
3
we do it in several places and it makes the code a bit easier
4
to read to not have to mentally figure out what the test is testing.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-14-git-send-email-peter.maydell@linaro.org
11
---
5
---
12
target/arm/cpu.h | 10 ++++++++--
6
hw/arm/musca.c | 34 +++++++++++++++++++++++++++++-----
13
target/arm/helper.c | 8 ++++----
7
1 file changed, 29 insertions(+), 5 deletions(-)
14
2 files changed, 12 insertions(+), 6 deletions(-)
15
8
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
17
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
11
--- a/hw/arm/musca.c
19
+++ b/target/arm/cpu.h
12
+++ b/hw/arm/musca.c
20
@@ -XXX,XX +XXX,XX @@ static inline int arm_highest_el(CPUARMState *env)
13
@@ -XXX,XX +XXX,XX @@
21
return 1;
14
#include "qemu/error-report.h"
15
#include "qapi/error.h"
16
#include "exec/address-spaces.h"
17
+#include "sysemu/sysemu.h"
18
#include "hw/arm/arm.h"
19
#include "hw/arm/armsse.h"
20
#include "hw/boards.h"
21
+#include "hw/char/pl011.h"
22
#include "hw/core/split-irq.h"
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/misc/tz-ppc.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
26
UnimplementedDeviceState mhu[2];
27
UnimplementedDeviceState pwm[3];
28
UnimplementedDeviceState i2s;
29
- UnimplementedDeviceState uart[2];
30
+ PL011State uart[2];
31
UnimplementedDeviceState i2c[2];
32
UnimplementedDeviceState spi;
33
UnimplementedDeviceState scc;
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
22
}
36
}
23
37
24
+/* Return true if a v7M CPU is in Handler mode */
38
+static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque,
25
+static inline bool arm_v7m_is_handler_mode(CPUARMState *env)
39
+ const char *name, hwaddr size)
26
+{
40
+{
27
+ return env->v7m.exception != 0;
41
+ PL011State *uart = opaque;
42
+ int i = uart - &mms->uart[0];
43
+ int irqbase = 7 + i * 6;
44
+ SysBusDevice *s;
45
+
46
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
47
+ TYPE_PL011);
48
+ qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
49
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
50
+ s = SYS_BUS_DEVICE(uart);
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */
52
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */
53
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */
54
+ sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */
55
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */
56
+ sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
28
+}
58
+}
29
+
59
+
30
/* Return the current Exception Level (as per ARMv8; note that this differs
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
31
* from the ARMv7 Privilege Level).
61
const char *name, hwaddr size)
32
*/
33
static inline int arm_current_el(CPUARMState *env)
34
{
62
{
35
if (arm_feature(env, ARM_FEATURE_M)) {
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
36
- return !((env->v7m.exception == 0) && (env->v7m.control & 1));
64
MemoryRegion *container = &mms->container;
37
+ return arm_v7m_is_handler_mode(env) || !(env->v7m.control & 1);
65
38
}
66
const PPCPortInfo devices[] = {
39
67
- { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
40
if (is_a64(env)) {
68
- { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
41
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
69
+ { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 },
42
}
70
+ { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 },
43
*flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
71
{ "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
44
72
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
45
- if (env->v7m.exception != 0) {
73
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
46
+ if (arm_v7m_is_handler_mode(env)) {
74
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
47
*flags |= ARM_TBFLAG_HANDLER_MASK;
75
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
48
}
76
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
49
77
{ "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
78
- { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
51
index XXXXXXX..XXXXXXX 100644
79
- { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
52
--- a/target/arm/helper.c
80
+ { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 },
53
+++ b/target/arm/helper.c
81
+ { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 },
54
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
82
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
55
* that jumps to magic addresses don't have magic behaviour unless
83
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
56
* we're in Handler mode (compare pseudocode BXWritePC()).
84
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
57
*/
58
- assert(env->v7m.exception != 0);
59
+ assert(arm_v7m_is_handler_mode(env));
60
61
/* In the spec pseudocode ExceptionReturn() is called directly
62
* from BXWritePC() and gets the full target PC value including
63
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
64
* resuming in Thread mode. If that doesn't match what the
65
* exception return type specified then this is a UsageFault.
66
*/
67
- if (return_to_handler == (env->v7m.exception == 0)) {
68
+ if (return_to_handler != arm_v7m_is_handler_mode(env)) {
69
/* Take an INVPC UsageFault by pushing the stack again. */
70
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
71
env->v7m.cfsr |= R_V7M_CFSR_INVPC_MASK;
72
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
73
if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
74
lr |= 4;
75
}
76
- if (env->v7m.exception == 0) {
77
+ if (!arm_v7m_is_handler_mode(env)) {
78
lr |= 8;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
82
* switch_v7m_sp() deals with updating the SPSEL bit in
83
* env->v7m.control, so we only need update the others.
84
*/
85
- if (env->v7m.exception == 0) {
86
+ if (!arm_v7m_is_handler_mode(env)) {
87
switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
88
}
89
env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
90
--
85
--
91
2.7.4
86
2.20.1
92
87
93
88
diff view generated by jsdifflib
1
In the ARM get_phys_addr() code, switch to using the MMUAccessType
1
The region 0x40010000 .. 0x4001ffff and its secure-only alias
2
enum and its MMU_* values rather than int and literal 0/1/2.
2
at 0x50010000... are for per-CPU devices. We implement this by
3
giving each CPU its own container memory region, where the
4
per-CPU devices live. Unfortunately, the alias region which
5
makes devices mapped at 0x4... addresses also appear at 0x5...
6
is only implemented in the overall "all CPUs" container. The
7
effect of this bug is that the CPU_IDENTITY register block appears
8
only at 0x4001f000, but not at the 0x5001f000 alias where it should
9
also appear. Guests (like very recent Arm Trusted Firmware-M)
10
which try to access it at 0x5001f000 will crash.
11
12
Fix this by moving the handling for this alias from the "all CPUs"
13
container to the per-CPU container. (We leave the aliases for
14
0x1... and 0x3... in the overall container, because there are
15
no per-CPU devices there.)
3
16
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
18
Message-id: 20190215180500.6906-1-peter.maydell@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 1501692241-23310-2-git-send-email-peter.maydell@linaro.org
9
---
20
---
10
target/arm/internals.h | 3 ++-
21
include/hw/arm/armsse.h | 2 +-
11
target/arm/helper.c | 30 +++++++++++++++---------------
22
hw/arm/armsse.c | 26 ++++++++++++++++----------
12
2 files changed, 17 insertions(+), 16 deletions(-)
23
2 files changed, 17 insertions(+), 11 deletions(-)
13
24
14
diff --git a/target/arm/internals.h b/target/arm/internals.h
25
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/internals.h
27
--- a/include/hw/arm/armsse.h
17
+++ b/target/arm/internals.h
28
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@ struct ARMMMUFaultInfo {
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
30
MemoryRegion cpu_container[SSE_MAX_CPUS];
31
MemoryRegion alias1;
32
MemoryRegion alias2;
33
- MemoryRegion alias3;
34
+ MemoryRegion alias3[SSE_MAX_CPUS];
35
MemoryRegion sram[MAX_SRAM_BANKS];
36
37
qemu_irq *exp_irqs[SSE_MAX_CPUS];
38
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/armsse.c
41
+++ b/hw/arm/armsse.c
42
@@ -XXX,XX +XXX,XX @@ static bool irq_is_common[32] = {
43
/* 30, 31: reserved */
19
};
44
};
20
45
21
/* Do a page table walk and add page to TLB if possible */
46
-/* Create an alias region of @size bytes starting at @base
22
-bool arm_tlb_fill(CPUState *cpu, vaddr address, int rw, int mmu_idx,
47
+/*
23
+bool arm_tlb_fill(CPUState *cpu, vaddr address,
48
+ * Create an alias region in @container of @size bytes starting at @base
24
+ MMUAccessType access_type, int mmu_idx,
49
* which mirrors the memory starting at @orig.
25
uint32_t *fsr, ARMMMUFaultInfo *fi);
50
*/
26
51
-static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
27
/* Return true if the stage 1 translation regime is using LPAE format page
52
- hwaddr base, hwaddr size, hwaddr orig)
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
53
+static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
29
index XXXXXXX..XXXXXXX 100644
54
+ const char *name, hwaddr base, hwaddr size, hwaddr orig)
30
--- a/target/arm/helper.c
55
{
31
+++ b/target/arm/helper.c
56
- memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
32
@@ -XXX,XX +XXX,XX @@
57
+ memory_region_init_alias(mr, NULL, name, container, orig, size);
33
58
/* The alias is even lower priority than unimplemented_device regions */
34
#ifndef CONFIG_USER_ONLY
59
- memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
35
static bool get_phys_addr(CPUARMState *env, target_ulong address,
60
+ memory_region_add_subregion_overlap(container, base, mr, -1500);
36
- int access_type, ARMMMUIdx mmu_idx,
37
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
38
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
39
target_ulong *page_size, uint32_t *fsr,
40
ARMMMUFaultInfo *fi);
41
42
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
43
- int access_type, ARMMMUIdx mmu_idx,
44
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
45
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
46
target_ulong *page_size_ptr, uint32_t *fsr,
47
ARMMMUFaultInfo *fi);
48
@@ -XXX,XX +XXX,XX @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
49
}
61
}
50
62
51
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
63
static void irq_status_forwarder(void *opaque, int n, int level)
52
- int access_type, ARMMMUIdx mmu_idx)
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
+ MMUAccessType access_type, ARMMMUIdx mmu_idx)
54
{
55
hwaddr phys_addr;
56
target_ulong page_size;
57
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
58
59
static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
60
{
61
- int access_type = ri->opc2 & 1;
62
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
63
uint64_t par64;
64
ARMMMUIdx mmu_idx;
65
int el = arm_current_el(env);
66
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
67
static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
uint64_t value)
69
{
70
- int access_type = ri->opc2 & 1;
71
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
72
uint64_t par64;
73
74
par64 = do_ats_write(env, value, access_type, ARMMMUIdx_S2NS);
75
@@ -XXX,XX +XXX,XX @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
76
static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
77
uint64_t value)
78
{
79
- int access_type = ri->opc2 & 1;
80
+ MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
81
ARMMMUIdx mmu_idx;
82
int secure = arm_is_secure_below_el3(env);
83
84
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
85
}
86
87
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
88
- int access_type, ARMMMUIdx mmu_idx,
89
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
90
hwaddr *phys_ptr, int *prot,
91
target_ulong *page_size, uint32_t *fsr,
92
ARMMMUFaultInfo *fi)
93
@@ -XXX,XX +XXX,XX @@ do_fault:
94
}
95
96
static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
97
- int access_type, ARMMMUIdx mmu_idx,
98
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
99
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
100
target_ulong *page_size, uint32_t *fsr,
101
ARMMMUFaultInfo *fi)
102
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
103
if (pxn && !regime_is_user(env, mmu_idx)) {
104
xn = 1;
105
}
106
- if (xn && access_type == 2)
107
+ if (xn && access_type == MMU_INST_FETCH)
108
goto do_fault;
109
110
if (arm_feature(env, ARM_FEATURE_V6K) &&
111
@@ -XXX,XX +XXX,XX @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
112
}
113
114
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
115
- int access_type, ARMMMUIdx mmu_idx,
116
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
117
hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
118
target_ulong *page_size_ptr, uint32_t *fsr,
119
ARMMMUFaultInfo *fi)
120
@@ -XXX,XX +XXX,XX @@ static inline bool m_is_system_region(CPUARMState *env, uint32_t address)
121
}
122
123
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
124
- int access_type, ARMMMUIdx mmu_idx,
125
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
126
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
127
{
128
ARMCPU *cpu = arm_env_get_cpu(env);
129
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
130
}
131
132
static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
133
- int access_type, ARMMMUIdx mmu_idx,
134
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
135
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
136
{
137
int n;
138
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
139
return true;
140
}
65
}
141
66
142
- if (access_type == 2) {
67
/* Set up the big aliases first */
143
+ if (access_type == MMU_INST_FETCH) {
68
- make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
144
mask = env->cp15.pmsav5_insn_ap;
69
- make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
145
} else {
70
+ make_alias(s, &s->alias1, &s->container, "alias 1",
146
mask = env->cp15.pmsav5_data_ap;
71
+ 0x10000000, 0x10000000, 0x00000000);
147
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
72
+ make_alias(s, &s->alias2, &s->container,
148
* @fsr: set to the DFSR/IFSR value on failure
73
+ "alias 2", 0x30000000, 0x10000000, 0x20000000);
149
*/
74
/* The 0x50000000..0x5fffffff region is not a pure alias: it has
150
static bool get_phys_addr(CPUARMState *env, target_ulong address,
75
* a few extra devices that only appear there (generally the
151
- int access_type, ARMMMUIdx mmu_idx,
76
* control interfaces for the protection controllers).
152
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
77
* We implement this by mapping those devices over the top of this
153
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
78
- * alias MR at a higher priority.
154
target_ulong *page_size, uint32_t *fsr,
79
+ * alias MR at a higher priority. Some of the devices in this range
155
ARMMMUFaultInfo *fi)
80
+ * are per-CPU, so we must put this alias in the per-cpu containers.
156
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
81
*/
157
* fsr with ARM DFSR/IFSR fault register format value on failure.
82
- make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
158
*/
83
-
159
bool arm_tlb_fill(CPUState *cs, vaddr address,
84
+ for (i = 0; i < info->num_cpus; i++) {
160
- int access_type, int mmu_idx, uint32_t *fsr,
85
+ make_alias(s, &s->alias3[i], &s->cpu_container[i],
161
+ MMUAccessType access_type, int mmu_idx, uint32_t *fsr,
86
+ "alias 3", 0x50000000, 0x10000000, 0x40000000);
162
ARMMMUFaultInfo *fi)
87
+ }
163
{
88
164
ARMCPU *cpu = ARM_CPU(cs);
89
/* Security controller */
90
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
165
--
91
--
166
2.7.4
92
2.20.1
167
93
168
94
diff view generated by jsdifflib
Deleted patch
1
M profile cores can never trap on WFI or WFE instructions. Check for
2
M profile in check_wfx_trap() to ensure this.
3
1
4
The existing code will do the right thing for v7M cores because
5
the hcr_el2 and scr_el3 registers will be all-zeroes and so we
6
won't attempt to trap, but when we start setting ARM_FEATURE_V8
7
for v8M cores the v8A handling of SCTLR.nTWE and .nTWI will not
8
give the right results.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1501692241-23310-3-git-send-email-peter.maydell@linaro.org
14
---
15
target/arm/op_helper.c | 5 +++++
16
1 file changed, 5 insertions(+)
17
18
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/op_helper.c
21
+++ b/target/arm/op_helper.c
22
@@ -XXX,XX +XXX,XX @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
23
int cur_el = arm_current_el(env);
24
uint64_t mask;
25
26
+ if (arm_feature(env, ARM_FEATURE_M)) {
27
+ /* M profile cores can never trap WFI/WFE. */
28
+ return 0;
29
+ }
30
+
31
/* If we are currently in EL0 then we need to check if SCTLR is set up for
32
* WFx instructions being trapped to EL1. These trap bits don't exist in v7.
33
*/
34
--
35
2.7.4
36
37
diff view generated by jsdifflib
Deleted patch
1
Remove an out of date comment which says there's only one
2
item in the NVIC container region -- we put systick into its
3
own device object a while back and so now there are two
4
things in the container.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1501692241-23310-6-git-send-email-peter.maydell@linaro.org
10
---
11
hw/intc/armv7m_nvic.c | 4 ----
12
1 file changed, 4 deletions(-)
13
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/armv7m_nvic.c
17
+++ b/hw/intc/armv7m_nvic.c
18
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
19
* 0xd00..0xd3c - SCS registers
20
* 0xd40..0xeff - Reserved or Not implemented
21
* 0xf00 - STIR
22
- *
23
- * At the moment there is only one thing in the container region,
24
- * but we leave it in place to allow us to pull systick out into
25
- * its own device object later.
26
*/
27
memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
28
/* The system register region goes at the bottom of the priority
29
--
30
2.7.4
31
32
diff view generated by jsdifflib
Deleted patch
1
Remove the comment that claims that some MPU_CTRL bits are stored
2
in sctlr_el[1]. This has never been true since MPU_CTRL was added
3
in commit 29c483a50607 -- the comment is a leftover from
4
Michael Davidsaver's original implementation, which I modified
5
not to use sctlr_el[1]; I forgot to delete the comment then.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-7-git-send-email-peter.maydell@linaro.org
11
---
12
target/arm/cpu.h | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
20
uint32_t dfsr; /* Debug Fault Status Register */
21
uint32_t mmfar; /* MemManage Fault Address */
22
uint32_t bfar; /* BusFault Address */
23
- unsigned mpu_ctrl; /* MPU_CTRL (some bits kept in sctlr_el[1]) */
24
+ unsigned mpu_ctrl; /* MPU_CTRL */
25
int exception;
26
} v7m;
27
28
--
29
2.7.4
30
31
diff view generated by jsdifflib
Deleted patch
1
For M profile the XPSR is a similar but not identical format to the
2
A profile CPSR/SPSR. (For instance the Thumb bit is in a different
3
place.) For guest accesses we make the M profile code go through
4
xpsr_read() and xpsr_write() which handle the different layout.
5
However for migration we use cpsr_read() and cpsr_write() to
6
marshal state into and out of the migration data stream. This
7
is pretty confusing and works more by luck than anything else.
8
Make M profile migration use xpsr_read() and xpsr_write() instead.
9
1
10
The most complicated part of this is handling the possibility
11
that the migration source is an older QEMU which hands us a
12
CPSR format value; helpfully we can always tell the two apart.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 1501692241-23310-11-git-send-email-peter.maydell@linaro.org
17
---
18
target/arm/machine.c | 49 ++++++++++++++++++++++++++++++++++---------------
19
1 file changed, 34 insertions(+), 15 deletions(-)
20
21
diff --git a/target/arm/machine.c b/target/arm/machine.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/machine.c
24
+++ b/target/arm/machine.c
25
@@ -XXX,XX +XXX,XX @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
26
uint32_t val = qemu_get_be32(f);
27
28
if (arm_feature(env, ARM_FEATURE_M)) {
29
- /* If the I or F bits are set then this is a migration from
30
- * an old QEMU which still stored the M profile FAULTMASK
31
- * and PRIMASK in env->daif. Set v7m.faultmask and v7m.primask
32
- * accordingly, and then clear the bits so they don't confuse
33
- * cpsr_write(). For a new QEMU, the bits here will always be
34
- * clear, and the data is transferred using the
35
- * vmstate_m_faultmask_primask subsection.
36
- */
37
- if (val & CPSR_F) {
38
- env->v7m.faultmask = 1;
39
- }
40
- if (val & CPSR_I) {
41
- env->v7m.primask = 1;
42
+ if (val & XPSR_EXCP) {
43
+ /* This is a CPSR format value from an older QEMU. (We can tell
44
+ * because values transferred in XPSR format always have zero
45
+ * for the EXCP field, and CPSR format will always have bit 4
46
+ * set in CPSR_M.) Rearrange it into XPSR format. The significant
47
+ * differences are that the T bit is not in the same place, the
48
+ * primask/faultmask info may be in the CPSR I and F bits, and
49
+ * we do not want the mode bits.
50
+ */
51
+ uint32_t newval = val;
52
+
53
+ newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE);
54
+ if (val & CPSR_T) {
55
+ newval |= XPSR_T;
56
+ }
57
+ /* If the I or F bits are set then this is a migration from
58
+ * an old QEMU which still stored the M profile FAULTMASK
59
+ * and PRIMASK in env->daif. For a new QEMU, the data is
60
+ * transferred using the vmstate_m_faultmask_primask subsection.
61
+ */
62
+ if (val & CPSR_F) {
63
+ env->v7m.faultmask = 1;
64
+ }
65
+ if (val & CPSR_I) {
66
+ env->v7m.primask = 1;
67
+ }
68
+ val = newval;
69
}
70
- val &= ~(CPSR_F | CPSR_I);
71
+ /* Ignore the low bits, they are handled by vmstate_m. */
72
+ xpsr_write(env, val, ~XPSR_EXCP);
73
+ return 0;
74
}
75
76
env->aarch64 = ((val & PSTATE_nRW) == 0);
77
@@ -XXX,XX +XXX,XX @@ static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
78
CPUARMState *env = &cpu->env;
79
uint32_t val;
80
81
- if (is_a64(env)) {
82
+ if (arm_feature(env, ARM_FEATURE_M)) {
83
+ /* The low 9 bits are v7m.exception, which is handled by vmstate_m. */
84
+ val = xpsr_read(env) & ~XPSR_EXCP;
85
+ } else if (is_a64(env)) {
86
val = pstate_read(env);
87
} else {
88
val = cpsr_read(env);
89
--
90
2.7.4
91
92
diff view generated by jsdifflib
Deleted patch
1
Make the arm_cpu_dump_state() debug logging handle the M-profile XPSR
2
rather than assuming it's an A-profile CPSR. On M profile the PSR
3
line of a register dump will now look like this:
4
1
5
XPSR=41000000 -Z-- T priv-thread
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 1501692241-23310-12-git-send-email-peter.maydell@linaro.org
11
---
12
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++----------------
13
1 file changed, 40 insertions(+), 18 deletions(-)
14
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
18
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20
ARMCPU *cpu = ARM_CPU(cs);
21
CPUARMState *env = &cpu->env;
22
int i;
23
- uint32_t psr;
24
- const char *ns_status;
25
26
if (is_a64(env)) {
27
aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
28
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29
else
30
cpu_fprintf(f, " ");
31
}
32
- psr = cpsr_read(env);
33
34
- if (arm_feature(env, ARM_FEATURE_EL3) &&
35
- (psr & CPSR_M) != ARM_CPU_MODE_MON) {
36
- ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
37
+ if (arm_feature(env, ARM_FEATURE_M)) {
38
+ uint32_t xpsr = xpsr_read(env);
39
+ const char *mode;
40
+
41
+ if (xpsr & XPSR_EXCP) {
42
+ mode = "handler";
43
+ } else {
44
+ if (env->v7m.control & R_V7M_CONTROL_NPRIV_MASK) {
45
+ mode = "unpriv-thread";
46
+ } else {
47
+ mode = "priv-thread";
48
+ }
49
+ }
50
+
51
+ cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s\n",
52
+ xpsr,
53
+ xpsr & XPSR_N ? 'N' : '-',
54
+ xpsr & XPSR_Z ? 'Z' : '-',
55
+ xpsr & XPSR_C ? 'C' : '-',
56
+ xpsr & XPSR_V ? 'V' : '-',
57
+ xpsr & XPSR_T ? 'T' : 'A',
58
+ mode);
59
} else {
60
- ns_status = "";
61
- }
62
-
63
- cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
64
- psr,
65
- psr & (1 << 31) ? 'N' : '-',
66
- psr & (1 << 30) ? 'Z' : '-',
67
- psr & (1 << 29) ? 'C' : '-',
68
- psr & (1 << 28) ? 'V' : '-',
69
- psr & CPSR_T ? 'T' : 'A',
70
- ns_status,
71
- cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
72
+ uint32_t psr = cpsr_read(env);
73
+ const char *ns_status = "";
74
+
75
+ if (arm_feature(env, ARM_FEATURE_EL3) &&
76
+ (psr & CPSR_M) != ARM_CPU_MODE_MON) {
77
+ ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
78
+ }
79
+
80
+ cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
81
+ psr,
82
+ psr & CPSR_N ? 'N' : '-',
83
+ psr & CPSR_Z ? 'Z' : '-',
84
+ psr & CPSR_C ? 'C' : '-',
85
+ psr & CPSR_V ? 'V' : '-',
86
+ psr & CPSR_T ? 'T' : 'A',
87
+ ns_status,
88
+ cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
89
+ }
90
91
if (flags & CPU_DUMP_FPU) {
92
int numvfpregs = 0;
93
--
94
2.7.4
95
96
diff view generated by jsdifflib
Deleted patch
1
For embedded systems, notably ARM, one common use of ELF
2
file segments is that the 'physical addresses' represent load addresses
3
and the 'virtual addresses' execution addresses, such that
4
the load addresses are packed into ROM or flash, and the
5
relocation and zero-initialization of data is done at runtime.
6
This means that the 'memsz' in the segment header represents
7
the runtime size of the segment, but the size that needs to
8
be loaded is only the 'filesz'. In particular, paddr+memsz
9
may overlap with the next segment to be loaded, as in this
10
example:
11
1
12
0x70000001 off 0x00007f68 vaddr 0x00008150 paddr 0x00008150 align 2**2
13
filesz 0x00000008 memsz 0x00000008 flags r--
14
LOAD off 0x000000f4 vaddr 0x00000000 paddr 0x00000000 align 2**2
15
filesz 0x00000124 memsz 0x00000124 flags r--
16
LOAD off 0x00000218 vaddr 0x00000400 paddr 0x00000400 align 2**3
17
filesz 0x00007d58 memsz 0x00007d58 flags r-x
18
LOAD off 0x00007f70 vaddr 0x20000140 paddr 0x00008158 align 2**3
19
filesz 0x00000a80 memsz 0x000022f8 flags rw-
20
LOAD off 0x000089f0 vaddr 0x20002438 paddr 0x00008bd8 align 2**0
21
filesz 0x00000000 memsz 0x00004000 flags rw-
22
LOAD off 0x000089f0 vaddr 0x20000000 paddr 0x20000000 align 2**0
23
filesz 0x00000000 memsz 0x00000140 flags rw-
24
25
where the segment at paddr 0x8158 has a memsz of 0x2258 and
26
would overlap with the segment at paddr 0x8bd8 if QEMU's loader
27
tried to honour it. (At runtime the segments will not overlap
28
since their vaddrs are more widely spaced than their paddrs.)
29
30
Currently if you try to load an ELF file like this with QEMU then
31
it will fail with an error "rom: requested regions overlap",
32
because we create a ROM image for each segment using the memsz
33
as the size.
34
35
Support ELF files using this scheme, by truncating the
36
zero-initialized part of the segment if it would overlap another
37
segment. This will retain the existing loader behaviour for
38
all ELF files we currently accept, and also accept ELF files
39
which only need 'filesz' bytes to be loaded.
40
41
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
43
Message-id: 1502116754-18867-2-git-send-email-peter.maydell@linaro.org
44
---
45
include/hw/elf_ops.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
46
1 file changed, 48 insertions(+)
47
48
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/elf_ops.h
51
+++ b/include/hw/elf_ops.h
52
@@ -XXX,XX +XXX,XX @@ static int glue(load_elf, SZ)(const char *name, int fd,
53
goto fail;
54
}
55
}
56
+
57
+ /* The ELF spec is somewhat vague about the purpose of the
58
+ * physical address field. One common use in the embedded world
59
+ * is that physical address field specifies the load address
60
+ * and the virtual address field specifies the execution address.
61
+ * Segments are packed into ROM or flash, and the relocation
62
+ * and zero-initialization of data is done at runtime. This
63
+ * means that the memsz header represents the runtime size of the
64
+ * segment, but the filesz represents the loadtime size. If
65
+ * we try to honour the memsz value for an ELF file like this
66
+ * we will end up with overlapping segments (which the
67
+ * loader.c code will later reject).
68
+ * We support ELF files using this scheme by by checking whether
69
+ * paddr + memsz for this segment would overlap with any other
70
+ * segment. If so, then we assume it's using this scheme and
71
+ * truncate the loaded segment to the filesz size.
72
+ * If the segment considered as being memsz size doesn't overlap
73
+ * then we use memsz for the segment length, to handle ELF files
74
+ * which assume that the loader will do the zero-initialization.
75
+ */
76
+ if (mem_size > file_size) {
77
+ /* If this segment's zero-init portion overlaps another
78
+ * segment's data or zero-init portion, then truncate this one.
79
+ * Invalid ELF files where the segments overlap even when
80
+ * only file_size bytes are loaded will be rejected by
81
+ * the ROM overlap check in loader.c, so we don't try to
82
+ * explicitly detect those here.
83
+ */
84
+ int j;
85
+ elf_word zero_start = ph->p_paddr + file_size;
86
+ elf_word zero_end = ph->p_paddr + mem_size;
87
+
88
+ for (j = 0; j < ehdr.e_phnum; j++) {
89
+ struct elf_phdr *jph = &phdr[j];
90
+
91
+ if (i != j && jph->p_type == PT_LOAD) {
92
+ elf_word other_start = jph->p_paddr;
93
+ elf_word other_end = jph->p_paddr + jph->p_memsz;
94
+
95
+ if (!(other_start >= zero_end ||
96
+ zero_start >= other_end)) {
97
+ mem_size = file_size;
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
/* address_offset is hack for kernel images that are
105
linked at the wrong physical address. */
106
if (translate_fn) {
107
--
108
2.7.4
109
110
diff view generated by jsdifflib
Deleted patch
1
Some ELF files have program headers that specify segments that
2
are of zero size. Ignore them, rather than trying to create
3
zero-length ROM blobs for them, because the zero-length blob
4
can falsely trigger the overlapping-ROM-blobs check.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Hua Yanghao <huayanghao@gmail.com>
10
Message-id: 1502116754-18867-3-git-send-email-peter.maydell@linaro.org
11
---
12
include/hw/elf_ops.h | 24 +++++++++++++++++-------
13
1 file changed, 17 insertions(+), 7 deletions(-)
14
15
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/elf_ops.h
18
+++ b/include/hw/elf_ops.h
19
@@ -XXX,XX +XXX,XX @@ static int glue(load_elf, SZ)(const char *name, int fd,
20
*pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
21
}
22
23
- if (load_rom) {
24
- snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
25
-
26
- /* rom_add_elf_program() seize the ownership of 'data' */
27
- rom_add_elf_program(label, data, file_size, mem_size, addr, as);
28
- } else {
29
- cpu_physical_memory_write(addr, data, file_size);
30
+ if (mem_size == 0) {
31
+ /* Some ELF files really do have segments of zero size;
32
+ * just ignore them rather than trying to create empty
33
+ * ROM blobs, because the zero-length blob can falsely
34
+ * trigger the overlapping-ROM-blobs check.
35
+ */
36
g_free(data);
37
+ } else {
38
+ if (load_rom) {
39
+ snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
40
+
41
+ /* rom_add_elf_program() seize the ownership of 'data' */
42
+ rom_add_elf_program(label, data, file_size, mem_size,
43
+ addr, as);
44
+ } else {
45
+ cpu_physical_memory_write(addr, data, file_size);
46
+ g_free(data);
47
+ }
48
}
49
50
total_size += mem_size;
51
--
52
2.7.4
53
54
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
7
hw/arm/armv7m.c | 4 ++--
8
hw/arm/exynos4210.c | 4 ++--
9
hw/arm/highbank.c | 11 +++++++----
10
hw/arm/realview.c | 6 ++++--
11
hw/arm/vexpress.c | 6 ++++--
12
hw/arm/xilinx_zynq.c | 14 ++++++++------
13
6 files changed, 27 insertions(+), 18 deletions(-)
14
15
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/armv7m.c
18
+++ b/hw/arm/armv7m.c
19
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
20
&error_abort);
21
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
22
23
- object_initialize(&s->nvic, sizeof(s->nvic), "armv7m_nvic");
24
+ object_initialize(&s->nvic, sizeof(s->nvic), TYPE_NVIC);
25
qdev_set_parent_bus(DEVICE(&s->nvic), sysbus_get_default());
26
object_property_add_alias(obj, "num-irq",
27
OBJECT(&s->nvic), "num-irq", &error_abort);
28
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
29
cpu_model = "cortex-m3";
30
}
31
32
- armv7m = qdev_create(NULL, "armv7m");
33
+ armv7m = qdev_create(NULL, TYPE_ARMV7M);
34
qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
35
qdev_prop_set_string(armv7m, "cpu-model", cpu_model);
36
object_property_set_link(OBJECT(armv7m), OBJECT(get_system_memory()),
37
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/exynos4210.c
40
+++ b/hw/arm/exynos4210.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "hw/arm/arm.h"
43
#include "hw/loader.h"
44
#include "hw/arm/exynos4210.h"
45
-#include "hw/sd/sd.h"
46
+#include "hw/sd/sdhci.h"
47
#include "hw/usb/hcd-ehci.h"
48
49
#define EXYNOS4210_CHIPID_ADDR 0x10000000
50
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
51
BlockBackend *blk;
52
DriveInfo *di;
53
54
- dev = qdev_create(NULL, "generic-sdhci");
55
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
56
qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
57
qdev_init_nofail(dev);
58
59
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/highbank.c
62
+++ b/hw/arm/highbank.c
63
@@ -XXX,XX +XXX,XX @@
64
#include "exec/address-spaces.h"
65
#include "qemu/error-report.h"
66
#include "hw/char/pl011.h"
67
+#include "hw/ide/ahci.h"
68
+#include "hw/cpu/a9mpcore.h"
69
+#include "hw/cpu/a15mpcore.h"
70
71
#define SMP_BOOT_ADDR 0x100
72
#define SMP_BOOT_REG 0x40
73
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
74
busdev = SYS_BUS_DEVICE(dev);
75
sysbus_mmio_map(busdev, 0, 0xfff12000);
76
77
- dev = qdev_create(NULL, "a9mpcore_priv");
78
+ dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
79
break;
80
case CALXEDA_MIDWAY:
81
- dev = qdev_create(NULL, "a15mpcore_priv");
82
+ dev = qdev_create(NULL, TYPE_A15MPCORE_PRIV);
83
break;
84
}
85
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
86
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
87
sysbus_connect_irq(busdev, 0, pic[18]);
88
pl011_create(0xfff36000, pic[20], serial_hds[0]);
89
90
- dev = qdev_create(NULL, "highbank-regs");
91
+ dev = qdev_create(NULL, TYPE_HIGHBANK_REGISTERS);
92
qdev_init_nofail(dev);
93
busdev = SYS_BUS_DEVICE(dev);
94
sysbus_mmio_map(busdev, 0, 0xfff3c000);
95
@@ -XXX,XX +XXX,XX @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
96
sysbus_create_simple("pl031", 0xfff35000, pic[19]);
97
sysbus_create_simple("pl022", 0xfff39000, pic[23]);
98
99
- sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
100
+ sysbus_create_simple(TYPE_SYSBUS_AHCI, 0xffe08000, pic[83]);
101
102
if (nd_table[0].used) {
103
qemu_check_nic_model(&nd_table[0], "xgmac");
104
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/arm/realview.c
107
+++ b/hw/arm/realview.c
108
@@ -XXX,XX +XXX,XX @@
109
#include "exec/address-spaces.h"
110
#include "qemu/error-report.h"
111
#include "hw/char/pl011.h"
112
+#include "hw/cpu/a9mpcore.h"
113
+#include "hw/intc/realview_gic.h"
114
115
#define SMP_BOOT_ADDR 0xe0000000
116
#define SMP_BOOTREG_ADDR 0x10000030
117
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
118
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
119
120
if (is_mpcore) {
121
- dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
122
+ dev = qdev_create(NULL, is_pb ? TYPE_A9MPCORE_PRIV : "realview_mpcore");
123
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
124
qdev_init_nofail(dev);
125
busdev = SYS_BUS_DEVICE(dev);
126
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
127
} else {
128
uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
129
/* For now just create the nIRQ GIC, and ignore the others. */
130
- dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
131
+ dev = sysbus_create_simple(TYPE_REALVIEW_GIC, gic_addr, cpu_irq[0]);
132
}
133
for (n = 0; n < 64; n++) {
134
pic[n] = qdev_get_gpio_in(dev, n);
135
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/arm/vexpress.c
138
+++ b/hw/arm/vexpress.c
139
@@ -XXX,XX +XXX,XX @@
140
#include "qemu/error-report.h"
141
#include <libfdt.h>
142
#include "hw/char/pl011.h"
143
+#include "hw/cpu/a9mpcore.h"
144
+#include "hw/cpu/a15mpcore.h"
145
146
#define VEXPRESS_BOARD_ID 0x8e0
147
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
148
@@ -XXX,XX +XXX,XX @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
149
memory_region_add_subregion(sysmem, 0x60000000, ram);
150
151
/* 0x1e000000 A9MPCore (SCU) private memory region */
152
- init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic, vms->secure);
153
+ init_cpus(cpu_model, TYPE_A9MPCORE_PRIV, 0x1e000000, pic, vms->secure);
154
155
/* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
156
157
@@ -XXX,XX +XXX,XX @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
158
memory_region_add_subregion(sysmem, 0x80000000, ram);
159
160
/* 0x2c000000 A15MPCore private memory region (GIC) */
161
- init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic, vms->secure);
162
+ init_cpus(cpu_model, TYPE_A15MPCORE_PRIV, 0x2c000000, pic, vms->secure);
163
164
/* A15 daughterboard peripherals: */
165
166
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/arm/xilinx_zynq.c
169
+++ b/hw/arm/xilinx_zynq.c
170
@@ -XXX,XX +XXX,XX @@
171
#include "hw/misc/zynq-xadc.h"
172
#include "hw/ssi/ssi.h"
173
#include "qemu/error-report.h"
174
-#include "hw/sd/sd.h"
175
+#include "hw/sd/sdhci.h"
176
#include "hw/char/cadence_uart.h"
177
+#include "hw/net/cadence_gem.h"
178
+#include "hw/cpu/a9mpcore.h"
179
180
#define NUM_SPI_FLASHES 4
181
#define NUM_QSPI_FLASHES 2
182
@@ -XXX,XX +XXX,XX @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
183
DeviceState *dev;
184
SysBusDevice *s;
185
186
- dev = qdev_create(NULL, "cadence_gem");
187
+ dev = qdev_create(NULL, TYPE_CADENCE_GEM);
188
if (nd->used) {
189
- qemu_check_nic_model(nd, "cadence_gem");
190
+ qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
191
qdev_set_nic_properties(dev, nd);
192
}
193
qdev_init_nofail(dev);
194
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
195
qdev_init_nofail(dev);
196
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
197
198
- dev = qdev_create(NULL, "a9mpcore_priv");
199
+ dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
200
qdev_prop_set_uint32(dev, "num-cpu", 1);
201
qdev_init_nofail(dev);
202
busdev = SYS_BUS_DEVICE(dev);
203
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
204
gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
205
gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
206
207
- dev = qdev_create(NULL, "generic-sdhci");
208
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
209
qdev_init_nofail(dev);
210
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
211
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
212
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
213
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
214
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);
215
216
- dev = qdev_create(NULL, "generic-sdhci");
217
+ dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
218
qdev_init_nofail(dev);
219
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
220
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
221
--
222
2.7.4
223
224
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
When adding a PMU with a userspace irqchip we skip the set-irq
4
stage of device creation. Split the 'create' function into two
5
functions 'init' and 'set-irq' so they may be called separately.
6
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Christoffer Dall <cdall@linaro.org>
9
Message-id: 1500471597-2517-3-git-send-email-drjones@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/kvm_arm.h | 10 ++++++++--
13
hw/arm/virt.c | 11 +++++++++--
14
target/arm/kvm32.c | 8 +++++++-
15
target/arm/kvm64.c | 52 +++++++++++++++++++++++++---------------------------
16
4 files changed, 49 insertions(+), 32 deletions(-)
17
18
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/kvm_arm.h
21
+++ b/target/arm/kvm_arm.h
22
@@ -XXX,XX +XXX,XX @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
23
24
int kvm_arm_vgic_probe(void);
25
26
-int kvm_arm_pmu_create(CPUState *cs, int irq);
27
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq);
28
+int kvm_arm_pmu_init(CPUState *cs);
29
30
#else
31
32
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
33
return 0;
34
}
35
36
-static inline int kvm_arm_pmu_create(CPUState *cs, int irq)
37
+static inline int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
38
+{
39
+ return 0;
40
+}
41
+
42
+static inline int kvm_arm_pmu_init(CPUState *cs)
43
{
44
return 0;
45
}
46
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/virt.c
49
+++ b/hw/arm/virt.c
50
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
51
52
CPU_FOREACH(cpu) {
53
armcpu = ARM_CPU(cpu);
54
- if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU) ||
55
- (kvm_enabled() && !kvm_arm_pmu_create(cpu, PPI(VIRTUAL_PMU_IRQ)))) {
56
+ if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
57
return;
58
}
59
+ if (kvm_enabled()) {
60
+ if (!kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
61
+ return;
62
+ }
63
+ if (!kvm_arm_pmu_init(cpu)) {
64
+ return;
65
+ }
66
+ }
67
}
68
69
if (vms->gic_version == 2) {
70
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/kvm32.c
73
+++ b/target/arm/kvm32.c
74
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_hw_debug_active(CPUState *cs)
75
return false;
76
}
77
78
-int kvm_arm_pmu_create(CPUState *cs, int irq)
79
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
80
+{
81
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
82
+ return 0;
83
+}
84
+
85
+int kvm_arm_pmu_init(CPUState *cs)
86
{
87
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
88
return 0;
89
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/kvm64.c
92
+++ b/target/arm/kvm64.c
93
@@ -XXX,XX +XXX,XX @@ static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
94
return NULL;
95
}
96
97
-static bool kvm_arm_pmu_support_ctrl(CPUState *cs, struct kvm_device_attr *attr)
98
-{
99
- return kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr) == 0;
100
-}
101
-
102
-int kvm_arm_pmu_create(CPUState *cs, int irq)
103
+static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr)
104
{
105
int err;
106
107
- struct kvm_device_attr attr = {
108
- .group = KVM_ARM_VCPU_PMU_V3_CTRL,
109
- .addr = (intptr_t)&irq,
110
- .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
111
- .flags = 0,
112
- };
113
-
114
- if (!kvm_arm_pmu_support_ctrl(cs, &attr)) {
115
- return 0;
116
+ err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
117
+ if (err != 0) {
118
+ return false;
119
}
120
121
- err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
122
+ err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
123
if (err < 0) {
124
fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
125
strerror(-err));
126
abort();
127
}
128
129
- attr.group = KVM_ARM_VCPU_PMU_V3_CTRL;
130
- attr.attr = KVM_ARM_VCPU_PMU_V3_INIT;
131
- attr.addr = 0;
132
- attr.flags = 0;
133
+ return true;
134
+}
135
136
- err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, &attr);
137
- if (err < 0) {
138
- fprintf(stderr, "KVM_SET_DEVICE_ATTR failed: %s\n",
139
- strerror(-err));
140
- abort();
141
- }
142
+int kvm_arm_pmu_init(CPUState *cs)
143
+{
144
+ struct kvm_device_attr attr = {
145
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
146
+ .attr = KVM_ARM_VCPU_PMU_V3_INIT,
147
+ };
148
+
149
+ return kvm_arm_pmu_set_attr(cs, &attr);
150
+}
151
+
152
+int kvm_arm_pmu_set_irq(CPUState *cs, int irq)
153
+{
154
+ struct kvm_device_attr attr = {
155
+ .group = KVM_ARM_VCPU_PMU_V3_CTRL,
156
+ .addr = (intptr_t)&irq,
157
+ .attr = KVM_ARM_VCPU_PMU_V3_IRQ,
158
+ };
159
160
- return 1;
161
+ return kvm_arm_pmu_set_attr(cs, &attr);
162
}
163
164
static inline void set_feature(uint64_t *features, int feature)
165
--
166
2.7.4
167
168
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
Move the in-kernel-irqchip test to only guard the set-irq
4
stage, not the init stage of the PMU. Also add the PMU to
5
the KVM device irq line synchronization to enable its use.
6
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Christoffer Dall <cdall@linaro.org>
9
Message-id: 1500471597-2517-4-git-send-email-drjones@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/virt.c | 3 ++-
14
target/arm/kvm.c | 6 +++++-
15
target/arm/kvm64.c | 3 +--
16
3 files changed, 8 insertions(+), 4 deletions(-)
17
18
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/virt.c
21
+++ b/hw/arm/virt.c
22
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
23
return;
24
}
25
if (kvm_enabled()) {
26
- if (!kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
27
+ if (kvm_irqchip_in_kernel() &&
28
+ !kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ))) {
29
return;
30
}
31
if (!kvm_arm_pmu_init(cpu)) {
32
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/kvm.c
35
+++ b/target/arm/kvm.c
36
@@ -XXX,XX +XXX,XX @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
37
switched_level &= ~KVM_ARM_DEV_EL1_PTIMER;
38
}
39
40
- /* XXX PMU IRQ is missing */
41
+ if (switched_level & KVM_ARM_DEV_PMU) {
42
+ qemu_set_irq(cpu->pmu_interrupt,
43
+ !!(run->s.regs.device_irq_level & KVM_ARM_DEV_PMU));
44
+ switched_level &= ~KVM_ARM_DEV_PMU;
45
+ }
46
47
if (switched_level) {
48
qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ %x\n",
49
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/kvm64.c
52
+++ b/target/arm/kvm64.c
53
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
54
if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
55
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
56
}
57
- if (!kvm_irqchip_in_kernel() ||
58
- !kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
59
+ if (!kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
60
cpu->has_pmu = false;
61
}
62
if (cpu->has_pmu) {
63
--
64
2.7.4
65
66
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jeffery <andrew@aj.id.au>
2
1
3
This is required to configure differences in behaviour between the
4
AST2400 and AST2500 watchdog IPs.
5
6
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/aspeed_soc.c | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/aspeed_soc.c
17
+++ b/hw/arm/aspeed_soc.c
18
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
19
object_initialize(&s->wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
20
object_property_add_child(obj, "wdt[*]", OBJECT(&s->wdt[i]), NULL);
21
qdev_set_parent_bus(DEVICE(&s->wdt[i]), sysbus_get_default());
22
+ qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev",
23
+ sc->info->silicon_rev);
24
}
25
26
object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
27
--
28
2.7.4
29
30
diff view generated by jsdifflib
Deleted patch
1
Call the new cpu_transaction_failed() hook at the places where
2
CPU generated code interacts with the memory system:
3
io_readx()
4
io_writex()
5
get_page_addr_code()
6
1
7
Any access from C code (eg via cpu_physical_memory_rw(),
8
address_space_rw(), ld/st_*_phys()) will *not* trigger CPU exceptions
9
via cpu_transaction_failed(). Handling for transactions failures for
10
this kind of call should be done by using a function which returns a
11
MemTxResult and treating the failure case appropriately in the
12
calling code.
13
14
In an ideal world we would not generate CPU exceptions for
15
instruction fetch failures in get_page_addr_code() but instead wait
16
until the code translation process tried a load and it failed;
17
however that change would require too great a restructuring and
18
redesign to attempt at this point.
19
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
22
---
23
softmmu_template.h | 4 ++--
24
accel/tcg/cputlb.c | 32 ++++++++++++++++++++++++++++++--
25
2 files changed, 32 insertions(+), 4 deletions(-)
26
27
diff --git a/softmmu_template.h b/softmmu_template.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/softmmu_template.h
30
+++ b/softmmu_template.h
31
@@ -XXX,XX +XXX,XX @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
32
uintptr_t retaddr)
33
{
34
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
35
- return io_readx(env, iotlbentry, addr, retaddr, DATA_SIZE);
36
+ return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, DATA_SIZE);
37
}
38
#endif
39
40
@@ -XXX,XX +XXX,XX @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
41
uintptr_t retaddr)
42
{
43
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
44
- return io_writex(env, iotlbentry, val, addr, retaddr, DATA_SIZE);
45
+ return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, DATA_SIZE);
46
}
47
48
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
49
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/accel/tcg/cputlb.c
52
+++ b/accel/tcg/cputlb.c
53
@@ -XXX,XX +XXX,XX @@ static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
54
}
55
56
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
57
+ int mmu_idx,
58
target_ulong addr, uintptr_t retaddr, int size)
59
{
60
CPUState *cpu = ENV_GET_CPU(env);
61
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
62
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
63
uint64_t val;
64
bool locked = false;
65
+ MemTxResult r;
66
67
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
68
cpu->mem_io_pc = retaddr;
69
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
70
qemu_mutex_lock_iothread();
71
locked = true;
72
}
73
- memory_region_dispatch_read(mr, physaddr, &val, size, iotlbentry->attrs);
74
+ r = memory_region_dispatch_read(mr, physaddr,
75
+ &val, size, iotlbentry->attrs);
76
+ if (r != MEMTX_OK) {
77
+ cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD,
78
+ mmu_idx, iotlbentry->attrs, r, retaddr);
79
+ }
80
if (locked) {
81
qemu_mutex_unlock_iothread();
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
84
}
85
86
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
87
+ int mmu_idx,
88
uint64_t val, target_ulong addr,
89
uintptr_t retaddr, int size)
90
{
91
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
92
hwaddr physaddr = iotlbentry->addr;
93
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
94
bool locked = false;
95
+ MemTxResult r;
96
97
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
98
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
99
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
100
qemu_mutex_lock_iothread();
101
locked = true;
102
}
103
- memory_region_dispatch_write(mr, physaddr, val, size, iotlbentry->attrs);
104
+ r = memory_region_dispatch_write(mr, physaddr,
105
+ val, size, iotlbentry->attrs);
106
+ if (r != MEMTX_OK) {
107
+ cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_STORE,
108
+ mmu_idx, iotlbentry->attrs, r, retaddr);
109
+ }
110
if (locked) {
111
qemu_mutex_unlock_iothread();
112
}
113
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
114
MemoryRegion *mr;
115
CPUState *cpu = ENV_GET_CPU(env);
116
CPUIOTLBEntry *iotlbentry;
117
+ hwaddr physaddr;
118
119
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
120
mmu_idx = cpu_mmu_index(env, true);
121
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
122
}
123
qemu_mutex_unlock_iothread();
124
125
+ /* Give the new-style cpu_transaction_failed() hook first chance
126
+ * to handle this.
127
+ * This is not the ideal place to detect and generate CPU
128
+ * exceptions for instruction fetch failure (for instance
129
+ * we don't know the length of the access that the CPU would
130
+ * use, and it would be better to go ahead and try the access
131
+ * and use the MemTXResult it produced). However it is the
132
+ * simplest place we have currently available for the check.
133
+ */
134
+ physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
135
+ cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
136
+ iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
137
+
138
cpu_unassigned_access(cpu, addr, false, true, 0, 4);
139
/* The CPU's unassigned access hook might have longjumped out
140
* with an exception. If it didn't (or there was no hook) then
141
--
142
2.7.4
143
144
diff view generated by jsdifflib
Deleted patch
1
Define a new MachineClass field ignore_memory_transaction_failures.
2
If this is flag is true then the CPU will ignore memory transaction
3
failures which should cause the CPU to take an exception due to an
4
access to an unassigned physical address; the transaction will
5
instead return zero (for a read) or be ignored (for a write). This
6
should be set only by legacy board models which rely on the old
7
RAZ/WI behaviour for handling devices that QEMU does not yet model.
8
New board models should instead use "unimplemented-device" for all
9
memory ranges where the guest will attempt to probe for a device that
10
QEMU doesn't implement and a stub device is required.
11
1
12
We need this for ARM boards, where we're about to implement support for
13
generating external aborts on memory transaction failures. Too many
14
of our legacy board models rely on the RAZ/WI behaviour and we
15
would break currently working guests when their "probe for device"
16
code provoked an external abort rather than a RAZ.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
include/hw/boards.h | 11 +++++++++++
21
include/qom/cpu.h | 7 ++++++-
22
qom/cpu.c | 7 +++++++
23
3 files changed, 24 insertions(+), 1 deletion(-)
24
25
diff --git a/include/hw/boards.h b/include/hw/boards.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/boards.h
28
+++ b/include/hw/boards.h
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
* size than the target architecture's minimum. (Attempting to create
31
* such a CPU will fail.) Note that changing this is a migration
32
* compatibility break for the machine.
33
+ * @ignore_memory_transaction_failures:
34
+ * If this is flag is true then the CPU will ignore memory transaction
35
+ * failures which should cause the CPU to take an exception due to an
36
+ * access to an unassigned physical address; the transaction will instead
37
+ * return zero (for a read) or be ignored (for a write). This should be
38
+ * set only by legacy board models which rely on the old RAZ/WI behaviour
39
+ * for handling devices that QEMU does not yet model. New board models
40
+ * should instead use "unimplemented-device" for all memory ranges where
41
+ * the guest will attempt to probe for a device that QEMU doesn't
42
+ * implement and a stub device is required.
43
*/
44
struct MachineClass {
45
/*< private >*/
46
@@ -XXX,XX +XXX,XX @@ struct MachineClass {
47
bool rom_file_has_mr;
48
int minimum_page_bits;
49
bool has_hotpluggable_cpus;
50
+ bool ignore_memory_transaction_failures;
51
int numa_mem_align_shift;
52
void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes,
53
int nb_nodes, ram_addr_t size);
54
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/qom/cpu.h
57
+++ b/include/qom/cpu.h
58
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
59
* @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
60
* to @trace_dstate).
61
* @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
62
+ * @ignore_memory_transaction_failures: Cached copy of the MachineState
63
+ * flag of the same name: allows the board to suppress calling of the
64
+ * CPU do_transaction_failed hook function.
65
*
66
* State of one CPU core or thread.
67
*/
68
@@ -XXX,XX +XXX,XX @@ struct CPUState {
69
*/
70
bool throttle_thread_scheduled;
71
72
+ bool ignore_memory_transaction_failures;
73
+
74
/* Note that this is accessed at the start of every TB via a negative
75
offset from AREG0. Leave this field at the end so as to make the
76
(absolute value) offset as small as possible. This reduces code
77
@@ -XXX,XX +XXX,XX @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
78
{
79
CPUClass *cc = CPU_GET_CLASS(cpu);
80
81
- if (cc->do_transaction_failed) {
82
+ if (!cpu->ignore_memory_transaction_failures && cc->do_transaction_failed) {
83
cc->do_transaction_failed(cpu, physaddr, addr, size, access_type,
84
mmu_idx, attrs, response, retaddr);
85
}
86
diff --git a/qom/cpu.c b/qom/cpu.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/qom/cpu.c
89
+++ b/qom/cpu.c
90
@@ -XXX,XX +XXX,XX @@
91
#include "exec/cpu-common.h"
92
#include "qemu/error-report.h"
93
#include "sysemu/sysemu.h"
94
+#include "hw/boards.h"
95
#include "hw/qdev-properties.h"
96
#include "trace-root.h"
97
98
@@ -XXX,XX +XXX,XX @@ static void cpu_common_parse_features(const char *typename, char *features,
99
static void cpu_common_realizefn(DeviceState *dev, Error **errp)
100
{
101
CPUState *cpu = CPU(dev);
102
+ Object *machine = qdev_get_machine();
103
+ ObjectClass *oc = object_get_class(machine);
104
+ MachineClass *mc = MACHINE_CLASS(oc);
105
+
106
+ cpu->ignore_memory_transaction_failures =
107
+ mc->ignore_memory_transaction_failures;
108
109
if (dev->hotplugged) {
110
cpu_synchronize_post_init(cpu);
111
--
112
2.7.4
113
114
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
QEMU currently aborts if the user is accidentially trying to
4
do something like this:
5
6
$ aarch64-softmmu/qemu-system-aarch64 -S -M integratorcp -nographic
7
QEMU 2.9.93 monitor - type 'help' for more information
8
(qemu) device_add ast2400
9
Unexpected error in error_set_from_qdev_prop_error()
10
at hw/core/qdev-properties.c:1032:
11
Aborted (core dumped)
12
13
The ast2400 SoC devices are clearly not creatable by the user since
14
they are using the serial_hds and nd_table arrays directly in their
15
realize function, so mark them with user_creatable = false.
16
17
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Cédric Le Goater <clg@kaod.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/aspeed_soc.c | 2 ++
23
1 file changed, 2 insertions(+)
24
25
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/aspeed_soc.c
28
+++ b/hw/arm/aspeed_soc.c
29
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
30
31
sc->info = (AspeedSoCInfo *) data;
32
dc->realize = aspeed_soc_realize;
33
+ /* Reason: Uses serial_hds and nd_table in realize() directly */
34
+ dc->user_creatable = false;
35
}
36
37
static const TypeInfo aspeed_soc_type_info = {
38
--
39
2.7.4
40
41
diff view generated by jsdifflib
Deleted patch
1
From: Pranith Kumar <bobby.prani@gmail.com>
2
1
3
Fix the following warning:
4
5
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: warning: logical not is only applied to the left hand side of this bitwise operator [-Wlogical-not-parentheses]
6
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
7
^ ~
8
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: note: add parentheses after the '!' to evaluate the bitwise operator first
9
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
10
^
11
/home/pranith/qemu/hw/intc/arm_gicv3_kvm.c:296:17: note: add parentheses around left hand side expression to silence this warning
12
if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
13
^
14
15
This logic error meant we were not setting the PTZ
16
bit when we should -- luckily as the comment suggests
17
this wouldn't have had any effects beyond making GIC
18
initialization take a little longer.
19
20
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
21
Message-id: 20170829173226.7625-1-bobby.prani@gmail.com
22
Cc: qemu-stable@nongnu.org
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
hw/intc/arm_gicv3_kvm.c | 2 +-
27
1 file changed, 1 insertion(+), 1 deletion(-)
28
29
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/intc/arm_gicv3_kvm.c
32
+++ b/hw/intc/arm_gicv3_kvm.c
33
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_put(GICv3State *s)
34
kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
35
36
reg64 = c->gicr_pendbaser;
37
- if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
38
+ if (!(c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
39
/* Setting PTZ is advised if LPIs are disabled, to reduce
40
* GIC initialization time.
41
*/
42
--
43
2.7.4
44
45
diff view generated by jsdifflib